Bit Hacks
Bit Hacks
Bit Hacks
Integers
David Barina
David Barina
Bit Hacks
1 / 41
unsigned x;
unsigned c;
for(c = 0; x; x >>= 1)
{
c += x & 1;
}
a.k.a. population count, popcount
David Barina
Bit Hacks
2 / 41
for(c = 0; x; c++)
{
x &= x - 1;
}
David Barina
Bit Hacks
3 / 41
x
x-1
x&(x-1)
x
x-1
x&(x-1)
David Barina
Bit Hacks
4 / 41
x
x
x
c
-= x
= (x
= (x
= (x
David Barina
Bit Hacks
5 / 41
x
x
x
c
-= x
= (x
= (x
= (x
David Barina
Bit Hacks
6 / 41
x
x>>1
&~0U/3
0..2
David Barina
11
10
01
00
Bit Hacks
01
01
00
00
=
=
=
=
10
01
01
00
=
=
=
=
2
1
1
0
7 / 41
x
x
x
c
-= x
= (x
= (x
= (x
David Barina
Bit Hacks
8 / 41
x
&~0U/15*3
x
+
x>>2
&~0U/15*3
0..4
David Barina
Bit Hacks
9 / 41
x
x
x
c
-= x
= (x
= (x
= (x
David Barina
Bit Hacks
10 / 41
x>>4
&~0U/255*15
0..8
David Barina
Bit Hacks
11 / 41
x
x
x
c
-= x
= (x
= (x
= (x
David Barina
Bit Hacks
12 / 41
x
~0U/255
David Barina
Bit Hacks
>>24
13 / 41
algorithm
naive
Kernighan
parallel
time
30.943180 ns
17.374596 ns
4.136793 ns
speedup 7.5
David Barina
Bit Hacks
14 / 41
x
x
x
x
x
|=
|=
|=
|=
|=
x
x
x
x
x
>> 1;
>> 2;
>> 4;
>> 8;
>> 16;
a.k.a. copymsb
David Barina
Bit Hacks
15 / 41
x>>1
x|=x>>1
x>>2
x|=x>>2
David Barina
x>>4
x|=x>>4
Bit Hacks
16 / 41
unsigned shift = 1;
while(shift < sizeof(int) * CHAR_BIT)
{
x |= x >> shift;
shift <<= 1;
}
David Barina
Bit Hacks
17 / 41
algorithm
unroll
loop
time
3.687508 ns
3.689689 ns
speedup 1.0
David Barina
Bit Hacks
18 / 41
log2 (x) = 1
x <1
David Barina
Bit Hacks
19 / 41
unsigned x;
unsigned r;
r = (unsigned)ceil(log2((double)x));
r = (unsigned)floor(log2((double)x));
David Barina
Bit Hacks
20 / 41
unsigned r = 0;
while(x >>= 1)
{
r++;
}
David Barina
Bit Hacks
21 / 41
unsigned r;
unsigned shift;
r =
(x >
shift = (x >
shift = (x >
shift = (x >
David Barina
0xFFFF)
0xFF )
0xF
)
0x3
)
<<
<<
<<
<<
4;
3;
2;
1;
x
x
x
x
>>=
>>=
>>=
>>=
Bit Hacks
r;
shift; r |= shift;
shift; r |= shift;
shift; r |= shift;
r |= (x >> 1);
22 / 41
r+=8
x>0xF
x>>4,
r+=4
x>0x3
David Barina
Bit Hacks
x>>2,
r+=2
x>>1,
r+=1
23 / 41
x--;
x = copymsb(x); // next pow2 minus 1
r = popcount(x);
David Barina
Bit Hacks
24 / 41
x
r
David Barina
x = copy MSB
r = popcount
Bit Hacks
25 / 41
David Barina
Bit Hacks
26 / 41
David Barina
Bit Hacks
27 / 41
Bit Hacks
28 / 41
24)
24 + LogTable256[t];
x >> 16)
16 + LogTable256[t];
x >> 8)
8 + LogTable256[t];
LogTable256[x];
Bit Hacks
29 / 41
algorithm
double
naive
fast
popcount
DeBruijn
fast loop
table
floor
64.648230 ns
20.249388 ns
12.542725 ns
8.794856 ns
4.519947 ns
3.784315 ns
1.834092 ns
ceil
64.569502 ns
20.179684 ns
12.199326 ns
8.409071 ns
4.809108 ns
3.716202 ns
1.835536 ns
speedup > 35
David Barina
Bit Hacks
30 / 41
x--;
x = copymsb(x);
x++;
David Barina
Bit Hacks
31 / 41
x = 1 << ceil_log2(x);
David Barina
Bit Hacks
32 / 41
Next power of 2
algorithm
copymsb
log2 table
time
3.976506 ns
2.169806 ns
David Barina
Bit Hacks
33 / 41
Is power of 2
David Barina
Bit Hacks
34 / 41
(x < y) ? x : y
(x > y) ? x : y
David Barina
Bit Hacks
35 / 41
(xy)
0
31 = 0xffffffff
31 = 0x00000000
David Barina
Bit Hacks
36 / 41
algorithm
naive
xor
min
1.509076 ns
2.035053 ns
max
1.503108 ns
1.847343 ns
speedup 0.7
David Barina
Bit Hacks
37 / 41
// stdlib.h
printf("%i\n", abs(+1000000000));
printf("%i\n", abs(-1000000000));
printf("%i\n", abs(-2147483648));
David Barina
Bit Hacks
38 / 41
// stdlib.h
printf("%i\n", abs(+1000000000));
printf("%i\n", abs(-1000000000));
printf("%i\n", abs(-2147483648));
1000000000
1000000000
-2147483648
David Barina
Bit Hacks
38 / 41
Negate (32-bit)
David Barina
Bit Hacks
39 / 41
Negate (32-bit)
David Barina
Bit Hacks
39 / 41
David Barina
Bit Hacks
40 / 41
David Barina
Bit Hacks
40 / 41
Sources
David Barina
Bit Hacks
41 / 41