Skip to content

Commit a458432

Browse files
committed
pythongh-122234: fix accuracy issues for sum()
* Use compensated summation for complex sums with floating-point items. This amends python#121176. * sum() specializations for floats and complexes now use PyLong_AsDouble() instead of PyLong_AsLongAndOverflow() and compensated summation as well.
1 parent f067efa commit a458432

File tree

3 files changed

+11
-11
lines changed

3 files changed

+11
-11
lines changed

Lib/test/test_builtin.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1803,6 +1803,9 @@ def test_sum_accuracy(self):
18031803
self.assertEqual(sum([1.0, 10E100, 1.0, -10E100, 2j]), 2+2j)
18041804
self.assertEqual(sum([2+1j, 10E100j, 1j, -10E100j]), 2+2j)
18051805
self.assertEqual(sum([1j, 1, 10E100j, 1j, 1.0, -10E100j]), 2+2j)
1806+
self.assertEqual(sum([2j, 1., 10E100, 1., -10E100]), 2+2j)
1807+
self.assertEqual(sum([1.0, 10**100, 1.0, -10**100]), 2.0)
1808+
self.assertEqual(sum([2j, 1.0, 10**100, 1.0, -10**100]), 2+2j)
18061809
self.assertEqual(sum([0.1j]*10 + [fractions.Fraction(1, 10)]), 0.1+1j)
18071810

18081811
def test_type(self):
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fixed complex-valued specialization for :func:`sum`.

Python/bltinmodule.c

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2687,11 +2687,9 @@ builtin_sum_impl(PyObject *module, PyObject *iterable, PyObject *start)
26872687
continue;
26882688
}
26892689
if (PyLong_Check(item)) {
2690-
long value;
2691-
int overflow;
2692-
value = PyLong_AsLongAndOverflow(item, &overflow);
2693-
if (!overflow) {
2694-
re_sum.hi += (double)value;
2690+
double value = PyLong_AsDouble(item);
2691+
if (value != -1.0 || !PyErr_Occurred()) {
2692+
re_sum = cs_add(re_sum, value);
26952693
Py_DECREF(item);
26962694
continue;
26972695
}
@@ -2736,19 +2734,17 @@ builtin_sum_impl(PyObject *module, PyObject *iterable, PyObject *start)
27362734
continue;
27372735
}
27382736
if (PyLong_Check(item)) {
2739-
long value;
2740-
int overflow;
2741-
value = PyLong_AsLongAndOverflow(item, &overflow);
2742-
if (!overflow) {
2743-
re_sum.hi += (double)value;
2737+
double value = PyLong_AsDouble(item);
2738+
if (value != -1.0 || !PyErr_Occurred()) {
2739+
re_sum = cs_add(re_sum, value);
27442740
im_sum.hi += 0.0;
27452741
Py_DECREF(item);
27462742
continue;
27472743
}
27482744
}
27492745
if (PyFloat_Check(item)) {
27502746
double value = PyFloat_AS_DOUBLE(item);
2751-
re_sum.hi += value;
2747+
re_sum = cs_add(re_sum, value);
27522748
im_sum.hi += 0.0;
27532749
_Py_DECREF_SPECIALIZED(item, _PyFloat_ExactDealloc);
27542750
continue;

0 commit comments

Comments
 (0)