1515#include < __bit/rotate.h>
1616#include < __concepts/arithmetic.h>
1717#include < __config>
18+ #include < __type_traits/enable_if.h>
19+ #include < __type_traits/is_unsigned.h>
1820#include < limits>
1921
2022#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
@@ -38,31 +40,83 @@ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int __libcpp_popcount(unsigned lo
3840 return __builtin_popcountll (__x);
3941}
4042
41- #if _LIBCPP_STD_VER >= 20
42-
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 ))
43+ #if _LIBCPP_STD_VER >= 14
44+ // constexpr implementation for C++14 and later
45+ template <class _Tp >
46+ _LIBCPP_HIDE_FROM_ABI constexpr int __popcount (_Tp __t ) _NOEXCEPT {
47+ static_assert (is_unsigned<_Tp>::value, " __popcount only works with unsigned types" );
48+ if constexpr (sizeof (_Tp) <= sizeof (unsigned int )) {
4949 return std::__libcpp_popcount (static_cast <unsigned int >(__t ));
50- else if (sizeof (_Tp) <= sizeof (unsigned long ))
50+ } else if constexpr (sizeof (_Tp) <= sizeof (unsigned long )) {
5151 return std::__libcpp_popcount (static_cast <unsigned long >(__t ));
52- else if (sizeof (_Tp) <= sizeof (unsigned long long ))
52+ } else if constexpr (sizeof (_Tp) <= sizeof (unsigned long long )) {
5353 return std::__libcpp_popcount (static_cast <unsigned long long >(__t ));
54- else {
54+ } else {
5555 int __ret = 0 ;
5656 while (__t != 0 ) {
5757 __ret += std::__libcpp_popcount (static_cast <unsigned long long >(__t ));
58- __t >>= numeric_limits<unsigned long long >::digits;
58+ __t >>= std:: numeric_limits<unsigned long long >::digits;
5959 }
6060 return __ret;
6161 }
62- # endif // __has_builtin(__builtin_popcountg)
6362}
6463
65- #endif // _LIBCPP_STD_VER >= 20
64+ #else
65+ // constexpr implementation for C++11
66+
67+ template < class _Tp , __enable_if_t <is_unsigned<_Tp>::value && sizeof (_Tp) <= sizeof (unsigned int ), int > = 0 >
68+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int __popcount (_Tp __t ) {
69+ return std::__libcpp_popcount (static_cast <unsigned int >(__t ));
70+ }
71+
72+ template < class _Tp ,
73+ __enable_if_t <is_unsigned<_Tp>::value && (sizeof (_Tp) > sizeof (unsigned int )) &&
74+ sizeof (_Tp) <= sizeof (unsigned long ),
75+ int > = 0 >
76+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int __popcount (_Tp __t ) {
77+ return std::__libcpp_popcount (static_cast <unsigned long >(__t ));
78+ }
79+
80+ template < class _Tp ,
81+ __enable_if_t <is_unsigned<_Tp>::value && (sizeof (_Tp) > sizeof (unsigned long )) &&
82+ sizeof (_Tp) <= sizeof (unsigned long long ),
83+ int > = 0 >
84+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int __popcount (_Tp __t ) {
85+ return std::__libcpp_popcount (static_cast <unsigned long long >(__t ));
86+ }
87+
88+ template < class _Tp , __enable_if_t <is_unsigned<_Tp>::value && (sizeof (_Tp) > sizeof (unsigned long long )), int > = 0 >
89+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int __popcount (_Tp __t ) {
90+ # if _LIBCPP_STD_VER == 11
91+ // A recursive constexpr implementation for C++11
92+ return __t != 0 ? std::__libcpp_popcount (static_cast <unsigned long long >(__t )) +
93+ std::__popcount<_Tp>(__t >> numeric_limits<unsigned long long >::digits)
94+ : 0 ;
95+ # else
96+ int __ret = 0 ;
97+ while (__t != 0 ) {
98+ __ret += std::__libcpp_popcount (static_cast <unsigned long long >(__t ));
99+ __t >>= std::numeric_limits<unsigned long long >::digits;
100+ }
101+ return __ret;
102+ }
103+ # endif // _LIBCPP_STD_VER == 11
104+ }
105+
106+ #endif // _LIBCPP_STD_VER >= 14
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
66120
67121_LIBCPP_END_NAMESPACE_STD
68122
0 commit comments