Search code examples
phpbitwise-operatorsgmp

Trouble with gmp_xor on 32 bit


On a 64-bit machine

(1 ^ 2489596804)

gives -1805370491 in response. However, when I do this on a 32-bit PHP machine, I get 2489596805 in response.

So, I tried to get it working on the 32-bit machine using gmp_strval(gmp_xor(1,2489596804)), but it also yields 2489596805. So what's up, and how can I get the right response?

Update: I just noticed that the 64-bit result is what you get from subtracting the 32-bit max from it (4294967295).


Solution

  • It's the same result, simply interpreted differently:

    0x94643B85 =  2489596805 (unsigned 32-bit integer)
    0x94643B85 = -1805370491 (signed 32-bit integer)
    

    The reason you see a negative value on your 64-bit machine is that you're interpreting that result as a signed 32-bit integer.

    If you really want to convert between the two interpretations, I think you'll have to do this yourself. A simple way to do that would be something like this:

    <?php
    function toSigned($value) {
      if ($value <= 2147483647)
        return $value;
      return $value - 4294967295 + 1;
    }
    
    function toUnsigned($value) {
      if ($value >= 0)
        return $value;
      return $value + 4294967295 - 1;
    }