Skip to content

Commit 787f2e5

Browse files
committed
Kahan summation
1 parent 916ab7e commit 787f2e5

File tree

2 files changed

+10
-12
lines changed

2 files changed

+10
-12
lines changed

Lib/test/test_builtin.py

+4-3
Original file line numberDiff line numberDiff line change
@@ -1614,9 +1614,10 @@ def test_sum(self):
16141614
self.assertEqual(sum((i / 2 for i in range(10)), 1000.25), 1022.75)
16151615
self.assertEqual(sum([0.5, 1]), 1.5)
16161616
self.assertEqual(sum([1, 0.5]), 1.5)
1617-
# self.assertEqual(repr(sum([-0.0])), '0.0')
1618-
# self.assertEqual(repr(sum([-0.0], -0.0)), '-0.0')
1619-
# self.assertEqual(repr(sum([], -0.0)), '-0.0')
1617+
self.assertEqual(sum([0.1] * 10), 1.0) # Test accuracy of Kahan summation
1618+
self.assertEqual(repr(sum([-0.0])), '0.0')
1619+
self.assertEqual(repr(sum([-0.0], -0.0)), '-0.0')
1620+
self.assertEqual(repr(sum([], -0.0)), '-0.0')
16201621

16211622
self.assertRaises(TypeError, sum)
16221623
self.assertRaises(TypeError, sum, 42)

Python/bltinmodule.c

+6-9
Original file line numberDiff line numberDiff line change
@@ -2533,25 +2533,22 @@ builtin_sum_impl(PyObject *module, PyObject *iterable, PyObject *start)
25332533
if (PyFloat_CheckExact(result)) {
25342534
double f_result = PyFloat_AS_DOUBLE(result);
25352535
double c = 0.0;
2536-
double x, t;
25372536
Py_SETREF(result, NULL);
25382537
while(result == NULL) {
25392538
item = PyIter_Next(iter);
25402539
if (item == NULL) {
25412540
Py_DECREF(iter);
25422541
if (PyErr_Occurred())
25432542
return NULL;
2544-
return PyFloat_FromDouble(f_result + c);
2543+
return PyFloat_FromDouble(f_result);
25452544
}
25462545
if (PyFloat_CheckExact(item)) {
2547-
// Neumaier compensated summation
2546+
// Kahan compensated summation
2547+
double x, y, t;
25482548
x = PyFloat_AS_DOUBLE(item);
2549-
t = f_result + x;
2550-
if (fabs(f_result) >= fabs(x)) {
2551-
c += (f_result - t) + x;
2552-
} else {
2553-
c += (x - t) + f_result;
2554-
}
2549+
y = x - c;
2550+
t = f_result + y;
2551+
c = (t - f_result) - y;
25552552
f_result = t;
25562553
_Py_DECREF_SPECIALIZED(item, _PyFloat_ExactDealloc);
25572554
continue;

0 commit comments

Comments
 (0)