Skip to content

Commit 8be8949

Browse files
authored
gh-91117: Ensure integer mod and pow operations use cached small ints (GH-31843)
1 parent a8abb76 commit 8be8949

File tree

3 files changed

+45
-0
lines changed

3 files changed

+45
-0
lines changed

Lib/test/test_long.py

+42
Original file line numberDiff line numberDiff line change
@@ -1024,6 +1024,48 @@ def test_small_ints_in_huge_calculation(self):
10241024
self.assertIs(a + b, 1)
10251025
self.assertIs(c - a, 1)
10261026

1027+
@support.cpython_only
1028+
def test_pow_uses_cached_small_ints(self):
1029+
self.assertIs(pow(10, 3, 998), 2)
1030+
self.assertIs(10 ** 3 % 998, 2)
1031+
a, p, m = 10, 3, 998
1032+
self.assertIs(a ** p % m, 2)
1033+
1034+
self.assertIs(pow(2, 31, 2 ** 31 - 1), 1)
1035+
self.assertIs(2 ** 31 % (2 ** 31 - 1), 1)
1036+
a, p, m = 2, 31, 2 ** 31 - 1
1037+
self.assertIs(a ** p % m, 1)
1038+
1039+
self.assertIs(pow(2, 100, 2**100 - 3), 3)
1040+
self.assertIs(2 ** 100 % (2 ** 100 - 3), 3)
1041+
a, p, m = 2, 100, 2**100 - 3
1042+
self.assertIs(a ** p % m, 3)
1043+
1044+
@support.cpython_only
1045+
def test_divmod_uses_cached_small_ints(self):
1046+
big = 10 ** 100
1047+
1048+
self.assertIs((big + 1) % big, 1)
1049+
self.assertIs((big + 1) // big, 1)
1050+
self.assertIs(big // (big // 2), 2)
1051+
self.assertIs(big // (big // -4), -4)
1052+
1053+
q, r = divmod(2 * big + 3, big)
1054+
self.assertIs(q, 2)
1055+
self.assertIs(r, 3)
1056+
1057+
q, r = divmod(-4 * big + 100, big)
1058+
self.assertIs(q, -4)
1059+
self.assertIs(r, 100)
1060+
1061+
q, r = divmod(3 * (-big) - 1, -big)
1062+
self.assertIs(q, 3)
1063+
self.assertIs(r, -1)
1064+
1065+
q, r = divmod(3 * big - 1, -big)
1066+
self.assertIs(q, -3)
1067+
self.assertIs(r, -1)
1068+
10271069
def test_small_ints(self):
10281070
for i in range(-5, 257):
10291071
self.assertIs(i, i + 0)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Integer mod/remainder operations, including the three-argument form of :func:`pow`, now consistently return ints from the global small integer cache when applicable.

Objects/longobject.c

+2
Original file line numberDiff line numberDiff line change
@@ -2679,6 +2679,7 @@ long_divrem(PyLongObject *a, PyLongObject *b,
26792679
}
26802680
else {
26812681
z = x_divrem(a, b, prem);
2682+
*prem = maybe_small_long(*prem);
26822683
if (z == NULL)
26832684
return -1;
26842685
}
@@ -2732,6 +2733,7 @@ long_rem(PyLongObject *a, PyLongObject *b, PyLongObject **prem)
27322733
else {
27332734
/* Slow path using divrem. */
27342735
Py_XDECREF(x_divrem(a, b, prem));
2736+
*prem = maybe_small_long(*prem);
27352737
if (*prem == NULL)
27362738
return -1;
27372739
}

0 commit comments

Comments
 (0)