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 1s 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.
Related
I've found a piece of code on Stackoverflow and edited it to my needs. source: How to check if value has even parity of bits or odd?
It works like a charm, but I can't get my head around WHY it works.
I tried writing it out, with example byte 0b01101101.
01101101
00000110
-------- ^
01101011
00011010
-------- ^
01110001
00111000
-------- ^
01001001
While my unit test gives the answer; 1
uint8_t check_even_parity(uint8_t value){
value ^= value >> 4;
value ^= value >> 2;
value ^= value >> 1;
return value & 1;
}
Expected is; 0
Actual result when trying to write it out; 01001001
Each step combines two bitsets L and R such that L's parity is merged with R's. R ends up having the same parity as L+R did originally.
In step 1 we take 8 bits and produce a 4-bit number with the same parity as the 8-bit one. In step 2 we produce a 2-bit number with the same parity as the 4. In the last step we produce a 1-bit number with the same parity as the 2. That means in three steps we get a single bit with the same parity as the original 8.
Let me show you what I mean one step at a time.
Let's start with the first step where L is the left 4 bits (0110) and R is the right 4 (1101).
xxxx1101 (R)
xxxx0110 (L)
--------
xxxx1011 (R^L)
I've gone ahead and x'ed out the left half of each number. Those bits don't matter. You'll see why as we progress: fewer and fewer bits will be relevant each step.
L is even and R is odd, which means L+R is odd. R ^= L should therefore leave R with odd parity. Does it? It does indeed. 0110 has two set bits, so R ^= 0110 flips two of R's bits. Flipping an even number of bits won't change parity. R remains odd.
In the second step, L is the left 2 bits (10) and R is the right 2 (11).
xxxxxx11 (R)
xxxxxx10 (L)
--------
xxxxxx01 (L^R)
Now six bits are x'ed out. We're only concerned with two bits from each number.
This time L is odd and R is even. Combined, L+R is odd, so this time we need to flip R's parity. Does R ^= L do that? Again, it does. L has an odd number of bits set, so XORing it will flip an odd number of bits of R, guaranteeing that R's parity is switched. R becomes odd.
In the final step, L and R are just 1 bit apiece.
xxxxxxx1 (L)
xxxxxxx0 (R)
--------
xxxxxxx1 (L^R)
L is 1, R is 0. Just like in the previous steps, we're hoping that R ^= L is odd, and it is. R is odd.
Wonderful. We started with 8 bits with odd parity and by successfully merging two halves together we got down to 1 bit with the same odd parity.
I would like to propose a metaphor that may give some intuition:
Imagine you have 4 cards lying in front of you, which you need to pile up. As a person with 2 hands, you can pick up a card in each hand simultaneously and place them on top of the other 2, then pick up one of the pairs and put it on top of the other.
This piles 4 cards in 2 moves.
Now imagine you need to pile 32 cards and have 16 hands (or more). You can use the same technique: create 16 piles of 2 cards, than 8 piles of 4 cards, 4 piles of 8 cards, 2 piles of 16 cards and finally a single pile of 32 cards.
This piles 32 cards in 5 moves.
Now replace 'pile' with 'xor', 'cards' with 'bits' and 'hands' with the capability of the processor. In 5 shifts and xors, you get the 32 bits of a number xor-ed together, which gives you 0 if the number have even parity and 1 otherwise.
In other words, sets the last 5 bits of integer variable x to zero, also it must be in a portable form.
I was trying to do it with the << operator but that only moves the bits to the left, rather than changing the last 5 bits to zero.
11001011 should be changed to 11000000
Create a mask that blanks out that last n integers if it is bitwise-ANDed with your int:
x &= ~ ((1 << n) - 1);
The expression 1 << n shifts 1 by n places and is effectively two to the power of n. So for 5, you get 32 or 0x00000020. Subtract one and you get a number that as the n lowest bits set, in your case 0x0000001F. Negate the bits with ~ and you get 0xFFFFFFE0, the mask others have posted, too. A bitwise AND with your integer will keep only the bits that the mask and your number have in common, which can only bet bits from the sixth bit on.
For 32-bit integers, you should be able to mask off those bits using the & (bitwise and) operator.
x & 0xFFFFFFE0.
http://en.wikipedia.org/wiki/Bitwise_operation#AND
You can use bitwise and & for this
int x = 0x00cb;
x = x & 0xffe0;
This keeps the higher bits and sets the lower bits to zero.
This question already has answers here:
Computing the Parity
(2 answers)
Closed 9 years ago.
There are already questions about counting how many 1s are there in a number, but this question is about judging whether there is even or odd number of 1s.
Any loop or conditional (including switch) statements are not allowed. Also, division, multiplication or modulus operators should be avoided. To be more specific, we may assume that it's a 32-bits unsigned integer.
Actually I've got an implementation already, but I cannot work out the reason why it works. Any proof of its correctness or any new idea would be very helpful.
int even_ones(unsigned x)
{
x ^= x>>16;
x ^= x>>8;
x ^= x>>4;
x ^= x>>2;
x ^= x>>1;
return !(x & 1);
}
I assume you know what the exclusive or ^ operation does - if two bits are set to the same value, the result is 0 - otherwise it is 1. So when I have two one-bit numbers, A and B, then A^B will be zero if either A and B are both 0, or both 1. In other words - the sum of ones in A and B is even...
Now let's do this two bits at a time: C and D are two-bit numbers. Here are the possible combinations:
C D C^D
00 00 00 even
01 00 01 odd
10 00 10 odd
11 00 11 even
00 01 01 odd
01 01 00 even
10 01 11 even
11 01 10 odd
00 10 10 odd
01 10 11 even
10 10 00 even
11 10 01 odd
00 11 11 even
01 11 10 odd
10 11 01 odd
11 11 00 even
As you can see - the operation in each instance reduces the number of bits by one half, and the resulting number of 1 bits is odd if you started out with an odd number (because pairs of 1s cancel out, but all the others are unchanged).
Now it should be obvious to see why the same thing continues to be true when you start with larger numbers (4 bit, 8 bit, 16 bit). In essence, your algorithm starts with a 32 bit number and splits it into two 16 bit numbers. By getting rid of "double 1's", it reduces the number of bits by half; then operates on the half that remains, and repeats until there is just a single bit left. By testing whether that bit is a one (odd) or zero (even), you get your answer.
In case it's not clear, an operation like x ^= x>>16 actually shifts the top 16 bits into the bottom 16 and produces an exclusive OR there. It doesn't actually clear the top bits, so "a mess is left behind". But the algorithm ignores that mess in what follows. See the following (starting with 8 bits for simplicity):
x = abcdefgh
x >> 4 = 0000abcd
new x = abcdijkl
x >> 2 = 00abcdij
new x = abmnopqr
x >> 1 = 0abmnopq
new x = astuvwxy
In this, the last digit y is the XOR of r and q, which in turn are the XOR of l,j and k,i; these in turn are the XOR of h,d, f,b, g,c, and e,a respectively. As you can see, you ended up with the XOR of all the bits; and as I explained above, that means either "all even" or "all odd", depending on whether the least significant bit is now a 1 or a 0.
I hope this helped.
Here are several variants to quickly compute the parity of a byte or a word. Exactly which method will be fastest depends on your CPU and how fast the different basic operations are relative to one another. So if this is somehow the bottleneck of your application, you should profile each one to find out which one runs best on your target machine.
Your solution is very similar to the "compute parity in parallel" implementation, just without the clever optimization at the end. What's going on here is that at each step, you're XORing half of the bits together with the other half of the bits until you have just one bit left. The parity of a word is 0 if there are an even number of 1's and 1 if there are an odd number of 1's; or equivalently, the parity of a word is just the XOR of all of the bits in the word.
Since the XOR operator is commutative and associative, we can reorder how all of the bits in the word are XORed together. So instead of calculating the XOR of all the bits by individually XORing each bit into the result, we XOR the higher half of the bits with the lower half of the bits, reducing the number of bits we care about by half; when there's one bit left, we're done.
Note that this XOR the most significant 16-bit with the least significant 16-bit.:
x ^= x>>16;
Then the series continues with XOR-ing the 2nd least significant 8-bit with the least significant 4-bit, note that the most significant 16-bit is now simply junk, whatever happens there can be ignored:
x ^= x>>8;
And so on we continue XOR-ing the 2nd least significant 4-bit with the least significant 4-bit until we get to 1-bit; by now every bits except the least significant bit are junk, and the final line just use bitwise and with 1 to get just the least significant bit and flip it for evenness test.
Perhaps, it's easier to follow if you write it this way:
int even_ones(unsigned x)
{
a = (x ^ x>>16) & 0x0000FFFF;
b = (a ^ a>>8) & 0x000000FF;
c = (b ^ b>>4) & 0x0000000F;
d = (c ^ c>>2) & 0x00000003;
e = (d ^ d>>1) & 0x00000001;
return !(e&1);
}
Why does this work? Because XOR is equivalent to bitwise addition without carry.
Hope this helps ::
enum {
EVEN,
ODD
} even_odd;
unsigned int check_even_odd_no_of_ones(unsigned int num)
{
if(num_of_ones(num) & 1)
return ODD;
else
return EVEN;
}
Thank you
I am using C for developing my program and I found out from an example code
unHiByte = unVal >> 8;
What does this mean? If unVal = 250. What could be the value for unHiByte?
>> in programming is a bitwise operation. The operation >> means shift right operation.
So unVal >> 8 means shift right unVal by 8 bits. Shifting the bits to the right can be interpreted as dividing the value by 2.
Hence, unHiByte = unval >> 8 means unHiByte = unVal/(2^8) (divide unVal by 2 eight times)
Without going into the shift operator itself (since that is answered already), here the assumption is that unVal is a two byte variable with a high byte (the upper 8 bits) and a low byte (the lower 8 bits). The intent is to obtain the value produced by ONLY the upper 8 bits and discarding the lower bits.
The shift operator though should easily be learned via any book / tutorial and perhaps was the reason some one down voted the question.
The >> is a bitwise right shift.
It operates on bits. With unHiByte = unVal >> 8; When unVal=250.
Its binary form is 11111010
Right shift means to shift the bits to the right. So when you shift 1111 1010, 8 digits to right you get 0000 0000.
Note: You can easily determine the right shift operation result by dividing the number to the left of >> by 2^(number to right of >>)
So, 250/28= 0
For example: if you have a hex 0x2A63 and you want to take 2A or you want to take 63 out of it, then you will do this.
For example, if we convert 2A63 to binary which is: 0010101001100011. (that is 16 bits, first 8 bits are 2A and the second 8 bits are 63)
The issue is that binary always starts from right. So we have to push the first 8 bits (2A) to the right side to be able to get it.
uint16_t hex = 0x2A63;
uint8_t part2A = (uint8_t)(hex >> 8) // Pushed the first
// eight bits (2A) to right and (63) is gone out of the way. Now we have 0000000000101010
// Now Line 2 returns for us 0x2A which the last 8 bits (2A).
// To get 63 we will do simply:
uint8_t part63 = (uint8_t)hex; // As by default the 63 is on the right most side in the binary.
It is that simple.
If we have a decimal value: 123
and its binary version: 01111011
How can I get four leftmost and the four rightmost bits from this byte into 2 separate int variables?
I mean:
int a = 7; // 0111 (the first four bits from the left)
int b = 11; // 1011 (the first four bits from the right)
Much appreciated!
int x = 123;
int low = x & 0x0F;
int high = (x & 0xF0) >> 4;
This is called masking and shifting. By ANDing with 0xF (which is binary 00001111) we remove the higher four bits. ANDing with 0xF0 (which is binary 11110000) removes the lower four bits. Then (in the latter case), we shift to the right by 4 bits, in effect, pushing away the lower 4 bits and leaving only what were the upper 4 bits.
As #owlstead says in the comments below, there's another way to get the higher bits. Instead of masking the lower bits then shifting, we can just shift.
int high = x >> 4;
Note that we don't need to mask the lower bits since whatever they were, they're gone (we've pushed them out). The above example is clearer since we explicitly zero them out first, but there's no need to do so for this particular example.
But to deal with numbers bigger than 16 bits (int is usually 32 bits), we still need to mask, because we can have the even higher sixteen bits getting in the way!
int high = (x >> 4) & 0x0F;