Live data from Hacker News

The Three Ways of XOR

horia141.com

41–50 of 69 posts

Re: The Three Ways of XOR

#41
post #35

Earlier quoted context omitted.

This also works with `sub` instead of xor. This code (xor swap, sub swap) should nevertheless better not be used on a modern CPU since it can badly be pipelined.

I think you mean a combination of sub and add (e.g. sub sub add). xor is somewhat special in that it is its own inverse.

Yes, you are right - I was a little abentminded.

Re: The Three Ways of XOR

#43
post #39

Very early on in my computing career (nearly 40 years ago now), I remember being blown away when an older IBM Systems 360 programmer showed me how you can swap the values of two variables over WITHOUT using a third placeholder variable by using pure XOR. I didn't believe him until he showed me. Apparently they used to use it all the time to swap out entire segments of RAM in the S/360 without having to page out to di…

I have a similar memory from my early days of coding. I was implementing a toy rc4 cipher. One of the steps in the ciphers involves swapping entries in an arrays of 256 elements. I thought "hey, I'm a 1337 coder, I'm going to use the xor trick". Except it doesn't work if you're trying to swap something with itself. If you do "a[i] ^= a[j]" and i == j then you're just clearing the entry. Taught me the valuable lesson…

This was the basis of an excellent entry [0] in the 2007 Underhanded C Contest. It had a correct implementation of the RC4 encryption algorithm, except it used the XOR swap, so on average one byte of the pseudorandom state was zeroed every 256 iterations. Eventually, the state is all zeroes, and the encryption just outputs pure plaintext. Best of all, the first few kilobytes of output looks random at first glance.

[0] http://www.underhanded-c.org/_page_id_16.html

Re: The Three Ways of XOR

#44
post #35

Very early on in my computing career (nearly 40 years ago now), I remember being blown away when an older IBM Systems 360 programmer showed me how you can swap the values of two variables over WITHOUT using a third placeholder variable by using pure XOR. I didn't believe him until he showed me. Apparently they used to use it all the time to swap out entire segments of RAM in the S/360 without having to page out to di…

This also works with `sub` instead of xor. This code (xor swap, sub swap) should nevertheless better not be used on a modern CPU since it can badly be pipelined.

Yes, in fact compilers these days are smart enough to convert people's xor swaps into mov swaps: https://godbolt.org/g/FYv7xQ

Re: The Three Ways of XOR

#45

Very early on in my computing career (nearly 40 years ago now), I remember being blown away when an older IBM Systems 360 programmer showed me how you can swap the values of two variables over WITHOUT using a third placeholder variable by using pure XOR. I didn't believe him until he showed me. Apparently they used to use it all the time to swap out entire segments of RAM in the S/360 without having to page out to di…

You can do the same with addition/subtract. Perhaps there is a simpler way, but here is one way to do it:

    a = a + b
    b = b + a
    a = b - a
    b = b - 2*a

Re: The Three Ways of XOR

#46

One thing I love about xor is an interesting correspondence between bitwise xor and the outer product of the exterior algebra. Say we have an N=4 dimensional vector space, and we use binary place values to represent units vector in a basis, like this: w = 1000 x = 0100 y = 0010 z = 0001 Then a multivector basis could be represented e.g.: xyz = 0111 xy = 0110 wz = 1001 Now, if ^ is the outer product: xy^yz = xz ↔ 0110…

I remember this and other tricks are implemented in Gaigen (a code generator for geometric algebra).

https://sourceforge.net/projects/g25/?source=directory

The XOR trick is close to slide 16 of http://www.science.uva.nl/research/ias/ga/gaigen/files/20020...

...

How to compute the geometric product of unit orthogonal basis blades (3/3) If we represent each basis vector with a specific bit in a binary number (e1 = 001b, e2 = 010b, e3 = 100b), computing the geometric product of basis blades is exactly the xor operation on binary numbers!

  (e1^e2)(e2^e3) = e1^e3
  011b xor 110b = 101b
We have to take care of the signs though:

- basis vectors have to be rearranged into a specific order before they can annihilate each other (this rearranging causes a sign change in the result). This can also be computed binary. - signature of annihilated basis vectors can change the sign as well.

Re: The Three Ways of XOR

#47
post #2

> most programming languages don’t have an explicit “logical operator” for it I guess the author never taught of != . The only thing to be careful with is that it doesn't implicitly convert arguments to boolean, so expressions like " != (flags & Flag)" will go wrong without an explicit conversion "bool(flags & Flag)" or equivalent expression like "((flags & Flag) != 0)". And let's not forget about the friend, ==. I'v…

!!a != !!b also works, but that's unwieldy. I think maybe part of the reason is that usually you're also doing something with the value of the lhs or rhs, so you end up having to separate the cases anyway: if (a && !b) { frob(a); } else if (b && !a) { twiddle(b); } else { panic(); }

You don't need to double-negate,

  !a != !b
is sufficient.

Re: The Three Ways of XOR

#48
post #44
post #35

Earlier quoted context omitted.

This also works with `sub` instead of xor. This code (xor swap, sub swap) should nevertheless better not be used on a modern CPU since it can badly be pipelined.

Yes, in fact compilers these days are smart enough to convert people's xor swaps into mov swaps: https://godbolt.org/g/FYv7xQ

When I look at the generated code that multiple of the compilers (gcc,clang,icc) generate

  mov     eax, edi
  mov     edi, esi
  mov     esi, eax
I would intuitively use the `xchg` instruction that x86-32/x86-64 provides instead. Is there a specific reason why the compiler(s) decide to generate the mentioned code instead?

Re: The Three Ways of XOR

#49
post #45

Very early on in my computing career (nearly 40 years ago now), I remember being blown away when an older IBM Systems 360 programmer showed me how you can swap the values of two variables over WITHOUT using a third placeholder variable by using pure XOR. I didn't believe him until he showed me. Apparently they used to use it all the time to swap out entire segments of RAM in the S/360 without having to page out to di…

You can do the same with addition/subtract. Perhaps there is a simpler way, but here is one way to do it: a = a + b b = b + a a = b - a b = b - 2*a

You have to take overflow into account. In most cases, that would make the algorithm not very useful compared to just doing the swap with a third variable.

Re: The Three Ways of XOR

#50
post #48
post #44

Earlier quoted context omitted.

Yes, in fact compilers these days are smart enough to convert people's xor swaps into mov swaps: https://godbolt.org/g/FYv7xQ

When I look at the generated code that multiple of the compilers (gcc,clang,icc) generate mov eax, edi mov edi, esi mov esi, eax I would intuitively use the `xchg` instruction that x86-32/x86-64 provides instead. Is there a specific reason why the compiler(s) decide to generate the mentioned code instead?

Some of that is weird placeholders for the debugger, for inserting hook instructions or whatnot?
Post reply on HN