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 16a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#include <sys/cdefs.h> 17a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes__FBSDID("$FreeBSD$"); 18a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes 19a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#include <float.h> 201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include "math.h" 221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include "math_private.h" 231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic const float 251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectone = 1.0, 261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source ProjecthalF[2] = {0.5,-0.5,}, 271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projecto_threshold= 8.8721679688e+01, /* 0x42b17180 */ 281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectu_threshold= -1.0397208405e+02, /* 0xc2cff1b5 */ 291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectln2HI[2] ={ 6.9314575195e-01, /* 0x3f317200 */ 301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project -6.9314575195e-01,}, /* 0xbf317200 */ 311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectln2LO[2] ={ 1.4286067653e-06, /* 0x35bfbe8e */ 321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project -1.4286067653e-06,}, /* 0xb5bfbe8e */ 331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectinvln2 = 1.4426950216e+00, /* 0x3fb8aa3b */ 34a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes/* 35a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes * Domain [-0.34568, 0.34568], range ~[-4.278e-9, 4.447e-9]: 36a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes * |x*(exp(x)+1)/(exp(x)-1) - p(x)| < 2**-27.74 37a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes */ 38a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott HughesP1 = 1.6666625440e-1, /* 0xaaaa8f.0p-26 */ 39a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott HughesP2 = -2.7667332906e-3; /* -0xb55215.0p-32 */ 40a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes 4178419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughesstatic volatile float 4278419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hugheshuge = 1.0e+30, 4378419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughestwom100 = 7.8886090522e-31; /* 2**-100=0x0d800000 */ 441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectfloat 46a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes__ieee754_expf(float x) 471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 48a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes float y,hi=0.0,lo=0.0,c,t,twopk; 491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int32_t k=0,xsb; 501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project u_int32_t hx; 511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project GET_FLOAT_WORD(hx,x); 531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project xsb = (hx>>31)&1; /* sign bit of x */ 541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project hx &= 0x7fffffff; /* high word of |x| */ 551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* filter out non-finite argument */ 571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if(hx >= 0x42b17218) { /* if |x|>=88.721... */ 581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if(hx>0x7f800000) 591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return x+x; /* NaN */ 601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if(hx==0x7f800000) 611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (xsb==0)? x:0.0; /* exp(+-inf)={inf,0} */ 621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if(x > o_threshold) return huge*huge; /* overflow */ 631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if(x < u_threshold) return twom100*twom100; /* underflow */ 641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* argument reduction */ 671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if(hx > 0x3eb17218) { /* if |x| > 0.5 ln2 */ 681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if(hx < 0x3F851592) { /* and |x| < 1.5 ln2 */ 691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project hi = x-ln2HI[xsb]; lo=ln2LO[xsb]; k = 1-xsb-xsb; 701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } else { 711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project k = invln2*x+halF[xsb]; 721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project t = k; 731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project hi = x - t*ln2HI[0]; /* t*ln2HI is exact here */ 741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project lo = t*ln2LO[0]; 751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 76a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes STRICT_ASSIGN(float, x, hi - lo); 771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 78a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes else if(hx < 0x39000000) { /* when |x|<2**-14 */ 791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if(huge+x>one) return one+x;/* trigger inexact */ 801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project else k = 0; 821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* x is now in primary range */ 841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project t = x*x; 85a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes if(k >= -125) 86a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes SET_FLOAT_WORD(twopk,0x3f800000+(k<<23)); 87a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes else 88a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes SET_FLOAT_WORD(twopk,0x3f800000+((k+100)<<23)); 89a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes c = x - t*(P1+t*P2); 901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if(k==0) return one-((x*c)/(c-(float)2.0)-x); 911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project else y = one-((lo-(x*c)/((float)2.0-c))-hi); 921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if(k >= -125) { 93a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes if(k==128) return y*2.0F*0x1p127F; 94a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes return y*twopk; 951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } else { 96a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes return y*twopk*twom100; 971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 99