Skip to content
8 changes: 8 additions & 0 deletions Lib/test/test_long.py
Original file line number Diff line number Diff line change
Expand Up @@ -956,6 +956,14 @@ 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 ** 100
b = -a + 1
c = a + 1
self.assertIs(a + b, 1)
self.assertIs(c - a, 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.
15 changes: 9 additions & 6 deletions Objects/longobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -3220,6 +3220,8 @@ x_sub(PyLongObject *a, PyLongObject *b)
;
if (i < 0)
return (PyLongObject *)PyLong_FromLong(0);
if (i == 0)
return (PyLongObject *)PyLong_FromLong((sdigit)a->ob_digit[0] - (sdigit)b->ob_digit[0]);
if (a->ob_digit[i] < b->ob_digit[i]) {
sign = -1;
{ PyLongObject *temp = a; a = b; b = temp; }
Expand Down Expand Up @@ -3247,7 +3249,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 +3298,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