4 * Compute the length of the hypotenuse of a right triangle, given the
5 * lengths of the two perpendicular sides.
9 * Written by Keith Marshall <keithmarshall@users.sourceforge.net>
10 * Copyright 2015, MinGW.org Project
13 * Permission is hereby granted, free of charge, to any person obtaining a
14 * copy of this software and associated documentation files (the "Software"),
15 * to deal in the Software without restriction, including without limitation
16 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
17 * and/or sell copies of the Software, and to permit persons to whom the
18 * Software is furnished to do so, subject to the following conditions:
20 * The above copyright notice and this permission notice (including the next
21 * paragraph) shall be included in all copies or substantial portions of the
24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
27 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
29 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
30 * DEALINGS IN THE SOFTWARE.
33 * This module should be compiled separately for each supported function:
35 * gcc -D FUNCTION=hypot -o hypot.o hypot_generic.c
36 * gcc -D FUNCTION=hypotl -o hypotl.o hypot_generic.c
37 * gcc -D FUNCTION=hypotf -o hypotf.o hypot_generic.c
45 /* If user neglected to specify it, the default compilation is for
46 * the hypot() function.
48 # define FUNCTION hypot
51 #define argtype_hypot double
52 #define argtype_hypotl long double
53 #define argtype_hypotf float
55 #define PASTE(PREFIX,SUFFIX) PREFIX##SUFFIX
56 #define mapname(PREFIX,SUFFIX) PASTE(PREFIX,SUFFIX)
58 #define ARGTYPE(FUNCTION) PASTE(argtype_,FUNCTION)
59 #define ARGCAST(VALUE) mapname(argcast_,FUNCTION)(VALUE)
61 #define argcast_hypot(VALUE) VALUE
62 #define argcast_hypotl(VALUE) PASTE(VALUE,L)
63 #define argcast_hypotf(VALUE) PASTE(VALUE,F)
65 #define mapfunc(NAME) mapname(mapfunc_,FUNCTION)(NAME)
67 #define mapfunc_hypot(NAME) NAME
68 #define mapfunc_hypotl(NAME) PASTE(NAME,l)
69 #define mapfunc_hypotf(NAME) PASTE(NAME,f)
71 #define hypot_argval_max DBL_MAX
72 #define hypotf_argval_max FLT_MAX
73 #define hypotl_argval_max LDBL_MAX
75 #define hypot_result_overflow HUGE_VAL
76 #define hypotf_result_overflow HUGE_VALF
77 #define hypotl_result_overflow HUGE_VALL
79 /* Prefer fast version of the sqrt() function.
82 #define sqrt __fast_sqrt
84 /* Define the generic function implementation.
87 ARGTYPE(FUNCTION) FUNCTION( ARGTYPE(FUNCTION) x, ARGTYPE(FUNCTION) y )
91 * By default, we implement the actual computation for the
92 * hypotl() function only, (since only METHODL is explicitly
93 * defined as non-zero); to do likewise for the hypot() and
94 * hypotf() functions, compile with -D METHOD and -D METHODF
98 if( isfinite(x) && isfinite(y) )
100 /* For all finite values of x and y, we may compute hypot(x,y)
101 * in terms of their respective magnitudes; we apply Pythagoras'
102 * theorum, but to avoid a possible overflow when computing the
103 * sum of the squares of x and y, we use a transformed variant
104 * of the conventional formula, based on the assumption that
105 * the arguments are ordered such that |x| >= |y|...
108 if( (h = x = mapfunc(fabs)( x )) < (y = mapfunc(fabs)( y )) )
110 /* ...otherwise, we transpose them.
114 /* After ensuring that |x| >= |y|, we must perform one more
115 * sanity check to ensure that we don't have |x| == 0.0, (in
116 * which case |y| must also be 0.0, and the quotient |y|/|x|
117 * becomes indeterminate).
119 if( x == ARGCAST(0.0) )
121 * For this specific case, we may avoid the need to compute
122 * the indeterminate quotient, by simple evaluation of the
123 * normal expression of Pythagoras' theorum:
125 * hypot = sqrt( x * x + y * y )
127 * directly, to obtain the expected result of zero.
131 /* We can now be confident that the ratio...
135 * ...is determinate, and must lie in the range 0.0 .. 1.0, so
136 * we may safely compute the overflow protected transformation
137 * of the expression of Pythagoras' theorum:
139 * hypot = x * sqrt( 1.0 + (y / x) * (y / x))
141 * without any possibility of overflow, when squaring the y / x
142 * ratio term; however, there is still a slight possibility that
143 * x itself is so large that multiplication by the square root
144 * term, (which must lie in the range 1.0 .. sqrt(2.0)), may
145 * cause overflow in the final result...
147 h = mapfunc(sqrt)( ARGCAST(1.0) + h * h );
148 if( x > (mapname(FUNCTION,_argval_max) / h) )
150 /* ...in which case, we set errno, and return the appropriate
151 * representation of HUGE_VAL...
154 return mapname(FUNCTION,_result_overflow);
156 /* ...otherwise, we may compute and return the requisite result;
157 * we may be certain that this is unaffected by OVERFLOW. On the
158 * other hand, UNDERFLOW may have occurred in the intermediate
159 * computation of y/x; however, the effect is insignificant.
163 /* If we get to here, one or both of x and y was indefinite; POSIX
164 * requires us to return +inf, if either x or y is infinite, (even
165 * if the other is nan)...
167 if( isinf( x ) ) return mapfunc(copysign)( x, ARGCAST(+1.0) );
168 if( isinf( y ) ) return mapfunc(copysign)( y, ARGCAST(+1.0) );
170 * ...otherwise, combine them to force an indefinite result.
175 /* For the hypot() and hypotf() implementations, we prefer to
176 * compute an intermediate result in the long double domain...
178 long double intermediate = hypotl( (long double)(x), (long double)(y) );
180 /* ...then check that this may be represented within the
181 * effective domain of the return data type...
183 if( isfinite( intermediate )
184 && (intermediate > (long double)(mapname(FUNCTION,_argval_max))) )
186 /* ...otherwise flag a RANGE error, and return the
187 * appropriate representation of HUGE_VAL...
190 return mapname(FUNCTION,_result_overflow);
192 /* ...or the valid imtermediate result, cast to the
193 * appropriate data type for the function.
195 return (ARGTYPE(FUNCTION))(intermediate);
200 /* $RCSfile$: end of file */