Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Simplify the inverse of Z = X ^ (X << Y) function

I'm having difficulty with simplifying the following function into several several atomic binary operations, it feels like it's possible however I'm unable to do it, I'm scratching my head for few hours already:

public UInt32 reverse_xor_lshift(UInt32 y, Int32 shift)
{
    var x = y & (UInt32)((1 << shift) - 1);

    for (int i = 0; i < (32 - shift); i++) {
        var bit = ((x & (1 << i)) >> i) ^ ((y & (1 << (shift + i))) >> (shift + i));

        x |= (UInt32)(bit << (shift + i));
    }

    return x;
}

what the function does is just it computes the inverse of the Z = X ^ (X << Y), in other words reverse_xor_lshift(Z, Y) == X

like image 536
Lu4 Avatar asked Jul 20 '15 16:07

Lu4


1 Answers

You can inverse it with much fewer operations, though in a harder to understand way, by using the same technique as used in converting back from grey code:

Apply the transformation z ^= z << i where i starts at shift and doubles every iteration.

In pseudocode:

while (i < 32)
    x ^= x << i
    i *= 2

This works because in the first step, you xor the lowest bits (unaffected) by the place where they were "xored in", thus "xoring them out". Then the part that has been changed to the original is twice as wide. The new number is then of the form x ^ (x << k) ^ (x << k) ^ (x << 2k) = x ^ (x << 2k) which is the same thing again but with twice the offset, so the same trick will work again, decoding yet more of the original bits.

like image 176
harold Avatar answered Nov 09 '22 06:11

harold