Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What does it mean if the bitwise XOR of the sum and two addends are both negative?

Tags:

c

binary

For example, there are 3 variables of long type, we add a and b and get s:

long a, b, s;
...
s = a + b

Now what does ((s^a) < 0 && (s^b) < 0) mean?

I saw a check like this in the source code of Python:

    if (PyInt_CheckExact(v) && PyInt_CheckExact(w)) {
        /* INLINE: int + int */
        register long a, b, i;
        a = PyInt_AS_LONG(v);
        b = PyInt_AS_LONG(w);
        i = a + b;
        if ((i^a) < 0 && (i^b) < 0)
            goto slow_iadd;
        x = PyInt_FromLong(i);
    }
like image 927
satoru Avatar asked Jun 25 '15 02:06

satoru


People also ask

How does XOR work in Bitwise?

The Bitwise Xor operation treats the sign bit as it would any other bit. If one or both inputs for a pixel location are negative, the output is negative; if both inputs are positive, the output is positive.

What happens when you XOR two numbers?

XOR Background As we can see, if both bits are similar, then the XOR equals to zero. Otherwise, the result equals to one. Put differently, the bitwise XOR operation equals zero in case the number of ones is even and equals one in case the number of ones is odd.

How do you find the Bitwise XOR of two numbers?

To find each bit of XOR just calculate number of 1's in the corresponding bits. If it is even or zero then that XOR'ed bit is 0. If it is odd then that XOR'ed bit is 1.

Does XOR do addition?

The XOR logic gate can be used as a one-bit adder that adds any two bits together to output one bit. For example, if we add 1 plus 1 in binary, we expect a two-bit answer, 10 (i.e. 2 in decimal). Since the trailing sum bit in this output is achieved with XOR, the preceding carry bit is calculated with an AND gate.


2 Answers

This code is wrong.

Assuming the usual 2's-complement rules of bitwise XOR for signed integers, then

(s^a) < 0

is the case if s and a have their sign bits set to opposite values. Thus,

((s^a) < 0 && (s^b) < 0)

indicates that s has sign different from both a and b, which must then have equal sign (pretending 0 is positive). If you added two integers of equal sign and got a result of different sign, there must have been an overflow, so this is an overflow check.

If we assume that signed overflow wraps, then s has opposite sign from a and b exactly when overflow has occurred. However, signed overflow is undefined behavior. Computing s is already wrong; we need to check whether the overflow would occur without actually performing the operation.

Python isn't supposed to do this. You can see what it's supposed to do in the Python 2 source code for int.__add__:

/* casts in the line below avoid undefined behaviour on overflow */
x = (long)((unsigned long)a + b);
if ((x^a) >= 0 || (x^b) >= 0)

It's supposed to cast to unsigned to get defined overflow behavior. The cast-to-unsigned fix was introduced in 5 different places as a result of issue 7406 on the Python bug tracker, but it looks like they missed a spot, or perhaps INPLACE_ADD was changed since then. I've left a message on the tracker.

like image 74
user2357112 supports Monica Avatar answered Oct 21 '22 04:10

user2357112 supports Monica


I don't see how this is possible.

If (s^a) < 0, then the sign bit of either s or a must be a 1, so either s or a (but not both) must be negative. Same for s and b. So either s is negative and both a and b are positive, or s is positive and both a and b are negative. Both situations seem impossible.

Unless you count integer overflow/underflow, of course.

like image 34
Sam Estep Avatar answered Oct 21 '22 03:10

Sam Estep