I'd be +1 on generalizing math.hypot to accept an arbitrary number of arguments. It's the natural building block for computing distance, but the reverse is strained. Both are useful.
Here's scaling code translated from the Fortran implementation of SNRM2 in LAPACK. It only looks at each element once, so would work almost as-is for an argument that's an arbitrary iterable (just change the formal argument from `*xs` to `xs`):
# http://www.netlib.org/lapack/explore-html/d7/df1/snrm2_8f_source.html
def hypot(*xs):
import math
scale = 0.0
sumsq = 1.0
for x in xs:
if x:
absx = abs(x)
if scale < absx:
sumsq = 1.0 + sumsq * (scale / absx)**2
scale = absx
else:
sumsq += (absx / scale)**2
return scale * math.sqrt(sumsq)
I believe it does the right with infinities by magic (return math.inf). It returns 0.0 if no arguments are passed, which makes sense. For one argument, it's a convoluted way to return its absolute value. The "if x:" test is necessary to prevent division by 0.0 if the first argument is 0.0. It would need another blob of code to give up (and return math.nan) if one of the arguments is a NaN (there's no guessing what various C compilers would do without special-casing NaN).
I doubt `fsum()` would add much value here: all the addends have the same sign, so cancellation is impossible.
To get really gonzo, a single-rounding dot product would be the best building block (the vector norm is the square root of the dot product of a vector with itself). `fsum()` is a special case of that (the dot product of a vector with a same-length vector of all ones). |