diff --git a/Lib/test/test_long.py b/Lib/test/test_long.py index 53101b3badb..7ce37e8dbd6 100644 --- a/Lib/test/test_long.py +++ b/Lib/test/test_long.py @@ -956,6 +956,14 @@ class LongTest(unittest.TestCase): 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) diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-09-06-16-40-12.bpo-27145.njuCXU.rst b/Misc/NEWS.d/next/Core and Builtins/2019-09-06-16-40-12.bpo-27145.njuCXU.rst new file mode 100644 index 00000000000..229753a3730 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2019-09-06-16-40-12.bpo-27145.njuCXU.rst @@ -0,0 +1 @@ +int + int and int - int operators can now return small integer singletons. Patch by hongweipeng. diff --git a/Objects/longobject.c b/Objects/longobject.c index 294308e3e12..f0567970468 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -3206,7 +3206,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 * @@ -3254,13 +3254,15 @@ long_sub(PyLongObject *a, PyLongObject *b) return PyLong_FromLong(MEDIUM_VALUE(a) - MEDIUM_VALUE(b)); } if (Py_SIZE(a) < 0) { - if (Py_SIZE(b) < 0) - z = x_sub(a, b); - else + if (Py_SIZE(b) < 0) { + 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 {