A slight improvement in Guffa's answer ... Since the amount you add to the result always has the power of two bit operations, it can lead to a slight improvement in some architectures. Also, since our context is bit patterns, it is a bit more readable to use hexadecimal. In this case, it is useful to shift the arithmetic to the power of 2.
int bits = 0; if (n > 0xffff) { n >>= 16; bits = 0x10; } if (n > 0xff) { n >>= 8; bits |= 0x8; } if (n > 0xf) { n >>= 4; bits |= 0x4; } if (n > 0x3) { n >>= 2; bits |= 0x2; } if (n > 0x1) { bits |= 0x1; }
Next, a check should be added for n == 0, since the above will give the result 0, and Log (0) - undefined (regardless of the base).
In the ARM assembly, this algorithm creates a very compact code, since the branch after comparison can be eliminated using conditional instructions that avoid flushing the pipeline. For example:
if (n > 0xff) { n >>= 8; bits |= 0x8; }
becomes (let R0 = n, R1 = bit)
CMP R0, $0xff MOVHI R0, R0, LSR $8 ORRHI R1, R1, $0x8
user3059763 Dec 03 '13 at 3:23 2013-12-03 03:23
source share