11dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* e_expf.c -- float version of e_exp.c. 21dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. 31dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 41dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 51dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* 61dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * ==================================================== 71dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. 81dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 91dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Developed at SunPro, a Sun Microsystems, Inc. business. 101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Permission to use, copy, modify, and distribute this 111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * software is freely granted, provided that this notice 121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * is preserved. 131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * ==================================================== 141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifndef lint 171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic char rcsid[] = "$FreeBSD: src/lib/msun/src/e_expf.c,v 1.10 2005/11/30 04:56:49 bde Exp $"; 181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif 191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include "math.h" 211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include "math_private.h" 221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic const float 241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectone = 1.0, 251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source ProjecthalF[2] = {0.5,-0.5,}, 261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projecthuge = 1.0e+30, 271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projecttwom100 = 7.8886090522e-31, /* 2**-100=0x0d800000 */ 281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projecto_threshold= 8.8721679688e+01, /* 0x42b17180 */ 291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectu_threshold= -1.0397208405e+02, /* 0xc2cff1b5 */ 301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectln2HI[2] ={ 6.9314575195e-01, /* 0x3f317200 */ 311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project -6.9314575195e-01,}, /* 0xbf317200 */ 321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectln2LO[2] ={ 1.4286067653e-06, /* 0x35bfbe8e */ 331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project -1.4286067653e-06,}, /* 0xb5bfbe8e */ 341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectinvln2 = 1.4426950216e+00, /* 0x3fb8aa3b */ 351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source ProjectP1 = 1.6666667163e-01, /* 0x3e2aaaab */ 361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source ProjectP2 = -2.7777778450e-03, /* 0xbb360b61 */ 371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source ProjectP3 = 6.6137559770e-05, /* 0x388ab355 */ 381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source ProjectP4 = -1.6533901999e-06, /* 0xb5ddea0e */ 391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source ProjectP5 = 4.1381369442e-08; /* 0x3331bb4c */ 401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectfloat 421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project__ieee754_expf(float x) /* default IEEE double exp */ 431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project float y,hi=0.0,lo=0.0,c,t; 451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int32_t k=0,xsb; 461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project u_int32_t hx; 471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project GET_FLOAT_WORD(hx,x); 491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project xsb = (hx>>31)&1; /* sign bit of x */ 501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project hx &= 0x7fffffff; /* high word of |x| */ 511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* filter out non-finite argument */ 531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if(hx >= 0x42b17218) { /* if |x|>=88.721... */ 541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if(hx>0x7f800000) 551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return x+x; /* NaN */ 561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if(hx==0x7f800000) 571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (xsb==0)? x:0.0; /* exp(+-inf)={inf,0} */ 581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if(x > o_threshold) return huge*huge; /* overflow */ 591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if(x < u_threshold) return twom100*twom100; /* underflow */ 601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* argument reduction */ 631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if(hx > 0x3eb17218) { /* if |x| > 0.5 ln2 */ 641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if(hx < 0x3F851592) { /* and |x| < 1.5 ln2 */ 651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project hi = x-ln2HI[xsb]; lo=ln2LO[xsb]; k = 1-xsb-xsb; 661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } else { 671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project k = invln2*x+halF[xsb]; 681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project t = k; 691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project hi = x - t*ln2HI[0]; /* t*ln2HI is exact here */ 701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project lo = t*ln2LO[0]; 711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project x = hi - lo; 731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project else if(hx < 0x31800000) { /* when |x|<2**-28 */ 751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if(huge+x>one) return one+x;/* trigger inexact */ 761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project else k = 0; 781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* x is now in primary range */ 801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project t = x*x; 811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project c = x - t*(P1+t*(P2+t*(P3+t*(P4+t*P5)))); 821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if(k==0) return one-((x*c)/(c-(float)2.0)-x); 831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project else y = one-((lo-(x*c)/((float)2.0-c))-hi); 841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if(k >= -125) { 851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project u_int32_t hy; 861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project GET_FLOAT_WORD(hy,y); 871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project SET_FLOAT_WORD(y,hy+(k<<23)); /* add k to y's exponent */ 881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return y; 891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } else { 901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project u_int32_t hy; 911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project GET_FLOAT_WORD(hy,y); 921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project SET_FLOAT_WORD(y,hy+((k+100)<<23)); /* add k to y's exponent */ 931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return y*twom100; 941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 96