Bit Hacks
Prev: 02-bentley-rules-for-optimizing-work Next: 04-assembly-language-computer-architecture
Binary Representation
Let be a -bit computer word.
So: 0b10010110 would represent 128 + 16 + 4 + 2 or 150 if it was unsigned.
The signed integer (two’s complement) would be:
So: 0b10010110 would be -128 + 16 + 4 + 2 or -106.
Thus, 0b00000000 would be 0.
And 0b11111111 would be -1.
Thus, x + ~x = -1, or -x = ~x + 1.
C Bitwise Operators are:
&: AND|OR^XOR~NOT<<left shift>>right shift
Set the kth bit:
- Shift and OR:
y = x | (1 << k)
Clear the kth bit:
y = x & ~(1 << k)
Toggle the kth bit:
y = x ^ (1 << k)
Extract a bitfield from a word:
(x & mask) >> shift
Set a bitfield:
x = (x & ~mask) | (y << shift)
Swap without a temporary:
x = x ^ y;
y = x ^ y;
x = x ^ y;Find the minimum of two integers:
if (x < y) r = x;
else r = y;or
r = (x < y) ? x : y;This requires a branch either way. We can do this without a branch:
r = y ^ ((x ^ y) & -(x < y));However branchless paths can be worse than a compiler’s optimizations.
You can round up to a power of two:
uint32_t round_up_pow2(uint32_t v) {
if (v == 0) return 1;
v--;
v |= v >> 1;
v |= v >> 2;
v |= v >> 4;
v |= v >> 8;
v |= v >> 16;
v++;
return v;
}You can use a debrujin sequence to compute log 2 of x if x is a power of 2:
int DEBRUIJN_IDX32[32] = {
0, 1, 28, 2, 29, 14, 24, 3,
30, 22, 20, 15, 25, 17, 4, 8,
31, 27, 13, 23, 21, 19, 16, 7,
26, 12, 18, 6, 11, 5, 10, 9
};
int log2_debruijn32(uint32_t x) {
// Multiply by De Bruijn constant and use high 5 bits as index
uint32_t idx = (x * 0x077CB531u) >> 27;
return DEBRUIJN_IDX32[idx];
}Population Count I
for (int r = 0; x !=0; r++)
x &= x - 1;Or you can use a lookup table:
int count[256] = { 0, 1, 1, 2, 1, 2, 2, 3 ..., 8};
for (int r = 0; x != 0; x >>= 8)
r += count[x & 0xFF];Prev: 02-bentley-rules-for-optimizing-work Next: 04-assembly-language-computer-architecture