|
15 | 15 | #include <__bit/rotate.h>
|
16 | 16 | #include <__concepts/arithmetic.h>
|
17 | 17 | #include <__config>
|
| 18 | +#include <__type_traits/enable_if.h> |
| 19 | +#include <__type_traits/is_unsigned.h> |
18 | 20 | #include <limits>
|
19 | 21 |
|
20 | 22 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
@@ -42,24 +44,68 @@ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int __libcpp_popcount(unsigned lo
|
42 | 44 |
|
43 | 45 | template <__libcpp_unsigned_integer _Tp>
|
44 | 46 | [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr int popcount(_Tp __t) noexcept {
|
45 |
| -# if __has_builtin(__builtin_popcountg) |
46 |
| - return __builtin_popcountg(__t); |
47 |
| -# else // __has_builtin(__builtin_popcountg) |
48 |
| - if (sizeof(_Tp) <= sizeof(unsigned int)) |
49 |
| - return std::__libcpp_popcount(static_cast<unsigned int>(__t)); |
50 |
| - else if (sizeof(_Tp) <= sizeof(unsigned long)) |
51 |
| - return std::__libcpp_popcount(static_cast<unsigned long>(__t)); |
52 |
| - else if (sizeof(_Tp) <= sizeof(unsigned long long)) |
53 |
| - return std::__libcpp_popcount(static_cast<unsigned long long>(__t)); |
54 |
| - else { |
55 |
| - int __ret = 0; |
56 |
| - while (__t != 0) { |
57 |
| - __ret += std::__libcpp_popcount(static_cast<unsigned long long>(__t)); |
58 |
| - __t >>= numeric_limits<unsigned long long>::digits; |
| 47 | + if constexpr (__has_builtin(__builtin_popcountg)) { |
| 48 | + return __builtin_popcountg(__t); |
| 49 | + } else { |
| 50 | + if constexpr (sizeof(_Tp) <= sizeof(unsigned int)) { |
| 51 | + return std::__libcpp_popcount(static_cast<unsigned int>(__t)); |
| 52 | + } else if constexpr (sizeof(_Tp) <= sizeof(unsigned long)) { |
| 53 | + return std::__libcpp_popcount(static_cast<unsigned long>(__t)); |
| 54 | + } else if constexpr (sizeof(_Tp) <= sizeof(unsigned long long)) { |
| 55 | + return std::__libcpp_popcount(static_cast<unsigned long long>(__t)); |
| 56 | + } else { |
| 57 | + int __ret = 0; |
| 58 | + while (__t != 0) { |
| 59 | + __ret += std::__libcpp_popcount(static_cast<unsigned long long>(__t)); |
| 60 | + __t >>= std::numeric_limits<unsigned long long>::digits; |
| 61 | + } |
| 62 | + return __ret; |
59 | 63 | }
|
60 |
| - return __ret; |
61 | 64 | }
|
62 |
| -# endif // __has_builtin(__builtin_popcountg) |
| 65 | +} |
| 66 | + |
| 67 | +#else |
| 68 | + |
| 69 | +template <class _Tp, __enable_if_t<__has_builtin(__builtin_popcountg) && is_unsigned<_Tp>::value, int> = 0> |
| 70 | +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int popcount(_Tp __t) _NOEXCEPT { |
| 71 | + return __builtin_popcountg(__t); |
| 72 | +} |
| 73 | + |
| 74 | +template < |
| 75 | + class _Tp, |
| 76 | + __enable_if_t<!__has_builtin(__builtin_popcountg) && is_unsigned<_Tp>::value && sizeof(_Tp) <= sizeof(unsigned int), |
| 77 | + int> = 0> |
| 78 | +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int popcount(_Tp __t) _NOEXCEPT { |
| 79 | + return std::__libcpp_popcount(static_cast<unsigned int>(__t)); |
| 80 | +} |
| 81 | + |
| 82 | +template < class _Tp, |
| 83 | + __enable_if_t<!__has_builtin(__builtin_popcountg) && is_unsigned<_Tp>::value && |
| 84 | + (sizeof(_Tp) > sizeof(unsigned int)) && sizeof(_Tp) <= sizeof(unsigned long), |
| 85 | + int> = 0 > |
| 86 | +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int popcount(_Tp __t) _NOEXCEPT { |
| 87 | + return std::__libcpp_popcount(static_cast<unsigned long>(__t)); |
| 88 | +} |
| 89 | + |
| 90 | +template < class _Tp, |
| 91 | + __enable_if_t<!__has_builtin(__builtin_popcountg) && is_unsigned<_Tp>::value && |
| 92 | + (sizeof(_Tp) > sizeof(unsigned long)) && sizeof(_Tp) <= sizeof(unsigned long long), |
| 93 | + int> = 0 > |
| 94 | +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int popcount(_Tp __t) _NOEXCEPT { |
| 95 | + return std::__libcpp_popcount(static_cast<unsigned long long>(__t)); |
| 96 | +} |
| 97 | + |
| 98 | +template < class _Tp, |
| 99 | + __enable_if_t<!__has_builtin(__builtin_popcountg) && is_unsigned<_Tp>::value && |
| 100 | + (sizeof(_Tp) > sizeof(unsigned long long)), |
| 101 | + int> = 0 > |
| 102 | +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 int popcount(_Tp __t) _NOEXCEPT { |
| 103 | + int __ret = 0; |
| 104 | + while (__t != 0) { |
| 105 | + __ret += std::__libcpp_popcount(static_cast<unsigned long long>(__t)); |
| 106 | + __t >>= numeric_limits<unsigned long long>::digits; |
| 107 | + } |
| 108 | + return __ret; |
63 | 109 | }
|
64 | 110 |
|
65 | 111 | #endif // _LIBCPP_STD_VER >= 20
|
|
0 commit comments