#include "bit_utils.h" #if defined(__GNUC__) && defined(__BMI2__) #include #include // _pdep_u32 #endif int bitParity(uint32_t x) { #ifdef __GNUC__ return __builtin_parity(x); #else bool p = static_cast(x); while (x &= x - 1) { p = !p; } return static_cast(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(65535))) << 4; x >>= 16 * empty; ctz += (empty = !(x & static_cast( 255))) << 3; x >>= 8 * empty; ctz += (empty = !(x & static_cast( 15))) << 2; x >>= 4 * empty; ctz += (empty = !(x & static_cast( 3))) << 1; x >>= 2 * empty; ctz += (empty = !(x & static_cast( 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)); }