https://github.com/python/cpython/commit/169e7138ab84db465b6bf28e6c1dc6c39dbf89f4
commit: 169e7138ab84db465b6bf28e6c1dc6c39dbf89f4
branch: main
author: Sergey B Kirpichev <[email protected]>
committer: vstinner <[email protected]>
date: 2024-07-29T05:56:40+02:00
summary:
gh-122234: fix accuracy issues for sum() (#122236)
* Use compensated summation for complex sums with floating-point items.
This amends #121176.
* sum() specializations for floats and complexes now use
PyLong_AsDouble() instead of PyLong_AsLongAndOverflow() and
compensated summation as well.
files:
A Misc/NEWS.d/next/Core and
Builtins/2024-07-24-17-11-51.gh-issue-122234.VxsP_F.rst
M Lib/test/test_builtin.py
M Python/bltinmodule.c
diff --git a/Lib/test/test_builtin.py b/Lib/test/test_builtin.py
index c6a563cc90fec4..85f139db9bcd45 100644
--- a/Lib/test/test_builtin.py
+++ b/Lib/test/test_builtin.py
@@ -1778,6 +1778,8 @@ def test_sum(self):
self.assertRaises(TypeError, sum, [], '')
self.assertRaises(TypeError, sum, [], b'')
self.assertRaises(TypeError, sum, [], bytearray())
+ self.assertRaises(OverflowError, sum, [1.0, 10**1000])
+ self.assertRaises(OverflowError, sum, [1j, 10**1000])
class BadSeq:
def __getitem__(self, index):
@@ -1803,6 +1805,9 @@ def test_sum_accuracy(self):
self.assertEqual(sum([1.0, 10E100, 1.0, -10E100, 2j]), 2+2j)
self.assertEqual(sum([2+1j, 10E100j, 1j, -10E100j]), 2+2j)
self.assertEqual(sum([1j, 1, 10E100j, 1j, 1.0, -10E100j]), 2+2j)
+ self.assertEqual(sum([2j, 1., 10E100, 1., -10E100]), 2+2j)
+ self.assertEqual(sum([1.0, 10**100, 1.0, -10**100]), 2.0)
+ self.assertEqual(sum([2j, 1.0, 10**100, 1.0, -10**100]), 2+2j)
self.assertEqual(sum([0.1j]*10 + [fractions.Fraction(1, 10)]), 0.1+1j)
def test_type(self):
diff --git a/Misc/NEWS.d/next/Core and
Builtins/2024-07-24-17-11-51.gh-issue-122234.VxsP_F.rst b/Misc/NEWS.d/next/Core
and Builtins/2024-07-24-17-11-51.gh-issue-122234.VxsP_F.rst
new file mode 100644
index 00000000000000..b86d6fbdfc648f
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and
Builtins/2024-07-24-17-11-51.gh-issue-122234.VxsP_F.rst
@@ -0,0 +1,4 @@
+Specializations for sums with float and complex inputs in :func:`sum()` now
+always use compensated summation. Also, for integer items in above
+specializations: :c:func:`PyLong_AsDouble` is used, instead of
+:c:func:`PyLong_AsLongAndOverflow`. Patch by Sergey B Kirpichev.
diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c
index 3f7bf4d568ee46..ae025e767ec838 100644
--- a/Python/bltinmodule.c
+++ b/Python/bltinmodule.c
@@ -2687,14 +2687,15 @@ builtin_sum_impl(PyObject *module, PyObject *iterable,
PyObject *start)
continue;
}
if (PyLong_Check(item)) {
- long value;
- int overflow;
- value = PyLong_AsLongAndOverflow(item, &overflow);
- if (!overflow) {
- re_sum.hi += (double)value;
+ double value = PyLong_AsDouble(item);
+ if (value != -1.0 || !PyErr_Occurred()) {
+ re_sum = cs_add(re_sum, value);
Py_DECREF(item);
continue;
}
+ else {
+ return NULL;
+ }
}
result = PyFloat_FromDouble(cs_to_double(re_sum));
if (result == NULL) {
@@ -2736,19 +2737,20 @@ builtin_sum_impl(PyObject *module, PyObject *iterable,
PyObject *start)
continue;
}
if (PyLong_Check(item)) {
- long value;
- int overflow;
- value = PyLong_AsLongAndOverflow(item, &overflow);
- if (!overflow) {
- re_sum.hi += (double)value;
+ double value = PyLong_AsDouble(item);
+ if (value != -1.0 || !PyErr_Occurred()) {
+ re_sum = cs_add(re_sum, value);
im_sum.hi += 0.0;
Py_DECREF(item);
continue;
}
+ else {
+ return NULL;
+ }
}
if (PyFloat_Check(item)) {
double value = PyFloat_AS_DOUBLE(item);
- re_sum.hi += value;
+ re_sum = cs_add(re_sum, value);
im_sum.hi += 0.0;
_Py_DECREF_SPECIALIZED(item, _PyFloat_ExactDealloc);
continue;
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]