Bit Manipulation (1)

The steps I took to derive the answer here

For numbers in binary format, incrementing by 1 is same as inverting the rightmost 0 and all the 1’s following the 0.

For example:

x              : 00000101
                       ^^  // invert these two bits
x + 1          : 00000110

In this case with masks, first we need to locate the rightmost 0 belonging to mask, and then secondly, invert the located 0 and the following 1’s belonging to mask.

mask           : 01010101
x              : 00010001
                      ^ ^ // these two bits needs to be reversed

The first step of locating the rightmost 0 can be done by finding the rightmost 1 of x ^ mask.

x              : 00010001
                      ^   // rightmost 0 belonging to mask
mask           : 01010101
x ^ mask (= y) : 01000100
                      ^   // we need to locate this 1

Finding the rightmost 1 of y can be done by y & -y. (This unary minus hack is from a book called Hacker’s Delight)

y              : 01000100
-y             : 10111100
y & -y (= z)   : 00000100
                      ^   // found!

We’ve now located the rightmost 0 of x belonging to mask. The reversal of this 0 can be done by bit-wise OR with z.

Next we need to reverse the 1’s of x on the right side of the above location. This can be done by x & -y.

x              : 00010001
-y             : 10111100
x & -y (= w)   : 00010000
                        ^ // bit cleared

In this step, other 1’s that needs to be preserved doesn’t become 0. I think this can be proved by the fact that the 1’s of x on the left of rightmost 0 (belonging to mask) become 0 in y (because the bit is XORed with mask) and it always will be 1 in -y.

x              : 00010001
                    ^     // this 1 needs to be preserved
y              : 01000100
                    ^     // it becomes 0 in y
-y             : 10111100
                    ^     // and it always will be 1 on -y

Then, combining z and w with bit-wise OR gives the answer.

z              : 00000100
w              : 00010000
z | w          : 00010100

To sum up, this results in 5 steps as follows.

y       = x ^ mask;
minus_y = -y;
z       = y & minus_y;
w       = x & minus_y;
x + 1   = z | w;

But since z | w = (y & -y) | (x & -y) = (y | x) & -y = mask & -y by boolean logic, this can be reduced to 3 steps:

x + 1   = mask & -(x ^ mask)