This snippet first fills up all bits below the highest set bit. After v |= v >> 1
the first two bits can be copied and so on. Finally the value is incremented by one.
uint32_t v = ...;
v |= v >> 1;
v |= v >> 2;
v |= v >> 4;
v |= v >> 8;
v |= v >> 16;
v += 1;
The unsigned
part of uint32_t
is important, because otherwise the result would be always 0
, because the sign bit gets extended by the shift operation. If the value is a uint64_t
, then you have to add a further shift, if it is a uint16_t
, then you have to remove a shift.
For an input of 8 the result would be 16. You need to test if the input is a power of two if you don't like that. Knowing that the binary representation of a power of two is one character shorter when you decrement it (8=0b1000, 7=0b111), you can use this guard:
if ((v & (v - 1)) > 0) {
…
}
(Reproduced from memory. Original from https://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2, which contains many more interesting tricks.)