e_sqrtf.c revision 97413
12116Sjkh/* e_sqrtf.c -- float version of e_sqrt.c. 22116Sjkh * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. 32116Sjkh */ 42116Sjkh 52116Sjkh/* 62116Sjkh * ==================================================== 72116Sjkh * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. 82116Sjkh * 92116Sjkh * Developed at SunPro, a Sun Microsystems, Inc. business. 102116Sjkh * Permission to use, copy, modify, and distribute this 118870Srgrimes * software is freely granted, provided that this notice 122116Sjkh * is preserved. 132116Sjkh * ==================================================== 142116Sjkh */ 152116Sjkh 162116Sjkh#ifndef lint 1750476Speterstatic char rcsid[] = "$FreeBSD: head/lib/msun/src/e_sqrtf.c 97413 2002-05-28 18:15:04Z alfred $"; 182116Sjkh#endif 192116Sjkh 202116Sjkh#include "math.h" 212116Sjkh#include "math_private.h" 222116Sjkh 232116Sjkhstatic const float one = 1.0, tiny=1.0e-30; 242116Sjkh 2597413Salfredfloat 2697413Salfred__ieee754_sqrtf(float x) 272116Sjkh{ 282116Sjkh float z; 298870Srgrimes int32_t sign = (int)0x80000000; 302116Sjkh int32_t ix,s,q,m,t,i; 312116Sjkh u_int32_t r; 322116Sjkh 332116Sjkh GET_FLOAT_WORD(ix,x); 342116Sjkh 352116Sjkh /* take care of Inf and NaN */ 368870Srgrimes if((ix&0x7f800000)==0x7f800000) { 372116Sjkh return x*x+x; /* sqrt(NaN)=NaN, sqrt(+inf)=+inf 382116Sjkh sqrt(-inf)=sNaN */ 398870Srgrimes } 402116Sjkh /* take care of zero */ 412116Sjkh if(ix<=0) { 422116Sjkh if((ix&(~sign))==0) return x;/* sqrt(+-0) = +-0 */ 432116Sjkh else if(ix<0) 442116Sjkh return (x-x)/(x-x); /* sqrt(-ve) = sNaN */ 452116Sjkh } 462116Sjkh /* normalize x */ 472116Sjkh m = (ix>>23); 482116Sjkh if(m==0) { /* subnormal x */ 492116Sjkh for(i=0;(ix&0x00800000)==0;i++) ix<<=1; 502116Sjkh m -= i-1; 512116Sjkh } 522116Sjkh m -= 127; /* unbias exponent */ 532116Sjkh ix = (ix&0x007fffff)|0x00800000; 542116Sjkh if(m&1) /* odd m, double x to make it even */ 552116Sjkh ix += ix; 562116Sjkh m >>= 1; /* m = [m/2] */ 572116Sjkh 582116Sjkh /* generate sqrt(x) bit by bit */ 592116Sjkh ix += ix; 602116Sjkh q = s = 0; /* q = sqrt(x) */ 612116Sjkh r = 0x01000000; /* r = moving bit from right to left */ 622116Sjkh 632116Sjkh while(r!=0) { 648870Srgrimes t = s+r; 658870Srgrimes if(t<=ix) { 668870Srgrimes s = t+r; 678870Srgrimes ix -= t; 688870Srgrimes q += r; 698870Srgrimes } 702116Sjkh ix += ix; 712116Sjkh r>>=1; 722116Sjkh } 732116Sjkh 742116Sjkh /* use floating add to find out rounding direction */ 752116Sjkh if(ix!=0) { 762116Sjkh z = one-tiny; /* trigger inexact flag */ 772116Sjkh if (z>=one) { 782116Sjkh z = one+tiny; 792116Sjkh if (z>one) 802116Sjkh q += 2; 812116Sjkh else 822116Sjkh q += (q&1); 832116Sjkh } 842116Sjkh } 852116Sjkh ix = (q>>1)+0x3f000000; 862116Sjkh ix += (m <<23); 872116Sjkh SET_FLOAT_WORD(z,ix); 882116Sjkh return z; 892116Sjkh} 90