1df930be7Sderaadt /* e_sqrtf.c -- float version of e_sqrt.c.
2df930be7Sderaadt * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
3df930be7Sderaadt */
4df930be7Sderaadt
5df930be7Sderaadt /*
6df930be7Sderaadt * ====================================================
7df930be7Sderaadt * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
8df930be7Sderaadt *
9df930be7Sderaadt * Developed at SunPro, a Sun Microsystems, Inc. business.
10df930be7Sderaadt * Permission to use, copy, modify, and distribute this
11df930be7Sderaadt * software is freely granted, provided that this notice
12df930be7Sderaadt * is preserved.
13df930be7Sderaadt * ====================================================
14df930be7Sderaadt */
15df930be7Sderaadt
16df930be7Sderaadt #include "math.h"
17df930be7Sderaadt #include "math_private.h"
18df930be7Sderaadt
19df930be7Sderaadt static const float one = 1.0, tiny=1.0e-30;
20df930be7Sderaadt
21e7beb4a7Smillert float
sqrtf(float x)227b36286aSmartynas sqrtf(float x)
23df930be7Sderaadt {
24df930be7Sderaadt float z;
25df930be7Sderaadt int32_t sign = (int)0x80000000;
26df930be7Sderaadt int32_t ix,s,q,m,t,i;
27df930be7Sderaadt u_int32_t r;
28df930be7Sderaadt
29df930be7Sderaadt GET_FLOAT_WORD(ix,x);
30df930be7Sderaadt
31df930be7Sderaadt /* take care of Inf and NaN */
32df930be7Sderaadt if((ix&0x7f800000)==0x7f800000) {
33df930be7Sderaadt return x*x+x; /* sqrt(NaN)=NaN, sqrt(+inf)=+inf
34df930be7Sderaadt sqrt(-inf)=sNaN */
35df930be7Sderaadt }
36df930be7Sderaadt /* take care of zero */
37df930be7Sderaadt if(ix<=0) {
38df930be7Sderaadt if((ix&(~sign))==0) return x;/* sqrt(+-0) = +-0 */
39df930be7Sderaadt else if(ix<0)
40df930be7Sderaadt return (x-x)/(x-x); /* sqrt(-ve) = sNaN */
41df930be7Sderaadt }
42df930be7Sderaadt /* normalize x */
43df930be7Sderaadt m = (ix>>23);
44df930be7Sderaadt if(m==0) { /* subnormal x */
45df930be7Sderaadt for(i=0;(ix&0x00800000)==0;i++) ix<<=1;
46df930be7Sderaadt m -= i-1;
47df930be7Sderaadt }
48df930be7Sderaadt m -= 127; /* unbias exponent */
49df930be7Sderaadt ix = (ix&0x007fffff)|0x00800000;
50df930be7Sderaadt if(m&1) /* odd m, double x to make it even */
51df930be7Sderaadt ix += ix;
52df930be7Sderaadt m >>= 1; /* m = [m/2] */
53df930be7Sderaadt
54df930be7Sderaadt /* generate sqrt(x) bit by bit */
55df930be7Sderaadt ix += ix;
56df930be7Sderaadt q = s = 0; /* q = sqrt(x) */
57df930be7Sderaadt r = 0x01000000; /* r = moving bit from right to left */
58df930be7Sderaadt
59df930be7Sderaadt while(r!=0) {
60df930be7Sderaadt t = s+r;
61df930be7Sderaadt if(t<=ix) {
62df930be7Sderaadt s = t+r;
63df930be7Sderaadt ix -= t;
64df930be7Sderaadt q += r;
65df930be7Sderaadt }
66df930be7Sderaadt ix += ix;
67df930be7Sderaadt r>>=1;
68df930be7Sderaadt }
69df930be7Sderaadt
70df930be7Sderaadt /* use floating add to find out rounding direction */
71df930be7Sderaadt if(ix!=0) {
72df930be7Sderaadt z = one-tiny; /* trigger inexact flag */
73df930be7Sderaadt if (z>=one) {
74df930be7Sderaadt z = one+tiny;
75df930be7Sderaadt if (z>one)
76df930be7Sderaadt q += 2;
77df930be7Sderaadt else
78df930be7Sderaadt q += (q&1);
79df930be7Sderaadt }
80df930be7Sderaadt }
81df930be7Sderaadt ix = (q>>1)+0x3f000000;
82df930be7Sderaadt ix += (m <<23);
83df930be7Sderaadt SET_FLOAT_WORD(z,ix);
84df930be7Sderaadt return z;
85df930be7Sderaadt }
86*2f2c0062Sguenther DEF_STD(sqrtf);
87