From d11353b1397816d7c823e27c0cee8b4010864bdd Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Mon, 8 Jul 2024 16:48:26 +0300 Subject: [PATCH 1/5] Try to find existing tests for large ints on 32-bit platforms --- Objects/longobject.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Objects/longobject.c b/Objects/longobject.c index 4ca259fb08e8c7..13f05ddcb7731c 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -142,8 +142,8 @@ _PyLong_New(Py_ssize_t size) assert(size >= 0); PyLongObject *result; if (size > (Py_ssize_t)MAX_LONG_DIGITS) { - PyErr_SetString(PyExc_OverflowError, - "too many digits in integer"); + PyErr_SetString(PyExc_SystemError, + "!!!too many digits in integer"); return NULL; } /* Fast operations for single digit integers (including zero) @@ -817,7 +817,7 @@ _PyLong_NumBits(PyObject *vv) return result; Overflow: - PyErr_SetString(PyExc_OverflowError, "int has too many bits " + PyErr_SetString(PyExc_SystemError, "!!!int has too many bits " "to express in a platform size_t"); return (size_t)-1; } From afa70d36dfce4253a81b433fa670f8dad81e89a5 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Mon, 8 Jul 2024 19:34:50 +0300 Subject: [PATCH 2/5] Add new tests. --- Lib/test/test_capi/test_long.py | 12 +++++++ Lib/test/test_long.py | 58 +++++++++++++++++++++++++++++++++ Lib/test/test_math.py | 16 +++++++++ Objects/longobject.c | 6 ++-- 4 files changed, 89 insertions(+), 3 deletions(-) diff --git a/Lib/test/test_capi/test_long.py b/Lib/test/test_capi/test_long.py index 7e8d571ae234d1..e0fcc0b8ac9e49 100644 --- a/Lib/test/test_capi/test_long.py +++ b/Lib/test/test_capi/test_long.py @@ -453,6 +453,18 @@ def test_long_aspid(self): def test_long_aspid_limited(self): self._test_long_aspid(_testlimitedcapi.pylong_aspid) + @support.bigmemtest(2**29, memuse=2.1, dry_run=False) + def test_long_asnativebytes_large(self, size): + asnativebytes = _testcapi.pylong_asnativebytes + v = 1 << (size * 8) + buffer = bytearray(size * 8 // 15 + 10) + r = asnativebytes(v, buffer, 0, -1) + self.assertEqual(r, size + 1) + self.assertEqual(buffer.count(0), len(buffer)) + r = asnativebytes(v, buffer, len(buffer), -1) + self.assertEqual(r, size + 1) + self.assertEqual(buffer.count(0), len(buffer) - 1) + def test_long_asnativebytes(self): import math from _testcapi import ( diff --git a/Lib/test/test_long.py b/Lib/test/test_long.py index 3b2e7c4e71d10d..1e2e3b1d673b61 100644 --- a/Lib/test/test_long.py +++ b/Lib/test/test_long.py @@ -473,6 +473,13 @@ def test_float_conversion(self): self.check_float_conversion(value) self.check_float_conversion(-value) + @support.requires_IEEE_754 + @support.bigmemtest(2**29, memuse=1.6, dry_run=False) + def test_float_conversion_large(self, size): + bits = size * 8 + v = 1 << bits + self.assertRaises(OverflowError, float, v) + def test_float_overflow(self): for x in -2.0, -1.0, 0.0, 1.0, 2.0: self.assertEqual(float(int(x)), x) @@ -614,6 +621,57 @@ def __lt__(self, other): eq(x > y, Rcmp > 0) eq(x >= y, Rcmp >= 0) + @support.requires_IEEE_754 + @support.bigmemtest(2**29, memuse=3.2, dry_run=False) + def test_mixed_compares_large_integer(self, size): + bits = size * 8 + v = 1 << bits + f = sys.float_info.max + self.assertIs(f == v, False) + self.assertIs(f != v, True) + self.assertIs(f < v, True) + self.assertIs(f <= v, True) + self.assertIs(f > v, False) + self.assertIs(f >= v, False) + f = float('inf') + self.assertIs(f == v, False) + self.assertIs(f != v, True) + self.assertIs(f < v, False) + self.assertIs(f <= v, False) + self.assertIs(f > v, True) + self.assertIs(f >= v, True) + f = float('nan') + self.assertIs(f == v, False) + self.assertIs(f != v, True) + self.assertIs(f < v, False) + self.assertIs(f <= v, False) + self.assertIs(f > v, False) + self.assertIs(f >= v, False) + + del v + v = (-1) << bits + f = -sys.float_info.max + self.assertIs(f == v, False) + self.assertIs(f != v, True) + self.assertIs(f < v, False) + self.assertIs(f <= v, False) + self.assertIs(f > v, True) + self.assertIs(f >= v, True) + f = float('-inf') + self.assertIs(f == v, False) + self.assertIs(f != v, True) + self.assertIs(f < v, True) + self.assertIs(f <= v, True) + self.assertIs(f > v, False) + self.assertIs(f >= v, False) + f = float('nan') + self.assertIs(f == v, False) + self.assertIs(f != v, True) + self.assertIs(f < v, False) + self.assertIs(f <= v, False) + self.assertIs(f > v, False) + self.assertIs(f >= v, False) + def test__format__(self): self.assertEqual(format(123456789, 'd'), '123456789') self.assertEqual(format(123456789, 'd'), '123456789') diff --git a/Lib/test/test_math.py b/Lib/test/test_math.py index b68c442013c09f..4a9395e70af36d 100644 --- a/Lib/test/test_math.py +++ b/Lib/test/test_math.py @@ -1120,6 +1120,14 @@ def __index__(self): with self.assertRaises(TypeError): math.isqrt(value) + @support.bigmemtest(2**29, memuse=7, dry_run=False) + def test_isqrt_large(self, size): + bits = size * 8 + v = 1 << bits + w = math.isqrt(v) + self.assertEqual(w.bit_length(), bits // 2 + 1) + self.assertEqual(w.bit_count(), 1) + def test_lcm(self): lcm = math.lcm self.assertEqual(lcm(0, 0), 0) @@ -1261,6 +1269,14 @@ def testLog10(self): self.assertEqual(math.log(INF), INF) self.assertTrue(math.isnan(math.log10(NAN))) + @support.bigmemtest(2**29, memuse=1.6, dry_run=False) + def test_log_large_integer(self, size): + bits = size * 8 + v = 1 << bits + self.assertAlmostEqual(math.log2(v), bits) + self.assertAlmostEqual(math.log(v), bits * 0.6931471805599453) + self.assertAlmostEqual(math.log10(v), bits * 0.3010299956639812) + def testSumProd(self): sumprod = math.sumprod Decimal = decimal.Decimal diff --git a/Objects/longobject.c b/Objects/longobject.c index 13f05ddcb7731c..4ca259fb08e8c7 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -142,8 +142,8 @@ _PyLong_New(Py_ssize_t size) assert(size >= 0); PyLongObject *result; if (size > (Py_ssize_t)MAX_LONG_DIGITS) { - PyErr_SetString(PyExc_SystemError, - "!!!too many digits in integer"); + PyErr_SetString(PyExc_OverflowError, + "too many digits in integer"); return NULL; } /* Fast operations for single digit integers (including zero) @@ -817,7 +817,7 @@ _PyLong_NumBits(PyObject *vv) return result; Overflow: - PyErr_SetString(PyExc_SystemError, "!!!int has too many bits " + PyErr_SetString(PyExc_OverflowError, "int has too many bits " "to express in a platform size_t"); return (size_t)-1; } From a3e6be413f5d80eedf02606b817dfaf0a1f31046 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Mon, 8 Jul 2024 20:48:21 +0300 Subject: [PATCH 3/5] Always run new tests. --- Lib/test/test_capi/test_long.py | 4 ++-- Lib/test/test_long.py | 8 ++++---- Lib/test/test_math.py | 8 ++++---- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Lib/test/test_capi/test_long.py b/Lib/test/test_capi/test_long.py index e0fcc0b8ac9e49..94ce68bce205f8 100644 --- a/Lib/test/test_capi/test_long.py +++ b/Lib/test/test_capi/test_long.py @@ -453,8 +453,8 @@ def test_long_aspid(self): def test_long_aspid_limited(self): self._test_long_aspid(_testlimitedcapi.pylong_aspid) - @support.bigmemtest(2**29, memuse=2.1, dry_run=False) - def test_long_asnativebytes_large(self, size): + #@support.bigmemtest(2**29, memuse=2.1, dry_run=False) + def test_long_asnativebytes_large(self, size=2**29): asnativebytes = _testcapi.pylong_asnativebytes v = 1 << (size * 8) buffer = bytearray(size * 8 // 15 + 10) diff --git a/Lib/test/test_long.py b/Lib/test/test_long.py index 1e2e3b1d673b61..9faac8a8a5b5cb 100644 --- a/Lib/test/test_long.py +++ b/Lib/test/test_long.py @@ -474,8 +474,8 @@ def test_float_conversion(self): self.check_float_conversion(-value) @support.requires_IEEE_754 - @support.bigmemtest(2**29, memuse=1.6, dry_run=False) - def test_float_conversion_large(self, size): + #@support.bigmemtest(2**29, memuse=1.6, dry_run=False) + def test_float_conversion_large(self, size=2**29): bits = size * 8 v = 1 << bits self.assertRaises(OverflowError, float, v) @@ -622,8 +622,8 @@ def __lt__(self, other): eq(x >= y, Rcmp >= 0) @support.requires_IEEE_754 - @support.bigmemtest(2**29, memuse=3.2, dry_run=False) - def test_mixed_compares_large_integer(self, size): + #@support.bigmemtest(2**29, memuse=3.2, dry_run=False) + def test_mixed_compares_large_integer(self, size=2**29): bits = size * 8 v = 1 << bits f = sys.float_info.max diff --git a/Lib/test/test_math.py b/Lib/test/test_math.py index 4a9395e70af36d..9a36875aa1e9d1 100644 --- a/Lib/test/test_math.py +++ b/Lib/test/test_math.py @@ -1120,8 +1120,8 @@ def __index__(self): with self.assertRaises(TypeError): math.isqrt(value) - @support.bigmemtest(2**29, memuse=7, dry_run=False) - def test_isqrt_large(self, size): + #@support.bigmemtest(2**29, memuse=7, dry_run=False) + def test_isqrt_large(self, size=2**29): bits = size * 8 v = 1 << bits w = math.isqrt(v) @@ -1269,8 +1269,8 @@ def testLog10(self): self.assertEqual(math.log(INF), INF) self.assertTrue(math.isnan(math.log10(NAN))) - @support.bigmemtest(2**29, memuse=1.6, dry_run=False) - def test_log_large_integer(self, size): + #@support.bigmemtest(2**29, memuse=1.6, dry_run=False) + def test_log_large_integer(self, size=2**29): bits = size * 8 v = 1 << bits self.assertAlmostEqual(math.log2(v), bits) From 8e0650e9fc75d2abfb0bec7d5e87058bc3bf0bd1 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Mon, 8 Jul 2024 21:10:10 +0300 Subject: [PATCH 4/5] Fix test_long_asnativebytes_large. --- Lib/test/test_capi/test_long.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_capi/test_long.py b/Lib/test/test_capi/test_long.py index 94ce68bce205f8..d9075b4ec50d7d 100644 --- a/Lib/test/test_capi/test_long.py +++ b/Lib/test/test_capi/test_long.py @@ -453,11 +453,11 @@ def test_long_aspid(self): def test_long_aspid_limited(self): self._test_long_aspid(_testlimitedcapi.pylong_aspid) - #@support.bigmemtest(2**29, memuse=2.1, dry_run=False) + @support.bigmemtest(2**29, memuse=2.7, dry_run=False) def test_long_asnativebytes_large(self, size=2**29): asnativebytes = _testcapi.pylong_asnativebytes v = 1 << (size * 8) - buffer = bytearray(size * 8 // 15 + 10) + buffer = bytearray(size * 16 // 15 + 10) r = asnativebytes(v, buffer, 0, -1) self.assertEqual(r, size + 1) self.assertEqual(buffer.count(0), len(buffer)) From 84f7aef79ef111f880ee397d0115c9f3691af16e Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Mon, 8 Jul 2024 21:35:06 +0300 Subject: [PATCH 5/5] Always run test_long_asnativebytes_large. --- Lib/test/test_capi/test_long.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/test_capi/test_long.py b/Lib/test/test_capi/test_long.py index d9075b4ec50d7d..903f86bdea1576 100644 --- a/Lib/test/test_capi/test_long.py +++ b/Lib/test/test_capi/test_long.py @@ -453,7 +453,7 @@ def test_long_aspid(self): def test_long_aspid_limited(self): self._test_long_aspid(_testlimitedcapi.pylong_aspid) - @support.bigmemtest(2**29, memuse=2.7, dry_run=False) + #@support.bigmemtest(2**29, memuse=2.7, dry_run=False) def test_long_asnativebytes_large(self, size=2**29): asnativebytes = _testcapi.pylong_asnativebytes v = 1 << (size * 8)