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.
Related
I need explanation what exaclty means this operation in C language.
I know this is doing a bit shift to left by n, but I don't understand this code:
| (a >> (32 - n)).
This is full code below:
uint32_t rot_l(uint32_t a, uint8_t n)
{
return (a << n) | (a >> (32 - n));
}
Please help me understand this.
Given a sample 32 bit integer a:
11000000001111111110000000000000
a << n will shift the entire sequence to the left by n bits. Any bits that are shifted to the left of the first bit are removed. Any new bits added on the right are 0. So, say we shift this by n = 3, we'll get:
00000001111111110000000000000000
Then, a >> (32 - n) will shift a to the right by 32 - n. Note that 32 is the size in bits of a, so 32 - n will shift all the bits that didn't get truncated to the right. For n = 3 again, we'll get:
00000000000000000000000000000110
(the 110 is the first 3 most significant bits of n)
Finally, the | is the bitwise or operator, and this will compute the result of every using or on every bit in the two results.
00000001111111110000000000000000
00000000000000000000000000000110
================================ |
00000001111111110000000000000110
So what happens is, first the bits of a are shifted to the left by n. This results in the n most significant bits being truncated. Then these n most signifcant bits are shifted all the way to the right, to fill up the space that was originally filled with 0 from the left shift.
The result is then combined using the |. This simulates the entire string of bits in the integer being rotated to the left. This makes sense given the name of the function is rot_l :)
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.
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
Reading the book "C - A reference manual (Fifth Edition)", I stumbled upon this piece of code (each integer in the SET is represented by a bit position):
typedef unsigned int SET;
#define emptyset ((SET) 0)
#define first_set_of_n_elements(n) (SET)((1<<(n))-1)
/* next_set_of_n_elements(s): Given a set of n elements,
produce a new set of n elements. If you start with the
result of first_set_of_n_elements(k)/ and then at each
step apply next_set_of_n_elements to the previous result,
and keep going until a set is obtained containing m as a
member, you will have obtained a set representing all
possible ways of choosing k things from m things. */
SET next_set_of_n_elements(SET x) {
/* This code exploits many unusual properties of unsigned arithmetic. As an illustration:
if x == 001011001111000, then
smallest == 000000000001000
ripple == 001011010000000
new_smallest == 000000010000000
ones == 000000000000111
returned value == 001011010000111
The overall idea is that you find the rightmost
contiguous group of 1-bits. Of that group, you slide the
leftmost 1-bit to the left one place, and slide all the
others back to the extreme right.
(This code was adapted from HAKMEM.) */
SET smallest, ripple, new_smallest, ones;
if (x == emptyset) return x;
smallest = (x & -x);
ripple = x + smallest;
new_smallest = (ripple & -ripple);
ones = ((new_smallest / smallest) >> 1) -1;
return (ripple | ones);
}
I'm lost at the calculation of 'ones', and it's significance in the calculation. Although I can understand the calculation mathematically, I cannot understand why this works, or how.
On a related note, the authors of the book claim that the calculation for first_set_of_n_elements "exploits the properties of unsigned subtractions". How is (2^n)-1 an "exploit"?
The smallest computation gets the first non-0 bit of your int. How does it works ?
Let n be the bit length of your int. The opposite of a number x (bits bn-1...b0) is computed in a way that when you sum x to -x, you will get 2n. Since your integer is only n-bit long, the resulting bit is discarded and you obtain 0.
Now, let b'n-1...b'0 be the binary representation of -x.
Since x+(-x) must be equal to 2n, when you meet the first bit 1 of x (say at position i), the related -x bit will also be set to 1 and when adding the numbers, you'll get a carry.
To obtain the 2n, this carry must propagate through all the bits until the end of the bit sequence of your int. Thus, the bit of -x at each position j with i < j < n follows the properties below :
bj + b'j + 1 = 10(binary)
Then, from the above we can infer that :
bj = NOT(b'j) and thus, that bj & b'j = 0
On the other hand, the bits b'j of -x located at a position j such that 0 <= j < i are ruled by what follows :
bj + b'j = 0 or 10
Since all the related bj are set to 0, the only option is b'j = 0
Thus, the only bit that is 1 in both x and -x is the one at position i
In your example :
x = 001011001111000
-x = 110100110001000
Thus,
0.0.1.0.1.1.0.0.1.1.1.1.0.0.0
1.1.0.1.0.0.1.1.0.0.0.1.0.0.0 AND
\=====================/
0.0.0.0.0.0.0.0.0.0.1.0.0.0
The ripple then turns every contiguous "1" after position i (bit i included) to 0, and the first following 0 bit to 1 (due to the carry propagation). That's why you ripple is :
r(x) = 0.0.1.0.1.1.0.1.0.0.0.0.0.0.0
Ones is computed as the division of smallest(r(x)) over smallest(x). Since smallest(x) is an integer with only a single bit set to 1 at position i, you have :
(smallest(r(x)) / smallest(x)) >> 1 = smallest(r(x)) >>(i+1)
The resulting integer has also only one bit set to 1, at say index p, thus, substract -1 to this value will get you an integer ones such that :
For each j such that 0 <= j < p,
onesj = 1
For each j such that p <= j < n,
onesj = 0
Finally, the return value is the integer such that :
The first subsequence of 1-bit of the argument is set to 0.
All the 0-bit before the subsequence are set to 1.
The first 0-bit after the subsequence is set to 1.
The remaining bits are left unchanged
Then, I can't explain the remaining part since I did not understand the sentence :
a set is obtained containing m as a member
First of all, this code is rather obscure and doesn't look like anything worth spending time pondering upon, it will only yield useless knowledge.
The "exploit" is that the code relies on implementation-defined behavior of various arithmetric rules.
001 0110 0111 1000 is a 15-bit number. Why the author uses 15 bit numbers instead of 16, I
don't know. Seems like a typo remaining even after 5 editions.
If we put a minus sign in front of that binary number on a two's complement system (explanation of two's complement here), it will turn into 1110 1001 1000 1000. Because the compiler will preserve the decimal presentation of the number (5752) and translate it to its negative equivalent (-5752). (However, the actual data type will remain unsigned int, so if you tried to print it you would get the garbage number 59784.)
0001 0110 0111 1000
AND 1110 1001 1000 1000
= 0000 0000 0000 1000
The C standard does not enforce two's complement, so the code in that book is not portable.
It's a little misleading, because it actually exploits 2's complement. First, the calculation of smallest:
In 2's complement representation, for the x in the comments -x is 110100110001000. Focus on the least significant bit of x that is a one; since two's complement is essentially 1's complement plus 1, that bit will be set in both x and -x and no other bit position after it (on the way to the LSB) will have that property. That's how you get the smallest bit set.
ripple is pretty straightforward and is named as such because it propagates ones to the MSB, and smallest_ripple follows from the description above.
ones is the number we should add to the ripple in order to continue choosing n elements, picture it below:
ones: 11 next set: 100011
ones: 1 next set: 100101
ones: 0 next set: 100110
Running it will indeed show you all the ways of choosing n bits out of CHAR_BIT * sizeof(int) - 1 items (CHAR_BIT * sizeof(int) bits are needed because -x of an n-bit number needs at worst n+1 bits to be represented).
First, here a exemple of the output we can get with n=4. The idea is that we start with 'n' LSB set to '1', and then we iterate through all the combinations of numbers with the same count of bits set to '1':
1111
10111
11011
11101
11110
100111
101011
101101
101110 (*)
110011
110101
110110
111001
111010
111100
1000111
1001011
1001101
It is working the following way. I will use the number with the star above as an exemple:
101110
We get the LSB set to '1' as clearly explained in other answers.
101110
& 010011
= 000010
We "move" the LSB one position to the left by adding it to the original number. If the bit immediately on the left is '0', this is easy to understand, as the subsequent operations will do nothing. If this left bit is '1', we get a carry which will propagate to the left. The problem with this last case is that the numbers of '1' will change, so we have to set back some '1' to keep their count constant.
101110
+ 000010
= 110000
To do so, we retrieve the LSB of the new result, and by dividing it with the previous LSB, we get the number of bits over which the carry has propagated. This is converted to plain '1' at the lowest positions with the '-1',
010000
/ 000010
= 001000
>> 1
- 1
= 000011
We finally OR the result of the addition and the ones.
110011
I would say that the "exploit" is on the unsigned change of sign, in the operation (x & -x).
I'm completely stuck on how to do this homework problem and looking for a hint or two to keep me going. I'm limited to 20 operations (= doesn't count in this 20).
I'm supposed to fill in a function that looks like this:
/* Supposed to do x%(2^n).
For example: for x = 15 and n = 2, the result would be 3.
Additionally, if positive overflow occurs, the result should be the
maximum positive number, and if negative overflow occurs, the result
should be the most negative number.
*/
int remainder_power_of_2(int x, int n){
int twoToN = 1 << n;
/* Magic...? How can I do this without looping? We are assuming it is a
32 bit machine, and we can't use constants bigger than 8 bits
(0xFF is valid for example).
However, I can make a 32 bit number by ORing together a bunch of stuff.
Valid operations are: << >> + ~ ! | & ^
*/
return theAnswer;
}
I was thinking maybe I could shift the twoToN over left... until I somehow check (without if/else) that it is bigger than x, and then shift back to the right once... then xor it with x... and repeat? But I only have 20 operations!
Hint: In decadic system to do a modulo by power of 10, you just leave the last few digits and null the other. E.g. 12345 % 100 = 00045 = 45. Well, in computer numbers are binary. So you have to null the binary digits (bits). So look at various bit manipulation operators (&, |, ^) to do so.
Since binary is base 2, remainders mod 2^N are exactly represented by the rightmost bits of a value. For example, consider the following 32 bit integer:
00000000001101001101000110010101
This has the two's compliment value of 3461525. The remainder mod 2 is exactly the last bit (1). The remainder mod 4 (2^2) is exactly the last 2 bits (01). The remainder mod 8 (2^3) is exactly the last 3 bits (101). Generally, the remainder mod 2^N is exactly the last N bits.
In short, you need to be able to take your input number, and mask it somehow to get only the last few bits.
A tip: say you're using mod 64. The value of 64 in binary is:
00000000000000000000000001000000
The modulus you're interested in is the last 6 bits. I'll provide you a sequence of operations that can transform that number into a mask (but I'm not going to tell you what they are, you can figure them out yourself :D)
00000000000000000000000001000000 // starting value
11111111111111111111111110111111 // ???
11111111111111111111111111000000 // ???
00000000000000000000000000111111 // the mask you need
Each of those steps equates to exactly one operation that can be performed on an int type. Can you figure them out? Can you see how to simplify my steps? :D
Another hint:
00000000000000000000000001000000 // 64
11111111111111111111111111000000 // -64
Since your divisor is always power of two, it's easy.
uint32_t remainder(uint32_t number, uint32_t power)
{
power = 1 << power;
return (number & (power - 1));
}
Suppose you input number as 5 and divisor as 2
`00000000000000000000000000000101` number
AND
`00000000000000000000000000000001` divisor - 1
=
`00000000000000000000000000000001` remainder (what we expected)
Suppose you input number as 7 and divisor as 4
`00000000000000000000000000000111` number
AND
`00000000000000000000000000000011` divisor - 1
=
`00000000000000000000000000000011` remainder (what we expected)
This only works as long as divisor is a power of two (Except for divisor = 1), so use it carefully.