Suppose we have 16-bit number where we want to reverse some bits between bits i'th and j'th. To illustrate that, say we have a 16-bit value stored in v:
|<-------- L = sizeof(short)*CHAR_BIT --------->|
15 7 1 0
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| | | | x| x| x| x| x| x| x| | | | | | |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
^ ^
| |
i=12 j=6
|<------>|
L - i - 1
So, we want to reverse bits between bits 6th to 12th.
Assume i is always greater than j (i > j):
Number of bits to reverse: n = (i - j) + 1
Mask to use: (2^n - 1) << j
Or, in the case above:
n = (12 - 6) + 1 = 7
mask = (2^7 - 1) << 6 = 127 << 6 = 0x1FC0 (0001111111000000 in binary)
Then we mask the bits stored in v and shift it back to 0 (to do reverse operation):
r = (v & mask) >> j;
r =
15 7 1 0
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| 0| 0| 0| 0| 0| 0| 0| 0| 0| x| x| x| x| x| x| x|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
We use bit reversal operation as posted previously on r:
r = bit_reversal(r);
After this call, the bits are reversed, but filled in from MSB. We need to put them to the position originally started.
15 7 1 0
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| x| x| x| x| x| x| x| | | | | | | | | |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|-------> shr 3
<========= sizeof(unsigned int)* CHAR_BIT ======>
m = sizeof(short) * CHAR_BIT - n - j
m = 2*8 - 7 -6 = 16 - 13 = 3
Final result is:
(v & !mask) | ((r >> m) & mask);
|<-------- L = sizeof(short)*CHAR_BIT --------->|
15 7 1 0
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| | | | x| x| x| x| x| x| x| | | | | | |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
^ ^
| |
i=12 j=6
|<------>|
L - i - 1
So, we want to reverse bits between bits 6th to 12th.
Assume i is always greater than j (i > j):
Number of bits to reverse: n = (i - j) + 1
Mask to use: (2^n - 1) << j
Or, in the case above:
n = (12 - 6) + 1 = 7
mask = (2^7 - 1) << 6 = 127 << 6 = 0x1FC0 (0001111111000000 in binary)
Then we mask the bits stored in v and shift it back to 0 (to do reverse operation):
r = (v & mask) >> j;
r =
15 7 1 0
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| 0| 0| 0| 0| 0| 0| 0| 0| 0| x| x| x| x| x| x| x|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
We use bit reversal operation as posted previously on r:
r = bit_reversal(r);
After this call, the bits are reversed, but filled in from MSB. We need to put them to the position originally started.
15 7 1 0
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| x| x| x| x| x| x| x| | | | | | | | | |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|-------> shr 3
<========= sizeof(unsigned int)* CHAR_BIT ======>
m = sizeof(short) * CHAR_BIT - n - j
m = 2*8 - 7 -6 = 16 - 13 = 3
Final result is:
(v & !mask) | ((r >> m) & mask);