11dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* s_log1pf.c -- float version of s_log1p.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 Projectln2_hi =   6.9313812256e-01,	/* 0x3f317180 */
261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectln2_lo =   9.0580006145e-06,	/* 0x3717f7d1 */
271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projecttwo25 =    3.355443200e+07,	/* 0x4c000000 */
281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source ProjectLp1 = 6.6666668653e-01,	/* 3F2AAAAB */
291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source ProjectLp2 = 4.0000000596e-01,	/* 3ECCCCCD */
301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source ProjectLp3 = 2.8571429849e-01, /* 3E924925 */
311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source ProjectLp4 = 2.2222198546e-01, /* 3E638E29 */
321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source ProjectLp5 = 1.8183572590e-01, /* 3E3A3325 */
331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source ProjectLp6 = 1.5313838422e-01, /* 3E1CD04F */
341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source ProjectLp7 = 1.4798198640e-01; /* 3E178897 */
351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic const float zero = 0.0;
3778419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughesstatic volatile float vzero = 0.0;
381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectfloat
401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectlog1pf(float x)
411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	float hfsq,f,c,s,z,R,u;
431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	int32_t k,hx,hu,ax;
441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	GET_FLOAT_WORD(hx,x);
461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	ax = hx&0x7fffffff;
471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	k = 1;
491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (hx < 0x3ed413d0) {			/* 1+x < sqrt(2)+  */
501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    if(ax>=0x3f800000) {		/* x <= -1.0 */
5178419467a2f88744ae2445fca5eb442877ebb1b0Elliott Hughes		if(x==(float)-1.0) return -two25/vzero; /* log1p(-1)=+inf */
521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		else return (x-x)/(x-x);	/* log1p(x<-1)=NaN */
531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    }
54a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes	    if(ax<0x38000000) {			/* |x| < 2**-15 */
551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if(two25+x>zero			/* raise inexact */
56a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes	            &&ax<0x33800000) 		/* |x| < 2**-24 */
571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		    return x;
581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		else
591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		    return x - x*x*(float)0.5;
601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    }
611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    if(hx>0||hx<=((int32_t)0xbe95f619)) {
621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		k=0;f=x;hu=1;}		/* sqrt(2)/2- <= 1+x < sqrt(2)+ */
631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (hx >= 0x7f800000) return x+x;
651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if(k!=0) {
661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    if(hx<0x5a000000) {
67a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes		STRICT_ASSIGN(float,u,(float)1.0+x);
681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		GET_FLOAT_WORD(hu,u);
691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	        k  = (hu>>23)-127;
701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		/* correction term */
711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	        c  = (k>0)? (float)1.0-(u-x):x-(u-(float)1.0);
721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		c /= u;
731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    } else {
741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		u  = x;
751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		GET_FLOAT_WORD(hu,u);
761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	        k  = (hu>>23)-127;
771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		c  = 0;
781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    }
791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    hu &= 0x007fffff;
801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    /*
811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	     * The approximation to sqrt(2) used in thresholds is not
821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	     * critical.  However, the ones used above must give less
831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	     * strict bounds than the one here so that the k==0 case is
841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	     * never reached from here, since here we have committed to
851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	     * using the correction term but don't use it if k==0.
861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	     */
871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    if(hu<0x3504f4) {			/* u < sqrt(2) */
881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	        SET_FLOAT_WORD(u,hu|0x3f800000);/* normalize u */
891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    } else {
901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	        k += 1;
911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		SET_FLOAT_WORD(u,hu|0x3f000000);	/* normalize u/2 */
921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	        hu = (0x00800000-hu)>>2;
931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    }
941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    f = u-(float)1.0;
951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	hfsq=(float)0.5*f*f;
971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if(hu==0) {	/* |f| < 2**-20 */
98a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes	    if(f==zero) {
99a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes		if(k==0) {
100a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes		    return zero;
101a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes		} else {
102a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes		    c += k*ln2_lo;
103a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes		    return k*ln2_hi+c;
104a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes		}
105a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes	    }
1061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    R = hfsq*((float)1.0-(float)0.66666666666666666*f);
1071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    if(k==0) return f-R; else
1081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    	     return k*ln2_hi-((R-(k*ln2_lo+c))-f);
1091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
1101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 	s = f/((float)2.0+f);
1111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	z = s*s;
1121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	R = z*(Lp1+z*(Lp2+z*(Lp3+z*(Lp4+z*(Lp5+z*(Lp6+z*Lp7))))));
1131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if(k==0) return f-(hfsq-s*(hfsq+R)); else
1141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 return k*ln2_hi-((hfsq-(s*(hfsq+R)+(k*ln2_lo+c)))-f);
1151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
116