The Most Significant Bit (LSB) is the bit position of the last bit set in a value.
There are many ways to determine the MSB, but the goal is to do that as quickly as possible.
int msbPerformanceJunkie32(u32 x) { static const unsigned int bval[] = { 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4 }; unsigned int r = 0; if (x & 0xFFFF0000) { r += 16 / 1; x >>= 16 / 1; } if (x & 0x0000FF00) { r += 16 / 2; x >>= 16 / 2; } if (x & 0x000000F0) { r += 16 / 4; x >>= 16 / 4; } return r + bval[x]; }
unsigned BSR64(uint64_t x) { return 63-__builtin_clzll(x); }
NOTE: Depending on architecture, the built-in functions include:
#ifdef MICROSOFT_COMPILER u32 msbNative32(u32 val) { unsigned long result; _BitScanReverse(&result, val); return result; } u32 msbNative64(u64 val) { unsigned long result; _BitScanReverse64(&result, val); return result; } #endif // MICROSOFT_COMPILER
u32 msbDeBruijn32(u32 v) { static const int MultiplyDeBruijnBitPosition[32] = { 0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30, 8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31 }; v |= v >> 1; // first round down to one less than a power of 2 v |= v >> 2; v |= v >> 4; v |= v >> 8; v |= v >> 16; return MultiplyDeBruijnBitPosition[( u32 )( v * 0x07C4ACDDU ) >> 27]; }
NOTE: This is very fast.
unsigned int msbLoop32(u32 x) { int r = 0; if (x < 1) return 0; while (x >>= 1) r++; return r; } unsigned int msbLoop64(u64 x) { int r = 0; if (x < 1) return 0; while (x >>= 1) r++; return r; }
NOTE: This is very slow.
#include <intrin.h> unsigned BSR32(unsigned long x) { bsr_idx_t idx; _BitScanReverse(&idx, x); // ignore bool retval return idx; } unsigned BSR64(uint64_t x) { bsr_idx_t idx; _BitScanReverse64(&idx, x); // ignore bool retval return idx; }