@@ -248,6 +248,35 @@ template <typename T, typename = cpp::enable_if_t<cpp::is_unsigned_v<T>>>
248
248
return value == cpp::numeric_limits<T>::max () ? 0 : countr_zero (value) + 1 ;
249
249
}
250
250
251
+ // / Count number of 1's aka population count or hamming weight.
252
+ // /
253
+ // / Only unsigned integral types are allowed.
254
+ template <typename T, typename = cpp::enable_if_t <cpp::is_unsigned_v<T>>>
255
+ [[nodiscard]] LIBC_INLINE constexpr int count_ones (T value) {
256
+ int count = 0 ;
257
+ for (int i = 0 ; i != cpp::numeric_limits<T>::digits; ++i)
258
+ if ((value >> i) & 0x1 )
259
+ ++count;
260
+ return count;
261
+ }
262
+ #define ADD_SPECIALIZATION (TYPE, BUILTIN ) \
263
+ template <> \
264
+ [[nodiscard]] LIBC_INLINE constexpr int count_ones<TYPE>(TYPE value) { \
265
+ return BUILTIN (value); \
266
+ }
267
+ ADD_SPECIALIZATION (unsigned char , __builtin_popcount)
268
+ ADD_SPECIALIZATION (unsigned short , __builtin_popcount)
269
+ ADD_SPECIALIZATION (unsigned , __builtin_popcount)
270
+ ADD_SPECIALIZATION (unsigned long , __builtin_popcountl)
271
+ ADD_SPECIALIZATION (unsigned long long , __builtin_popcountll)
272
+ // TODO: 128b specializations?
273
+ #undef ADD_SPECIALIZATION
274
+
275
+ template <typename T, typename = cpp::enable_if_t <cpp::is_unsigned_v<T>>>
276
+ [[nodiscard]] LIBC_INLINE constexpr int count_zeros (T value) {
277
+ return count_ones<T>(static_cast <T>(~value));
278
+ }
279
+
251
280
} // namespace LIBC_NAMESPACE::cpp
252
281
253
282
#endif // LLVM_LIBC_SRC___SUPPORT_CPP_BIT_H
0 commit comments