From: Raymond Hettinger Date: Sat, 11 Aug 2018 18:26:36 +0000 (-0700) Subject: Replace straight addition with Kahan summation and move max to the end (GH-8727) X-Git-Tag: v3.8.0a1~1216 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=13990745350d9332103b37c2425fa9977716db4b;p=thirdparty%2FPython%2Fcpython.git Replace straight addition with Kahan summation and move max to the end (GH-8727) --- diff --git a/Modules/mathmodule.c b/Modules/mathmodule.c index 8f11f2cf3184..cd390f240da2 100644 --- a/Modules/mathmodule.c +++ b/Modules/mathmodule.c @@ -2031,6 +2031,49 @@ math_fmod_impl(PyObject *module, double x, double y) return PyFloat_FromDouble(r); } +/* +Given an *n* length *vec* of non-negative, non-nan, non-inf values +where *max* is the largest value in the vector, compute: + + sum((x / max) ** 2 for x in vec) + +When a maximum value is found, it is swapped to the end. This +lets us skip one loop iteration and just add 1.0 at the end. +Saving the largest value for last also helps improve accuracy. + +Kahan summation is used to improve accuracy. The *csum* +variable tracks the cumulative sum and *frac* tracks +fractional round-off error for the most recent addition. + +*/ + +static inline double +scaled_vector_squared(Py_ssize_t n, double *vec, double max) +{ + double x, csum = 0.0, oldcsum, frac = 0.0; + Py_ssize_t i; + + if (max == 0.0) { + return 0.0; + } + assert(n > 0); + for (i=0 ; i