13a8617a8SJordan K. Hubbard /* e_logf.c -- float version of e_log.c. 23a8617a8SJordan K. Hubbard * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. 33a8617a8SJordan K. Hubbard */ 43a8617a8SJordan K. Hubbard 53a8617a8SJordan K. Hubbard /* 63a8617a8SJordan K. Hubbard * ==================================================== 73a8617a8SJordan K. Hubbard * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. 83a8617a8SJordan K. Hubbard * 93a8617a8SJordan K. Hubbard * Developed at SunPro, a Sun Microsystems, Inc. business. 103a8617a8SJordan K. Hubbard * Permission to use, copy, modify, and distribute this 113a8617a8SJordan K. Hubbard * software is freely granted, provided that this notice 123a8617a8SJordan K. Hubbard * is preserved. 133a8617a8SJordan K. Hubbard * ==================================================== 143a8617a8SJordan K. Hubbard */ 153a8617a8SJordan K. Hubbard 165aa554c7SDavid Schultz #include <sys/cdefs.h> 175aa554c7SDavid Schultz __FBSDID("$FreeBSD$"); 183a8617a8SJordan K. Hubbard 193a8617a8SJordan K. Hubbard #include "math.h" 203a8617a8SJordan K. Hubbard #include "math_private.h" 213a8617a8SJordan K. Hubbard 223a8617a8SJordan K. Hubbard static const float 233a8617a8SJordan K. Hubbard ln2_hi = 6.9313812256e-01, /* 0x3f317180 */ 243a8617a8SJordan K. Hubbard ln2_lo = 9.0580006145e-06, /* 0x3717f7d1 */ 253a8617a8SJordan K. Hubbard two25 = 3.355443200e+07, /* 0x4c000000 */ 26d4a74de9SBruce Evans /* |(log(1+s)-log(1-s))/s - Lg(s)| < 2**-34.24 (~[-4.95e-11, 4.97e-11]). */ 27d4a74de9SBruce Evans Lg1 = 0xaaaaaa.0p-24, /* 0.66666662693 */ 28d4a74de9SBruce Evans Lg2 = 0xccce13.0p-25, /* 0.40000972152 */ 29d4a74de9SBruce Evans Lg3 = 0x91e9ee.0p-25, /* 0.28498786688 */ 30d4a74de9SBruce Evans Lg4 = 0xf89e26.0p-26; /* 0.24279078841 */ 313a8617a8SJordan K. Hubbard 323a8617a8SJordan K. Hubbard static const float zero = 0.0; 337dbbb6ddSDavid Schultz static volatile float vzero = 0.0; 343a8617a8SJordan K. Hubbard 3559b19ff1SAlfred Perlstein float 36*99843eb8SSteve Kargl logf(float x) 373a8617a8SJordan K. Hubbard { 383a8617a8SJordan K. Hubbard float hfsq,f,s,z,R,w,t1,t2,dk; 393a8617a8SJordan K. Hubbard int32_t k,ix,i,j; 403a8617a8SJordan K. Hubbard 413a8617a8SJordan K. Hubbard GET_FLOAT_WORD(ix,x); 423a8617a8SJordan K. Hubbard 433a8617a8SJordan K. Hubbard k=0; 443a8617a8SJordan K. Hubbard if (ix < 0x00800000) { /* x < 2**-126 */ 453a8617a8SJordan K. Hubbard if ((ix&0x7fffffff)==0) 467dbbb6ddSDavid Schultz return -two25/vzero; /* log(+-0)=-inf */ 473a8617a8SJordan K. Hubbard if (ix<0) return (x-x)/zero; /* log(-#) = NaN */ 483a8617a8SJordan K. Hubbard k -= 25; x *= two25; /* subnormal number, scale up x */ 493a8617a8SJordan K. Hubbard GET_FLOAT_WORD(ix,x); 503a8617a8SJordan K. Hubbard } 513a8617a8SJordan K. Hubbard if (ix >= 0x7f800000) return x+x; 523a8617a8SJordan K. Hubbard k += (ix>>23)-127; 533a8617a8SJordan K. Hubbard ix &= 0x007fffff; 543a8617a8SJordan K. Hubbard i = (ix+(0x95f64<<3))&0x800000; 553a8617a8SJordan K. Hubbard SET_FLOAT_WORD(x,ix|(i^0x3f800000)); /* normalize x or x/2 */ 563a8617a8SJordan K. Hubbard k += (i>>23); 573a8617a8SJordan K. Hubbard f = x-(float)1.0; 58d79d610dSBruce Evans if((0x007fffff&(0x8000+ix))<0xc000) { /* -2**-9 <= f < 2**-9 */ 59ee0730e6SDavid Schultz if(f==zero) { 60ee0730e6SDavid Schultz if(k==0) { 61ee0730e6SDavid Schultz return zero; 62ee0730e6SDavid Schultz } else { 63ee0730e6SDavid Schultz dk=(float)k; 64ee0730e6SDavid Schultz return dk*ln2_hi+dk*ln2_lo; 65ee0730e6SDavid Schultz } 66ee0730e6SDavid Schultz } 673a8617a8SJordan K. Hubbard R = f*f*((float)0.5-(float)0.33333333333333333*f); 683a8617a8SJordan K. Hubbard if(k==0) return f-R; else {dk=(float)k; 693a8617a8SJordan K. Hubbard return dk*ln2_hi-((R-dk*ln2_lo)-f);} 703a8617a8SJordan K. Hubbard } 713a8617a8SJordan K. Hubbard s = f/((float)2.0+f); 723a8617a8SJordan K. Hubbard dk = (float)k; 733a8617a8SJordan K. Hubbard z = s*s; 743a8617a8SJordan K. Hubbard i = ix-(0x6147a<<3); 753a8617a8SJordan K. Hubbard w = z*z; 763a8617a8SJordan K. Hubbard j = (0x6b851<<3)-ix; 77d4a74de9SBruce Evans t1= w*(Lg2+w*Lg4); 78d4a74de9SBruce Evans t2= z*(Lg1+w*Lg3); 793a8617a8SJordan K. Hubbard i |= j; 803a8617a8SJordan K. Hubbard R = t2+t1; 813a8617a8SJordan K. Hubbard if(i>0) { 823a8617a8SJordan K. Hubbard hfsq=(float)0.5*f*f; 833a8617a8SJordan K. Hubbard if(k==0) return f-(hfsq-s*(hfsq+R)); else 843a8617a8SJordan K. Hubbard return dk*ln2_hi-((hfsq-(s*(hfsq+R)+dk*ln2_lo))-f); 853a8617a8SJordan K. Hubbard } else { 863a8617a8SJordan K. Hubbard if(k==0) return f-s*(f-R); else 873a8617a8SJordan K. Hubbard return dk*ln2_hi-((s*(f-R)-dk*ln2_lo)-f); 883a8617a8SJordan K. Hubbard } 893a8617a8SJordan K. Hubbard } 90