xref: /openbsd-src/lib/libm/src/e_sqrtf.c (revision 2f2c00629eff6a304ebffb255fc56f4fa7a1833b)
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