From: Raymond Hettinger Date: Sun, 12 Aug 2018 01:39:05 +0000 (-0700) Subject: Factor-out common code. Also, optimize common cases by preallocating space on the... X-Git-Tag: v3.8.0a1~1215 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=c630e104401605af5dded8ffa4002fb6683da076;p=thirdparty%2FPython%2Fcpython.git Factor-out common code. Also, optimize common cases by preallocating space on the stack. GH-8738 Improves speed by 9 to 10ns per call. --- diff --git a/Modules/mathmodule.c b/Modules/mathmodule.c index cd390f240da2..896cf8dcd5bd 100644 --- a/Modules/mathmodule.c +++ b/Modules/mathmodule.c @@ -2032,10 +2032,10 @@ math_fmod_impl(PyObject *module, double x, double y) } /* -Given an *n* length *vec* of non-negative, non-nan, non-inf values +Given an *n* length *vec* of non-negative values where *max* is the largest value in the vector, compute: - sum((x / max) ** 2 for x in vec) + max * sqrt(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. @@ -2045,19 +2045,31 @@ 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. +The value of the *max* variable must be present in *vec* +or should equal to 0.0 when n==0. Likewise, *max* will +be INF if an infinity is present in the vec. + +The *found_nan* variable indicates whether some member of +the *vec* is a NaN. */ static inline double -scaled_vector_squared(Py_ssize_t n, double *vec, double max) +vector_norm(Py_ssize_t n, double *vec, double max, int found_nan) { double x, csum = 0.0, oldcsum, frac = 0.0; Py_ssize_t i; + if (Py_IS_INFINITY(max)) { + return max; + } + if (found_nan) { + return Py_NAN; + } if (max == 0.0) { return 0.0; } assert(n > 0); - for (i=0 ; i NUM_STACK_ELEMS) { + diffs = (double *) PyObject_Malloc(n * sizeof(double)); + if (diffs == NULL) { + return NULL; + } } for (i=0 ; i NUM_STACK_ELEMS) { + coordinates = (double *) PyObject_Malloc(n * sizeof(double)); + if (coordinates == NULL) + return NULL; + } for (i=0 ; i value\n\n\ Multidimensional Euclidean distance from the origin to a point.\n\