misc: Add functions for doing popcount and power-of-two checking

Adds two public domain algorithms for determining number of set bits and also
whether a value is a power of two, uses the builtin that is available in GCC
and clang for popcount.
This commit is contained in:
Stephan Diestelhorst 2014-04-24 17:41:26 +01:00
parent ba98d598ae
commit fe98cb6be4

View file

@ -178,4 +178,37 @@ findLsbSet(uint64_t val) {
return lsb;
}
/**
* Checks if a number is a power of two, or zero.
*/
template <class T>
inline bool
isPow2(T v) {
return (v & (v - 1)) == (T)0;
}
/**
* Returns the number of set ones in the provided value.
* PD algorithm from
* http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel
*/
inline int
popCount(uint64_t val) {
#ifndef __has_builtin
#define __has_builtin(foo) 0
#endif
#if defined(__GNUC__) || (defined(__clang__) && __has_builtin(__builtin_popcountl))
return __builtin_popcountl(val);
#else
const uint64_t m1 = 0x5555555555555555; // ..010101b
const uint64_t m2 = 0x3333333333333333; // ..110011b
const uint64_t m4 = 0x0f0f0f0f0f0f0f0f; // ..001111b
const uint64_t sum = 0x0101010101010101;
val -= (val >> 1) & m1; // 2 bits count -> 2 bits
val = (val & m2) + ((val >> 2) & m2); // 4 bits count -> 4 bits
val = (val + (val >> 4)) & m4; // 8 bits count -> 8 bits
return (val * sum) >> 56; // horizontal sum
#endif // defined(__GNUC__) || (defined(__clang__) && __has_builtin(__builtin_popcountl))
}
#endif // __BASE_BITFIELD_HH__