1 /* ef_sqrtf.c -- float version of e_sqrt.c.
2  * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
3  */
4 
5 /*
6  * ====================================================
7  * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
8  *
9  * Developed at SunPro, a Sun Microsystems, Inc. business.
10  * Permission to use, copy, modify, and distribute this
11  * software is freely granted, provided that this notice
12  * is preserved.
13  * ====================================================
14  */
15 
16 #include "fdlibm.h"
17 
18 float
sqrtf(float x)19 sqrtf(float x)
20 {
21     float z;
22     __uint32_t r, hx;
23     __int32_t ix, s, q, m, t, i;
24 
25     GET_FLOAT_WORD(ix, x);
26     hx = ix & 0x7fffffff;
27 
28     /* take care of Inf and NaN */
29     if (!FLT_UWORD_IS_FINITE(hx)) {
30         if (ix < 0 && !isnanf(x))
31             return __math_invalidf(x); /* sqrt(-inf)=sNaN */
32         return x + x; /* sqrt(NaN)=NaN, sqrt(+inf)=+inf */
33     }
34 
35     /* take care of zero and -ves */
36     if (FLT_UWORD_IS_ZERO(hx))
37         return x; /* sqrt(+-0) = +-0 */
38     if (ix < 0)
39         return __math_invalidf(x); /* sqrt(-ve) = sNaN */
40 
41     /* normalize x */
42     m = (ix >> 23);
43     if (FLT_UWORD_IS_SUBNORMAL(hx)) { /* subnormal x */
44         for (i = 0; (ix & 0x00800000L) == 0; i++)
45             ix <<= 1;
46         m -= i - 1;
47     }
48     m -= 127; /* unbias exponent */
49     ix = (ix & 0x007fffffL) | 0x00800000L;
50     if (m & 1) /* odd m, double x to make it even */
51         ix += ix;
52     m >>= 1; /* m = [m/2] */
53 
54     /* generate sqrt(x) bit by bit */
55     ix += ix;
56     q = s = 0; /* q = sqrt(x) */
57     r = 0x01000000L; /* r = moving bit from right to left */
58 
59     while (r != 0) {
60         t = s + r;
61         if (t <= ix) {
62             s = t + r;
63             ix -= t;
64             q += r;
65         }
66         ix += ix;
67         r >>= 1;
68     }
69 
70     if (ix != 0) {
71         FE_DECL_ROUND(rnd);
72         if (__is_nearest(rnd))
73             q += (q & 1);
74         else if (__is_upward(rnd))
75             q += 2;
76     }
77     ix = (q >> 1) + 0x3f000000L;
78     ix += (m << 23);
79     SET_FLOAT_WORD(z, ix);
80     return z;
81 }
82 
83 _MATH_ALIAS_f_f(sqrt)
84