Skip to content
10 changes: 10 additions & 0 deletions Lib/test/test_long.py
Original file line number Diff line number Diff line change
Expand Up @@ -956,6 +956,16 @@ def test_huge_rshift_of_huge(self, size):
self.assertEqual(huge >> (sys.maxsize + 1), (1 << 499) + 5)
self.assertEqual(huge >> (sys.maxsize + 1000), 0)

@support.cpython_only
def test_small_ints_in_huge_calculation(self):
a = 2 ** SHIFT
b = 2 ** SHIFT - 1
c = 2 ** SHIFT + 1
d = -a
self.assertIsNot(a + b, 2 ** (SHIFT + 1) - 1)
self.assertIs(a - b, 1)
self.assertIs(c + d, 1)

def test_small_ints(self):
for i in range(-5, 257):
self.assertIs(i, i + 0)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
int + int and int - int operators can now return small integer singletons. Patch by hongweipeng.
13 changes: 7 additions & 6 deletions Objects/longobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -3247,7 +3247,7 @@ x_sub(PyLongObject *a, PyLongObject *b)
if (sign < 0) {
Py_SIZE(z) = -Py_SIZE(z);
}
return long_normalize(z);
return maybe_small_long(long_normalize(z));
}

static PyObject *
Expand Down Expand Up @@ -3296,12 +3296,13 @@ long_sub(PyLongObject *a, PyLongObject *b)
}
if (Py_SIZE(a) < 0) {
if (Py_SIZE(b) < 0)
z = x_sub(a, b);
else
z = x_sub(b, a);
else {
z = x_add(a, b);
if (z != NULL) {
assert(Py_SIZE(z) == 0 || Py_REFCNT(z) == 1);
Py_SIZE(z) = -(Py_SIZE(z));
if (z != NULL) {
assert(Py_SIZE(z) == 0 || Py_REFCNT(z) == 1);
Py_SIZE(z) = -(Py_SIZE(z));
}
}
}
else {
Expand Down