I came across this code while doing research for finding bit parity and have almost no idea why this works. Would anyone be able to enlighten me about its algorithm?
x ^= x >> 16
x ^= x >> 8
x ^= x >> 4
x ^= x >> 2
x ^= x >> 1
x &= 1;
I came across this code while doing research for finding bit parity and have almost no idea why this works. Would anyone be able to enlighten me about its algorithm?
x ^= x >> 16
x ^= x >> 8
x ^= x >> 4
x ^= x >> 2
x ^= x >> 1
x &= 1;
The first line XORs the high 16 bits into the low 16 bits.
The second line XORs the the high half of the low 16 bits into the low half.
etc.
Before the last line, the low bit contains the parity of the initial 32 bits but the other bits contain intermediate results (garbage). The last line clears all of the garbage bits.
Each line takes half of the remaining values and XORs it into the other half. In total, because the XOR operation is associative and commutative, this works out the same as individually XORing each bit together.
You're folding 32-bits to 16-bits, then 16 to 8, ... and finally 2 to 1. So how does folding work? Well let's take a simple example starting with a 4-bit number (shown in binary)
x = 1110
To fold it with x ^= x >> 2
the calculation is
1110 // x three bits, odd parity
0011 // x >> 2
----
xx01 // after the XOR, ignoring the upper bits
At this point, we've folded 4-bits into 2, and we only care about the 2 lsbs which are 01
. Note that the parity has been preserved, there's one bit set, and the parity is still odd. How did that happen? If you examine just the lower two bits, you see
10 // the lower two bits from the 4-bit number
11 // the upper two bits from the 4-bit number
01 // after exclusive-OR
The exclusive-OR converts the first column to 0
, which removes two bits from the result, but keeps the parity the same. And that's why it works. The exclusive-OR reduces the total bit count by 2 any time you have two 1
s in the same column. So if the original bit count was odd, the final bit count will be odd. If the original bit count was even, the final bit count will be even.
Continuing with the example, fold it again with x ^= x >> 1
01 // the lower 2 bits from the previous calculation
00 // shifted by one
--
x1 // after the XOR, ignoring the upper bits
The final piece of the puzzle is the x &= 1
at the end. That throws away all of the upper bits, leaving the one-bit result.