Blame sysdeps/ieee754/flt-32/e_lgammaf_r.c

Packit 6c4009
/* e_lgammaf_r.c -- float version of e_lgamma_r.c.
Packit 6c4009
 * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
Packit 6c4009
 */
Packit 6c4009
Packit 6c4009
/*
Packit 6c4009
 * ====================================================
Packit 6c4009
 * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
Packit 6c4009
 *
Packit 6c4009
 * Developed at SunPro, a Sun Microsystems, Inc. business.
Packit 6c4009
 * Permission to use, copy, modify, and distribute this
Packit 6c4009
 * software is freely granted, provided that this notice
Packit 6c4009
 * is preserved.
Packit 6c4009
 * ====================================================
Packit 6c4009
 */
Packit 6c4009
Packit 6c4009
#include <math.h>
Packit 6c4009
#include <math-narrow-eval.h>
Packit 6c4009
#include <math_private.h>
Packit 6c4009
#include <libc-diag.h>
Packit 6c4009
Packit 6c4009
static const float
Packit 6c4009
two23=  8.3886080000e+06, /* 0x4b000000 */
Packit 6c4009
half=  5.0000000000e-01, /* 0x3f000000 */
Packit 6c4009
one =  1.0000000000e+00, /* 0x3f800000 */
Packit 6c4009
pi  =  3.1415927410e+00, /* 0x40490fdb */
Packit 6c4009
a0  =  7.7215664089e-02, /* 0x3d9e233f */
Packit 6c4009
a1  =  3.2246702909e-01, /* 0x3ea51a66 */
Packit 6c4009
a2  =  6.7352302372e-02, /* 0x3d89f001 */
Packit 6c4009
a3  =  2.0580807701e-02, /* 0x3ca89915 */
Packit 6c4009
a4  =  7.3855509982e-03, /* 0x3bf2027e */
Packit 6c4009
a5  =  2.8905137442e-03, /* 0x3b3d6ec6 */
Packit 6c4009
a6  =  1.1927076848e-03, /* 0x3a9c54a1 */
Packit 6c4009
a7  =  5.1006977446e-04, /* 0x3a05b634 */
Packit 6c4009
a8  =  2.2086278477e-04, /* 0x39679767 */
Packit 6c4009
a9  =  1.0801156895e-04, /* 0x38e28445 */
Packit 6c4009
a10 =  2.5214456400e-05, /* 0x37d383a2 */
Packit 6c4009
a11 =  4.4864096708e-05, /* 0x383c2c75 */
Packit 6c4009
tc  =  1.4616321325e+00, /* 0x3fbb16c3 */
Packit 6c4009
tf  = -1.2148628384e-01, /* 0xbdf8cdcd */
Packit 6c4009
/* tt = -(tail of tf) */
Packit 6c4009
tt  =  6.6971006518e-09, /* 0x31e61c52 */
Packit 6c4009
t0  =  4.8383611441e-01, /* 0x3ef7b95e */
Packit 6c4009
t1  = -1.4758771658e-01, /* 0xbe17213c */
Packit 6c4009
t2  =  6.4624942839e-02, /* 0x3d845a15 */
Packit 6c4009
t3  = -3.2788541168e-02, /* 0xbd064d47 */
Packit 6c4009
t4  =  1.7970675603e-02, /* 0x3c93373d */
Packit 6c4009
t5  = -1.0314224288e-02, /* 0xbc28fcfe */
Packit 6c4009
t6  =  6.1005386524e-03, /* 0x3bc7e707 */
Packit 6c4009
t7  = -3.6845202558e-03, /* 0xbb7177fe */
Packit 6c4009
t8  =  2.2596477065e-03, /* 0x3b141699 */
Packit 6c4009
t9  = -1.4034647029e-03, /* 0xbab7f476 */
Packit 6c4009
t10 =  8.8108185446e-04, /* 0x3a66f867 */
Packit 6c4009
t11 = -5.3859531181e-04, /* 0xba0d3085 */
Packit 6c4009
t12 =  3.1563205994e-04, /* 0x39a57b6b */
Packit 6c4009
t13 = -3.1275415677e-04, /* 0xb9a3f927 */
Packit 6c4009
t14 =  3.3552918467e-04, /* 0x39afe9f7 */
Packit 6c4009
u0  = -7.7215664089e-02, /* 0xbd9e233f */
Packit 6c4009
u1  =  6.3282704353e-01, /* 0x3f2200f4 */
Packit 6c4009
u2  =  1.4549225569e+00, /* 0x3fba3ae7 */
Packit 6c4009
u3  =  9.7771751881e-01, /* 0x3f7a4bb2 */
Packit 6c4009
u4  =  2.2896373272e-01, /* 0x3e6a7578 */
Packit 6c4009
u5  =  1.3381091878e-02, /* 0x3c5b3c5e */
Packit 6c4009
v1  =  2.4559779167e+00, /* 0x401d2ebe */
Packit 6c4009
v2  =  2.1284897327e+00, /* 0x4008392d */
Packit 6c4009
v3  =  7.6928514242e-01, /* 0x3f44efdf */
Packit 6c4009
v4  =  1.0422264785e-01, /* 0x3dd572af */
Packit 6c4009
v5  =  3.2170924824e-03, /* 0x3b52d5db */
Packit 6c4009
s0  = -7.7215664089e-02, /* 0xbd9e233f */
Packit 6c4009
s1  =  2.1498242021e-01, /* 0x3e5c245a */
Packit 6c4009
s2  =  3.2577878237e-01, /* 0x3ea6cc7a */
Packit 6c4009
s3  =  1.4635047317e-01, /* 0x3e15dce6 */
Packit 6c4009
s4  =  2.6642270386e-02, /* 0x3cda40e4 */
Packit 6c4009
s5  =  1.8402845599e-03, /* 0x3af135b4 */
Packit 6c4009
s6  =  3.1947532989e-05, /* 0x3805ff67 */
Packit 6c4009
r1  =  1.3920053244e+00, /* 0x3fb22d3b */
Packit 6c4009
r2  =  7.2193557024e-01, /* 0x3f38d0c5 */
Packit 6c4009
r3  =  1.7193385959e-01, /* 0x3e300f6e */
Packit 6c4009
r4  =  1.8645919859e-02, /* 0x3c98bf54 */
Packit 6c4009
r5  =  7.7794247773e-04, /* 0x3a4beed6 */
Packit 6c4009
r6  =  7.3266842264e-06, /* 0x36f5d7bd */
Packit 6c4009
w0  =  4.1893854737e-01, /* 0x3ed67f1d */
Packit 6c4009
w1  =  8.3333335817e-02, /* 0x3daaaaab */
Packit 6c4009
w2  = -2.7777778450e-03, /* 0xbb360b61 */
Packit 6c4009
w3  =  7.9365057172e-04, /* 0x3a500cfd */
Packit 6c4009
w4  = -5.9518753551e-04, /* 0xba1c065c */
Packit 6c4009
w5  =  8.3633989561e-04, /* 0x3a5b3dd2 */
Packit 6c4009
w6  = -1.6309292987e-03; /* 0xbad5c4e8 */
Packit 6c4009
Packit 6c4009
static const float zero=  0.0000000000e+00;
Packit 6c4009
Packit 6c4009
static float
Packit 6c4009
sin_pif(float x)
Packit 6c4009
{
Packit 6c4009
	float y,z;
Packit 6c4009
	int n,ix;
Packit 6c4009
Packit 6c4009
	GET_FLOAT_WORD(ix,x);
Packit 6c4009
	ix &= 0x7fffffff;
Packit 6c4009
Packit 6c4009
	if(ix<0x3e800000) return __kernel_sinf(pi*x,zero,0);
Packit 6c4009
	y = -x;		/* x is assume negative */
Packit 6c4009
Packit 6c4009
    /*
Packit 6c4009
     * argument reduction, make sure inexact flag not raised if input
Packit 6c4009
     * is an integer
Packit 6c4009
     */
Packit 6c4009
	z = __floorf(y);
Packit 6c4009
	if(z!=y) {				/* inexact anyway */
Packit 6c4009
	    y  *= (float)0.5;
Packit 6c4009
	    y   = (float)2.0*(y - __floorf(y));	/* y = |x| mod 2.0 */
Packit 6c4009
	    n   = (int) (y*(float)4.0);
Packit 6c4009
	} else {
Packit 6c4009
	    if(ix>=0x4b800000) {
Packit 6c4009
		y = zero; n = 0;                 /* y must be even */
Packit 6c4009
	    } else {
Packit 6c4009
		if(ix<0x4b000000) z = y+two23;	/* exact */
Packit 6c4009
		GET_FLOAT_WORD(n,z);
Packit 6c4009
		n &= 1;
Packit 6c4009
		y  = n;
Packit 6c4009
		n<<= 2;
Packit 6c4009
	    }
Packit 6c4009
	}
Packit 6c4009
	switch (n) {
Packit 6c4009
	    case 0:   y =  __kernel_sinf(pi*y,zero,0); break;
Packit 6c4009
	    case 1:
Packit 6c4009
	    case 2:   y =  __kernel_cosf(pi*((float)0.5-y),zero); break;
Packit 6c4009
	    case 3:
Packit 6c4009
	    case 4:   y =  __kernel_sinf(pi*(one-y),zero,0); break;
Packit 6c4009
	    case 5:
Packit 6c4009
	    case 6:   y = -__kernel_cosf(pi*(y-(float)1.5),zero); break;
Packit 6c4009
	    default:  y =  __kernel_sinf(pi*(y-(float)2.0),zero,0); break;
Packit 6c4009
	    }
Packit 6c4009
	return -y;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
Packit 6c4009
float
Packit 6c4009
__ieee754_lgammaf_r(float x, int *signgamp)
Packit 6c4009
{
Packit 6c4009
	float t,y,z,nadj,p,p1,p2,p3,q,r,w;
Packit 6c4009
	int i,hx,ix;
Packit 6c4009
Packit 6c4009
	GET_FLOAT_WORD(hx,x);
Packit 6c4009
Packit 6c4009
    /* purge off +-inf, NaN, +-0, and negative arguments */
Packit 6c4009
	*signgamp = 1;
Packit 6c4009
	ix = hx&0x7fffffff;
Packit 6c4009
	if(__builtin_expect(ix>=0x7f800000, 0)) return x*x;
Packit 6c4009
	if(__builtin_expect(ix==0, 0))
Packit 6c4009
	  {
Packit 6c4009
	    if (hx < 0)
Packit 6c4009
	      *signgamp = -1;
Packit 6c4009
	    return one/fabsf(x);
Packit 6c4009
	  }
Packit 6c4009
	if(__builtin_expect(ix<0x30800000, 0)) {
Packit 6c4009
	    /* |x|<2**-30, return -log(|x|) */
Packit 6c4009
	    if(hx<0) {
Packit 6c4009
		*signgamp = -1;
Packit 6c4009
		return -__ieee754_logf(-x);
Packit 6c4009
	    } else return -__ieee754_logf(x);
Packit 6c4009
	}
Packit 6c4009
	if(hx<0) {
Packit 6c4009
	    if(ix>=0x4b000000)	/* |x|>=2**23, must be -integer */
Packit 6c4009
		return fabsf (x)/zero;
Packit 6c4009
	    if (ix > 0x40000000 /* X < 2.0f.  */
Packit 6c4009
		&& ix < 0x41700000 /* X > -15.0f.  */)
Packit 6c4009
		return __lgamma_negf (x, signgamp);
Packit 6c4009
	    t = sin_pif(x);
Packit 6c4009
	    if(t==zero) return one/fabsf(t); /* -integer */
Packit 6c4009
	    nadj = __ieee754_logf(pi/fabsf(t*x));
Packit 6c4009
	    if(t
Packit 6c4009
	    x = -x;
Packit 6c4009
	}
Packit 6c4009
Packit 6c4009
    /* purge off 1 and 2 */
Packit 6c4009
	if (ix==0x3f800000||ix==0x40000000) r = 0;
Packit 6c4009
    /* for x < 2.0 */
Packit 6c4009
	else if(ix<0x40000000) {
Packit 6c4009
	    if(ix<=0x3f666666) {	/* lgamma(x) = lgamma(x+1)-log(x) */
Packit 6c4009
		r = -__ieee754_logf(x);
Packit 6c4009
		if(ix>=0x3f3b4a20) {y = one-x; i= 0;}
Packit 6c4009
		else if(ix>=0x3e6d3308) {y= x-(tc-one); i=1;}
Packit 6c4009
		else {y = x; i=2;}
Packit 6c4009
	    } else {
Packit 6c4009
		r = zero;
Packit 6c4009
		if(ix>=0x3fdda618) {y=(float)2.0-x;i=0;} /* [1.7316,2] */
Packit 6c4009
		else if(ix>=0x3F9da620) {y=x-tc;i=1;} /* [1.23,1.73] */
Packit 6c4009
		else {y=x-one;i=2;}
Packit 6c4009
	    }
Packit 6c4009
	    switch(i) {
Packit 6c4009
	      case 0:
Packit 6c4009
		z = y*y;
Packit 6c4009
		p1 = a0+z*(a2+z*(a4+z*(a6+z*(a8+z*a10))));
Packit 6c4009
		p2 = z*(a1+z*(a3+z*(a5+z*(a7+z*(a9+z*a11)))));
Packit 6c4009
		p  = y*p1+p2;
Packit 6c4009
		r  += (p-(float)0.5*y); break;
Packit 6c4009
	      case 1:
Packit 6c4009
		z = y*y;
Packit 6c4009
		w = z*y;
Packit 6c4009
		p1 = t0+w*(t3+w*(t6+w*(t9 +w*t12)));	/* parallel comp */
Packit 6c4009
		p2 = t1+w*(t4+w*(t7+w*(t10+w*t13)));
Packit 6c4009
		p3 = t2+w*(t5+w*(t8+w*(t11+w*t14)));
Packit 6c4009
		p  = z*p1-(tt-w*(p2+y*p3));
Packit 6c4009
		r += (tf + p); break;
Packit 6c4009
	      case 2:
Packit 6c4009
		p1 = y*(u0+y*(u1+y*(u2+y*(u3+y*(u4+y*u5)))));
Packit 6c4009
		p2 = one+y*(v1+y*(v2+y*(v3+y*(v4+y*v5))));
Packit 6c4009
		r += (-(float)0.5*y + p1/p2);
Packit 6c4009
	    }
Packit 6c4009
	}
Packit 6c4009
	else if(ix<0x41000000) {			/* x < 8.0 */
Packit 6c4009
	    i = (int)x;
Packit 6c4009
	    t = zero;
Packit 6c4009
	    y = x-(float)i;
Packit 6c4009
	    p = y*(s0+y*(s1+y*(s2+y*(s3+y*(s4+y*(s5+y*s6))))));
Packit 6c4009
	    q = one+y*(r1+y*(r2+y*(r3+y*(r4+y*(r5+y*r6)))));
Packit 6c4009
	    r = half*y+p/q;
Packit 6c4009
	    z = one;	/* lgamma(1+s) = log(s) + lgamma(s) */
Packit 6c4009
	    switch(i) {
Packit 6c4009
	    case 7: z *= (y+(float)6.0);	/* FALLTHRU */
Packit 6c4009
	    case 6: z *= (y+(float)5.0);	/* FALLTHRU */
Packit 6c4009
	    case 5: z *= (y+(float)4.0);	/* FALLTHRU */
Packit 6c4009
	    case 4: z *= (y+(float)3.0);	/* FALLTHRU */
Packit 6c4009
	    case 3: z *= (y+(float)2.0);	/* FALLTHRU */
Packit 6c4009
		    r += __ieee754_logf(z); break;
Packit 6c4009
	    }
Packit 6c4009
    /* 8.0 <= x < 2**26 */
Packit 6c4009
	} else if (ix < 0x4c800000) {
Packit 6c4009
	    t = __ieee754_logf(x);
Packit 6c4009
	    z = one/x;
Packit 6c4009
	    y = z*z;
Packit 6c4009
	    w = w0+z*(w1+y*(w2+y*(w3+y*(w4+y*(w5+y*w6)))));
Packit 6c4009
	    r = (x-half)*(t-one)+w;
Packit 6c4009
	} else
Packit 6c4009
    /* 2**26 <= x <= inf */
Packit 6c4009
	    r =  math_narrow_eval (x*(__ieee754_logf(x)-one));
Packit 6c4009
	/* NADJ is set for negative arguments but not otherwise,
Packit 6c4009
	   resulting in warnings that it may be used uninitialized
Packit 6c4009
	   although in the cases where it is used it has always been
Packit 6c4009
	   set.  */
Packit 6c4009
	DIAG_PUSH_NEEDS_COMMENT;
Packit 6c4009
	DIAG_IGNORE_NEEDS_COMMENT (4.9, "-Wmaybe-uninitialized");
Packit 6c4009
	if(hx<0) r = nadj - r;
Packit 6c4009
	DIAG_POP_NEEDS_COMMENT;
Packit 6c4009
	return r;
Packit 6c4009
}
Packit 6c4009
strong_alias (__ieee754_lgammaf_r, __lgammaf_r_finite)