From 3f8caa3ba733619e466d1b829acecefd35684345 Mon Sep 17 00:00:00 2001 From: Raymond Hettinger Date: Wed, 24 Oct 2007 01:28:33 +0000 Subject: [PATCH] Optimize sum() for integer and float inputs. --- Misc/NEWS | 2 ++ Python/bltinmodule.c | 70 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+) diff --git a/Misc/NEWS b/Misc/NEWS index f0e24b25390..6ae2ac51bf5 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -12,6 +12,8 @@ What's New in Python 2.6 alpha 1? Core and builtins ----------------- +- optimize the performance of builtin.sum(). + - Fix warnings found by the new version of the Coverity checker. - The enumerate() builtin function is no longer bounded to sequences smaller diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index ef3eac8f955..cc96cdf7a63 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -2066,6 +2066,76 @@ builtin_sum(PyObject *self, PyObject *args) Py_INCREF(result); } +#ifndef SLOW_SUM + /* Fast addition by keeping temporary sums in C instead of new Python objects. + Assumes all inputs are the same type. If the assumption fails, default + to the more general routine. + */ + if (PyInt_CheckExact(result)) { + long i_result = PyInt_AS_LONG(result); + Py_DECREF(result); + result = NULL; + while(result == NULL) { + item = PyIter_Next(iter); + if (item == NULL) { + Py_DECREF(iter); + if (PyErr_Occurred()) + return NULL; + return PyInt_FromLong(i_result); + } + if (PyInt_CheckExact(item)) { + long b = PyInt_AS_LONG(item); + long x = i_result + b; + if ((x^i_result) >= 0 || (x^b) >= 0) { + i_result = x; + Py_DECREF(item); + continue; + } + } + /* Either overflowed or is not an int. Restore real objects and process normally */ + result = PyInt_FromLong(i_result); + temp = PyNumber_Add(result, item); + Py_DECREF(result); + Py_DECREF(item); + result = temp; + if (result == NULL) { + Py_DECREF(iter); + return NULL; + } + } + } + + if (PyFloat_CheckExact(result)) { + double f_result = PyFloat_AS_DOUBLE(result); + Py_DECREF(result); + result = NULL; + while(result == NULL) { + item = PyIter_Next(iter); + if (item == NULL) { + Py_DECREF(iter); + if (PyErr_Occurred()) + return NULL; + return PyFloat_FromDouble(f_result); + } + if (PyFloat_CheckExact(item)) { + PyFPE_START_PROTECT("add", return 0) + f_result += PyFloat_AS_DOUBLE(item); + PyFPE_END_PROTECT(a) + continue; + } + result = PyFloat_FromDouble(f_result); + temp = PyNumber_Add(result, item); + Py_DECREF(result); + Py_DECREF(item); + result = temp; + if (result == NULL) { + Py_DECREF(iter); + return NULL; + } + } + } +#endif + for(;;) { item = PyIter_Next(iter); if (item == NULL) {