I need to calculate floor(log2(n))
, where n
is positive integer of up to 64 bits.
The value floor(log2(n))
is equal to the bit-length of n
minus 1, hence the title.
I have implemented the following function:
uint8_t floorLog2(uint64_t n)
{
uint8_t res = 0;
uint64_t ONE = 1;
for (uint8_t k = 32; k > 0; k >>= 1)
{
if (n >= (ONE << k))
{
n >>= k;
res |= k;
}
}
return res;
}
It works great, but...
I've realized that for 6-bit numbers, it is less efficient than the straightforward method:
uint8_t floorLog2(uint64_t n)
{
uint8_t res = 0;
while (n > 1)
{
n >>= 1;
res += 1;
}
return res;
}
So I've created a combined version:
uint8_t floorLog2(uint64_t n)
{
uint8_t res = 0;
if (n < 64)
{
while (n > 1)
{
n >>= 1;
res += 1;
}
}
else
{
uint64_t ONE = 1;
for (uint8_t k = 32; k > 0; k >>= 1)
{
if (n >= (ONE << k))
{
n >>= k;
res |= k;
}
}
}
return res;
}
But I don't really like the branch (if
/else
) here.
Since I call this function many times, it impacts the overall performance of my program.
Is there a better approach that I am missing here?