简体   繁体   中英

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

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM