====== Chess - Programming - MSB (Most Significant Bit) ======
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.
* Due to the number of Chess positions possible, many millions, even a small saving for the lookup of the MSB can provide much further lookups in the same time.
----
===== Using Bit Manipulation =====
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];
}
----
===== Using Built-in for GCC =====
unsigned BSR64(uint64_t x)
{
return 63-__builtin_clzll(x);
}
**NOTE:** Depending on architecture, the built-in functions include:
* __builtin_clz
* __builtin_clzl
* __builtin_clzll
* The returned value is undefined for 0 inputs.
* See https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html
----
===== Using Built-in for Microsoft Compiler =====
#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
----
===== Using de Bruijn for 32-bit =====
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.
* The De Bruijn lookup table needs to be pre-calculated.
* See: https://www.chessprogramming.org/De_Bruijn_Sequence_Generator.
----
===== Using a Loop =====
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.
----
===== Using MS C++ Compiler Built-in =====
#include
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;
}
----
===== References =====
https://www.chessprogramming.org/De_Bruijn_Sequence_Generator.
http://graphics.stanford.edu/~seander/bithacks.html#IntegerLogObvious
https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html
https://docs.microsoft.com/en-us/cpp/intrinsics/bitscanforward-bitscanforward64?redirectedfrom=MSDN&view=msvc-160