diff options
author | Raymond Hettinger <python@rcn.com> | 2007-10-24 01:28:33 (GMT) |
---|---|---|
committer | Raymond Hettinger <python@rcn.com> | 2007-10-24 01:28:33 (GMT) |
commit | 3f8caa3ba733619e466d1b829acecefd35684345 (patch) | |
tree | 9b5528f7c5cfa58794224ecdd53ff81167cc81c2 /Python/bltinmodule.c | |
parent | cd3c108ca11c425d557dc86cd1e554ee98681445 (diff) | |
download | cpython-3f8caa3ba733619e466d1b829acecefd35684345.zip cpython-3f8caa3ba733619e466d1b829acecefd35684345.tar.gz cpython-3f8caa3ba733619e466d1b829acecefd35684345.tar.bz2 |
Optimize sum() for integer and float inputs.
Diffstat (limited to 'Python/bltinmodule.c')
-rw-r--r-- | Python/bltinmodule.c | 70 |
1 files changed, 70 insertions, 0 deletions
diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index ef3eac8..cc96cdf 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) { |