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)
@@ -38,31 +40,83 @@ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int __libcpp_popcount(unsigned lo
38
40
return __builtin_popcountll (__x);
39
41
}
40
42
41
- #if _LIBCPP_STD_VER >= 20
43
+ #ifndef _LIBCPP_CXX03_LANG
44
+ // constexpr implementation for C++11 and later
42
45
43
- template <__libcpp_unsigned_integer _Tp>
44
- [[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 ))
46
+ template <class _Tp >
47
+ _LIBCPP_HIDE_FROM_ABI constexpr int __popcount (_Tp __t ) _NOEXCEPT {
48
+ static_assert (is_unsigned<_Tp>::value, " __popcount only works with unsigned types" );
49
+ if constexpr (sizeof (_Tp) <= sizeof (unsigned int )) {
49
50
return std::__libcpp_popcount (static_cast <unsigned int >(__t ));
50
- else if (sizeof (_Tp) <= sizeof (unsigned long ))
51
+ } else if constexpr (sizeof (_Tp) <= sizeof (unsigned long )) {
51
52
return std::__libcpp_popcount (static_cast <unsigned long >(__t ));
52
- else if (sizeof (_Tp) <= sizeof (unsigned long long ))
53
+ } else if constexpr (sizeof (_Tp) <= sizeof (unsigned long long )) {
53
54
return std::__libcpp_popcount (static_cast <unsigned long long >(__t ));
54
- else {
55
+ } else {
56
+ # if _LIBCPP_STD_VER == 11
57
+ // A recursive constexpr implementation for C++11
58
+ return __t != 0 ? std::__libcpp_popcount (static_cast <unsigned long long >(__t )) +
59
+ std::__popcount<_Tp>(__t >> numeric_limits<unsigned long long >::digits)
60
+ : 0 ;
61
+ # else
55
62
int __ret = 0 ;
56
63
while (__t != 0 ) {
57
64
__ret += std::__libcpp_popcount (static_cast <unsigned long long >(__t ));
58
- __t >>= numeric_limits<unsigned long long >::digits;
65
+ __t >>= std:: numeric_limits<unsigned long long >::digits;
59
66
}
60
67
return __ret;
68
+ # endif
61
69
}
62
- # endif // __has_builtin(__builtin_popcountg)
63
70
}
64
71
65
- #endif // _LIBCPP_STD_VER >= 20
72
+ #else
73
+ // Implementation for C++03
74
+
75
+ template < class _Tp , __enable_if_t <is_unsigned<_Tp>::value && sizeof (_Tp) <= sizeof (unsigned int ), int > = 0 >
76
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int __popcount (_Tp __t ) {
77
+ return std::__libcpp_popcount (static_cast <unsigned int >(__t ));
78
+ }
79
+
80
+ template < class _Tp ,
81
+ __enable_if_t <is_unsigned<_Tp>::value && (sizeof (_Tp) > sizeof (unsigned int )) &&
82
+ sizeof (_Tp) <= sizeof (unsigned long ),
83
+ int > = 0 >
84
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int __popcount (_Tp __t ) {
85
+ return std::__libcpp_popcount (static_cast <unsigned long >(__t ));
86
+ }
87
+
88
+ template < class _Tp ,
89
+ __enable_if_t <is_unsigned<_Tp>::value && (sizeof (_Tp) > sizeof (unsigned long )) &&
90
+ sizeof (_Tp) <= sizeof (unsigned long long ),
91
+ int > = 0 >
92
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int __popcount (_Tp __t ) {
93
+ return std::__libcpp_popcount (static_cast <unsigned long long >(__t ));
94
+ }
95
+
96
+ template < class _Tp , __enable_if_t <is_unsigned<_Tp>::value && (sizeof (_Tp) > sizeof (unsigned long long )), int > = 0 >
97
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int __popcount (_Tp __t ) {
98
+ int __ret = 0 ;
99
+ while (__t != 0 ) {
100
+ __ret += std::__libcpp_popcount (static_cast <unsigned long long >(__t ));
101
+ __t >>= std::numeric_limits<unsigned long long >::digits;
102
+ }
103
+ return __ret;
104
+ }
105
+
106
+ #endif // _LIBCPP_CXX03_LANG
107
+
108
+ #if _LIBCPP_STD_VER >= 20
109
+
110
+ template <__libcpp_unsigned_integer _Tp>
111
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr int popcount (_Tp __t ) noexcept {
112
+ # if __has_builtin(__builtin_popcountg)
113
+ return __builtin_popcountg (__t );
114
+ # else
115
+ return std::__popcount (__t );
116
+ # endif
117
+ }
118
+
119
+ #endif
66
120
67
121
_LIBCPP_END_NAMESPACE_STD
68
122
0 commit comments