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