xref: /netbsd-src/external/gpl3/gcc.old/dist/libquadmath/math/sqrtq.c (revision 627f7eb200a4419d89b531d55fccd2ee3ffdcde0)
1*627f7eb2Smrg #include "quadmath-imp.h"
2*627f7eb2Smrg #include <math.h>
3*627f7eb2Smrg #include <float.h>
4*627f7eb2Smrg 
5*627f7eb2Smrg __float128
sqrtq(const __float128 x)6*627f7eb2Smrg sqrtq (const __float128 x)
7*627f7eb2Smrg {
8*627f7eb2Smrg   __float128 y;
9*627f7eb2Smrg   int exp;
10*627f7eb2Smrg 
11*627f7eb2Smrg   if (isnanq (x) || (isinfq (x) && x > 0))
12*627f7eb2Smrg     return x;
13*627f7eb2Smrg 
14*627f7eb2Smrg   if (x == 0)
15*627f7eb2Smrg     return x;
16*627f7eb2Smrg 
17*627f7eb2Smrg   if (x < 0)
18*627f7eb2Smrg     {
19*627f7eb2Smrg       /* Return NaN with invalid signal.  */
20*627f7eb2Smrg       return (x - x) / (x - x);
21*627f7eb2Smrg     }
22*627f7eb2Smrg 
23*627f7eb2Smrg   if (x <= DBL_MAX && x >= DBL_MIN)
24*627f7eb2Smrg   {
25*627f7eb2Smrg     /* Use double result as starting point.  */
26*627f7eb2Smrg     y = sqrt ((double) x);
27*627f7eb2Smrg 
28*627f7eb2Smrg     /* Two Newton iterations.  */
29*627f7eb2Smrg     y -= 0.5q * (y - x / y);
30*627f7eb2Smrg     y -= 0.5q * (y - x / y);
31*627f7eb2Smrg     return y;
32*627f7eb2Smrg   }
33*627f7eb2Smrg 
34*627f7eb2Smrg #ifdef HAVE_SQRTL
35*627f7eb2Smrg   {
36*627f7eb2Smrg     long double xl = (long double) x;
37*627f7eb2Smrg     if (xl <= LDBL_MAX && xl >= LDBL_MIN)
38*627f7eb2Smrg       {
39*627f7eb2Smrg 	/* Use long double result as starting point.  */
40*627f7eb2Smrg 	y = (__float128) sqrtl (xl);
41*627f7eb2Smrg 
42*627f7eb2Smrg 	/* One Newton iteration.  */
43*627f7eb2Smrg 	y -= 0.5q * (y - x / y);
44*627f7eb2Smrg 	return y;
45*627f7eb2Smrg       }
46*627f7eb2Smrg   }
47*627f7eb2Smrg #endif
48*627f7eb2Smrg 
49*627f7eb2Smrg   /* If we're outside of the range of C types, we have to compute
50*627f7eb2Smrg      the initial guess the hard way.  */
51*627f7eb2Smrg   y = frexpq (x, &exp);
52*627f7eb2Smrg   if (exp % 2)
53*627f7eb2Smrg     y *= 2, exp--;
54*627f7eb2Smrg 
55*627f7eb2Smrg   y = sqrt (y);
56*627f7eb2Smrg   y = scalbnq (y, exp / 2);
57*627f7eb2Smrg 
58*627f7eb2Smrg   /* Two Newton iterations.  */
59*627f7eb2Smrg   y -= 0.5q * (y - x / y);
60*627f7eb2Smrg   y -= 0.5q * (y - x / y);
61*627f7eb2Smrg   return y;
62*627f7eb2Smrg }
63*627f7eb2Smrg 
64