83 lines
2.0 KiB
C++
83 lines
2.0 KiB
C++
#include "bit_utils.h"
|
|
|
|
#if defined(__GNUC__) && defined(__BMI2__)
|
|
#include <x86intrin.h>
|
|
#include <bmi2intrin.h> // _pdep_u32
|
|
#endif
|
|
|
|
|
|
int bitParity(uint32_t x) {
|
|
#ifdef __GNUC__
|
|
return __builtin_parity(x);
|
|
#else
|
|
bool p = static_cast<bool>(x);
|
|
while (x &= x - 1) {
|
|
p = !p;
|
|
}
|
|
return static_cast<int>(p);
|
|
#endif
|
|
}
|
|
|
|
int bitCount(uint32_t x) {
|
|
#ifdef __GNUC__
|
|
return __builtin_popcount(x); // `POPulation COUNT`
|
|
#else
|
|
int count = 0; // counts set bits
|
|
|
|
// increment count until there are no bits set in x
|
|
for (; x; count++) {
|
|
x &= x - 1; // unset least significant bit
|
|
}
|
|
|
|
return count;
|
|
#endif
|
|
}
|
|
|
|
int bitScanLS(uint32_t x) {
|
|
#ifdef __GNUC__
|
|
return __builtin_ctz(x); // Count Trailing Zeros
|
|
#else
|
|
// result storing the Count of Trailing Zeros
|
|
int ctz = 0;
|
|
|
|
// boolean variable storing if a bit has not found (search area is empty)
|
|
bool empty;
|
|
|
|
// logarithmic search for LSB bit index (-1)
|
|
ctz += (empty = !(x & static_cast<uint32_t>(65535))) << 4;
|
|
x >>= 16 * empty;
|
|
ctz += (empty = !(x & static_cast<uint32_t>( 255))) << 3;
|
|
x >>= 8 * empty;
|
|
ctz += (empty = !(x & static_cast<uint32_t>( 15))) << 2;
|
|
x >>= 4 * empty;
|
|
ctz += (empty = !(x & static_cast<uint32_t>( 3))) << 1;
|
|
x >>= 2 * empty;
|
|
ctz += (empty = !(x & static_cast<uint32_t>( 1)));
|
|
|
|
return ctz;
|
|
#endif
|
|
}
|
|
|
|
uint32_t bitDeposit(uint32_t val, uint32_t mask) {
|
|
#if (defined(__GNUC__) && defined(__BMI2__))
|
|
return _pdep_u32(val, mask);
|
|
#else
|
|
uint32_t res = 0;
|
|
for (uint32_t pos = 1; mask; pos <<= 1) {
|
|
if (val & pos) {
|
|
res |= mask & -mask;
|
|
}
|
|
mask &= mask - 1;
|
|
}
|
|
return res;
|
|
#endif
|
|
}
|
|
|
|
uint32_t bitNextPerm(uint32_t val) {
|
|
// Sets all least significant 0-bits of val to 1
|
|
uint32_t t = val | (val - 1);
|
|
// Next set to 1 the most significant bit to change,
|
|
// set to 0 the least significant ones, and add the necessary 1 bits.
|
|
return (t + 1) | (((~t & -~t) - 1) >> (bitScanLS(val) + 1));
|
|
}
|