]> granicus.if.org Git - python/commitdiff
Optimize sum() for integer and float inputs.
authorRaymond Hettinger <python@rcn.com>
Wed, 24 Oct 2007 01:28:33 +0000 (01:28 +0000)
committerRaymond Hettinger <python@rcn.com>
Wed, 24 Oct 2007 01:28:33 +0000 (01:28 +0000)
Misc/NEWS
Python/bltinmodule.c

index f0e24b25390e8cd84a0cb8923eeb9aa934060d67..6ae2ac51bf5b9f72c89ba2d11f2b8ef92c1b70ad 100644 (file)
--- 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
index ef3eac8f955f3d003dc08eeb92f357c4a110035a..cc96cdf7a63a69b20ff4204069c7a1b0f2cc7231 100644 (file)
@@ -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) {