Low-Level C & Bit Tricksfoundational
Write code in C to "round up" any number to the next "power of 2", unless the number is already a power of 2. For example, 5 rounds up to 8, 42 rounds up to 64, 128 rounds to 128. When is this algorithm useful?
0 upvotes
Practice with AISoon
The classic bit-smear technique: decrement, propagate (OR) the highest set bit down into every lower bit position to form a contiguous run of 1s, then add 1 to carry up to the next power of two. The initial n-- handles the "already a power of two stays the same" requirement.
c
#include <stdint.h>uint32_t round_up_pow2(uint32_t n) {if (n == 0u) {return 1u; /* define 0 -> 1; smear alone would yield 0 */}n--; /* so exact powers of two are unchanged */n |= n >> 1;n |= n >> 2;n |= n >> 4;n |= n >> 8;n |= n >> 16;n++; /* carry to the next power of two */return n;}
How it works on n = 42 (0b101010): n-- → 41 = 0b101001; after the OR-shifts every bit below the MSB fills in → 0b111111 = 63; n++ → 64. For n = 128 (already a power of two): n-- → 127 = 0b1111111, smear leaves it 127, n++ → 128 (unchanged, as required).
Notes / variants:
- Handle
n == 0explicitly — the smear of 0 is 0, then+1gives 1; pick the convention you want (1 is typical). - For 64-bit inputs, add one more step:
n |= n >> 32;. - CLZ-based alternative (single instruction on capable cores), valid for
n > 1:Usingcuint32_t round_up_pow2_clz(uint32_t n) {if (n <= 1u) return 1u;return 1u << (32 - clz32(n - 1)); /* clz32 from the CLZ answer */}n - 1makes exact powers of two map to themselves.
Where it's useful:
- Memory allocators / buddy allocators / size classes — rounding requests up to power-of-two blocks.
- Hash tables and ring/circular buffers — power-of-two capacity lets you replace
% sizewith a fast& (size - 1)mask. - GPU textures / DMA / alignment — hardware that requires power-of-two dimensions or alignment.
- Geometric growth of dynamic arrays/vectors.
