Comment #3 on issue 8909 by
alb.doni...@gmail.com: math: math.Hypot returns
incorrect result
https://code.google.com/p/go/issues/detail?id=8909
G. W. Stewart in "Matrix Algorithms: Volume 1", SIAM 1998, pages 139 and
144, cited by B. Einarsson
in "Accuracy and Reliability in Scientific Computing", SIAM 2005, page 48,
suggest using
s = p + q
hypot(p, q) = s * math.Sqrt((p/s)*(p/s) + (q/s)*(q/s))
so, scaling with p+q instead of max{|p|, |q|}, because (I cite from the
former)
"If the scale factor s in the algorithm [..] is replaced by max{|a|, |b|},
the results
may be less accurate on a hexadecimal machine. The reason is that the number
sqrt((a/s)^2 + (b/s)^2) [equivalent to our q = q / p; return p *
math.Sqrt(1+q*q); ndr]
is a little bit greater than one [iff min{a,b} is small? I think, ndr] so
that the leading three bits
in its representation are zero."
Scaling with s = a + b returns the correct number in this case:
http://play.golang.org/p/P0GduYlgQ-
and also provides protection against [over|under]flow.
If we don't want to port the (rather complicated) libc hypot(), maybe the
suggested alternative
expression would be a better "simple but good enough" implementation than
the current one.
This claim should be tested, though.