You can simply count the number of start or end zero bits, because any exact power of the two is represented as one 1 bit, with all other bits 0. Many CPUs have special instructions for this, and compilers are like that since gcc has built-in functions for these operations, which are compiled into a single command on the respective architectures.
If you have efficient clz ("count leading zeroes"), the log2 implementation might look like this:
int32_t ilog2(uint32_t x) { return sizeof(uint32_t) * CHAR_BIT - clz(x) - 1; }
(Note: returns -1 for ilog2(0) .)
When using a gcc or gcc-compatible compiler, you can simply define clz as follows:
#define clz(x) __builtin_clz(x)
Microsoft has something similar: BitScanReverse .
Note that it is more convenient to count trailing zeros (using the ctz instruction), but the clz instruction clz more widely available on various processor architectures .
An additional advantage of using clz rather than ctz is that you get floor(log2(x)) for values โโwithout power 2, which makes your ilog2 function more useful than if you used ctz , which only works for exact degrees-2 .
See also: Search for the first bit of a set in a binary number .
source share