Hypot

From HandWiki
Short description: Computationally safe computer function to calculate the hypotenuse of a right triangle

Hypot is a mathematical function defined to calculate the length of the hypotenuse of a right-angle triangle. It was designed to avoid errors arising due to limited-precision calculations performed on computers.

Motivation and usage

Calculating the length of the hypotenuse of a triangle is possible using the square-root function on the sum of two squares, but hypot(xy) avoids problems that occur when squaring very large or very small numbers.

The magnitude of the hypotenuse from (0, 0) to (xy) can be calculated using

[math]\displaystyle{ r = \sqrt{x^2 + y^2}. }[/math]

This operation is also known as Pythagorean addition.

However, the squares of very large or small values of x and y may exceed the range of machine precision when calculated on a computer, leading to an inaccurate result caused by arithmetic underflow and/or arithmetic overflow. The hypot function was designed to calculate the result without causing this problem.

The hypot function is often used together with the atan2 function to convert from Cartesian coordinates to polar coordinates:

r = hypot(xy),
θ = atan2(yx).

If either input is infinite, the result is infinite, i.e.

hypot(x, ±∞) = hypot(±∞, x) = +∞

Because this is true for all possible values of x, including infinity, the IEEE 754 floating-point standard requires that this definition also applies if x is not a number (NaN).[1]

Implementation

The difficulty with the naive implementation is that x2 or y2 may overflow or underflow, unless the intermediate result is computed with extended precision. A common implementation technique is to exchange the values, if necessary, so that |x| ≥ |y|, and then use the equivalent form[2]

[math]\displaystyle{ \begin{align} r &= \sqrt{x^2 + y^2} \\ &= \sqrt{x^2 \left( 1 + \left(\tfrac{y}{x}\right)^2\right)} \\ &= |x| \sqrt{1 + \left(\tfrac{y}{x}\right)^2} \left(= |x| + \frac{y}{|x|}\frac{y}{1 + \sqrt{1 + \left(\tfrac{y}{x}\right)^2 }}\right). \end{align} }[/math]

The computation of y/x cannot overflow unless both x and y are 0. If y/x underflows, the final result is equal to |x|, which is correct within the precision of the calculation. The square root is computed of a value between 1 and 2. Finally, the multiplication by |x| cannot underflow, and overflows only when the result is too large to represent.

This implementation has the downside that it requires an additional floating-point division, which can double the cost of the naive implementation, as multiplication and addition are typically far faster than division and square root.

More complex implementations avoid this by dividing the inputs into more cases:

  • xy: hypot(x, y) = |x|, to within machine precision.
  • x2 overflows: Multiply both x and y by a small scaling factor (e.g. 2−64 for IEEE single precision), use the naive algorithm which will now not overflow, and multiply the result by the (large) inverse (e.g. 264).
  • y2 underflows: As above, but reverse the scaling factors to scale up the intermediate values.
  • Otherwise: The naive algorithm is safe to use.

Additional techniques allow the result to be computed more accurately, e.g. to less than one ulp.[3]

Programming language support

The function is present in several programming languages:

See also

References

  1. "Floating point exception tracking and NAN propagation". 2020-04-27. p. 6. https://www.agner.org/optimize/nan_propagation.pdf#page=6. 
  2. In some situations, last form reduces calculation errors (in ULPs).
  3. Borges, Carlos F. (14 June 2019). "An Improved Algorithm for hypot(a,b)". arXiv:1904.09481 [math.NA].
  4. Cimpanu, Catalin. "CSS to get support for trigonometry functions" (in en). https://www.zdnet.com/article/css-to-get-support-for-trigonometry-functions/. 
  5. http://www.cplusplus.com/reference/cmath/hypot/
  6. https://dlang.org/phobos/std_math.html#.hypot
  7. https://docs.julialang.org/en/v1/base/math/#Base.Math.hypot
  8. https://docs.python.org/3/library/math.html#math.hypot
  9. https://developer.apple.com/DOCUMENTATION/mac/PPCNumerics/PPCNumerics-141.html
  10. http://nl.mathworks.com/help/matlab/ref/hypot.html
  11. http://www.frameworkpascal.com/helphtml/hypot_func.htm
  12. http://www.php.net/hypot
  13. http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Math.html#hypot(double,%20double)
  14. "hypot - Kotlin Programming Language". https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.math/hypot.html. 
  15. http://ruby-doc.org/core/Math.html#method-c-hypot
  16. http://golang.org/pkg/math/#Hypot
  17. https://doc.rust-lang.org/std/primitive.f64.html#method.hypot
  18. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/hypot
  19. Single Unix Specification, Open Group, http://www.opengroup.org/onlinepubs/007908799/xsh/hypot.html
  20. IBM, ILE C/C++ Run-Time Library Functions, http://publib.boulder.ibm.com/infocenter/iadthelp/v7r0/index.jsp?topic=/com.ibm.etools.iseries.langref.doc/rzan5mst144.htm
  21. The GNU C Library, Mathematics, http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_17.html
  22. https://www.scala-lang.org/api/current/scala/math/index.html#hypot(x:Double,y:Double):Double