float __asinhf(float x) { float w; int32_t hx,ix; GET_FLOAT_WORD(hx,x); ix = hx&0x7fffffff; if(__builtin_expect(ix< 0x38000000, 0)) { /* |x|<2**-14 */ math_check_force_underflow (x); if(huge+x>one) return x; /* return x inexact except 0 */ } if(__builtin_expect(ix>0x47000000, 0)) { /* |x| > 2**14 */ if(ix>=0x7f800000) return x+x; /* x is inf or NaN */ w = __ieee754_logf(fabsf(x))+ln2; } else { float xa = fabsf(x); if (ix>0x40000000) { /* 2**14 > |x| > 2.0 */ w = __ieee754_logf(2.0f*xa+one/(__ieee754_sqrtf(xa*xa+one)+xa)); } else { /* 2.0 > |x| > 2**-14 */ float t = xa*xa; w =__log1pf(xa+t/(one+__ieee754_sqrtf(one+t))); } } return __copysignf(w, x); }
float __ieee754_y0f(float x) { float z, s,c,ss,cc,u,v; int32_t hx,ix; GET_FLOAT_WORD(hx,x); ix = 0x7fffffff&hx; /* Y0(NaN) is NaN, y0(-inf) is Nan, y0(inf) is 0 */ if(ix>=0x7f800000) return one/(x+x*x); if(ix==0) return -one/zero; if(hx<0) return zero/zero; if(ix >= 0x40000000) { /* |x| >= 2.0 */ /* y0(x) = sqrt(2/(pi*x))*(p0(x)*sin(x0)+q0(x)*cos(x0)) * where x0 = x-pi/4 * Better formula: * cos(x0) = cos(x)cos(pi/4)+sin(x)sin(pi/4) * = 1/sqrt(2) * (sin(x) + cos(x)) * sin(x0) = sin(x)cos(3pi/4)-cos(x)sin(3pi/4) * = 1/sqrt(2) * (sin(x) - cos(x)) * To avoid cancellation, use * sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x)) * to compute the worse one. */ s = sinf(x); c = cosf(x); ss = s-c; cc = s+c; /* * j0(x) = 1/sqrt(pi) * (P(0,x)*cc - Q(0,x)*ss) / sqrt(x) * y0(x) = 1/sqrt(pi) * (P(0,x)*ss + Q(0,x)*cc) / sqrt(x) */ if(ix<0x7f000000) { /* make sure x+x not overflow */ z = -cosf(x+x); if ((s*c)<zero) cc = z/ss; else ss = z/cc; } #ifdef DEAD_CODE if(ix>0x80000000) z = (invsqrtpi*ss)/sqrtf(x); else #endif { u = pzerof(x); v = qzerof(x); z = invsqrtpi*(u*ss+v*cc)/sqrtf(x); } return z; } if(ix<=0x32000000) { /* x < 2**-27 */ return(u00 + tpi*__ieee754_logf(x)); } z = x*x; u = u00+z*(u01+z*(u02+z*(u03+z*(u04+z*(u05+z*u06))))); v = one+z*(v01+z*(v02+z*(v03+z*v04))); return(u/v + tpi*(__ieee754_j0f(x)*__ieee754_logf(x))); }
__complex__ float __catanhf (__complex__ float x) { __complex__ float res; int rcls = fpclassify (__real__ x); int icls = fpclassify (__imag__ x); if (__builtin_expect (rcls <= FP_INFINITE || icls <= FP_INFINITE, 0)) { if (icls == FP_INFINITE) { __real__ res = __copysignf (0.0, __real__ x); __imag__ res = __copysignf (M_PI_2, __imag__ x); } else if (rcls == FP_INFINITE || rcls == FP_ZERO) { __real__ res = __copysignf (0.0, __real__ x); if (icls >= FP_ZERO) __imag__ res = __copysignf (M_PI_2, __imag__ x); else __imag__ res = __nanf (""); } else { __real__ res = __nanf (""); __imag__ res = __nanf (""); } } else if (__builtin_expect (rcls == FP_ZERO && icls == FP_ZERO, 0)) { res = x; } else { float i2 = __imag__ x * __imag__ x; float num = 1.0 + __real__ x; num = i2 + num * num; float den = 1.0 - __real__ x; den = i2 + den * den; __real__ res = 0.25 * (__ieee754_logf (num) - __ieee754_logf (den)); den = 1 - __real__ x * __real__ x - i2; __imag__ res = 0.5 * __ieee754_atan2f (2.0 * __imag__ x, den); } return res; }
__complex__ float __clogf (__complex__ float x) { __complex__ float result; int rcls = fpclassify (__real__ x); int icls = fpclassify (__imag__ x); if (__builtin_expect (rcls == FP_ZERO && icls == FP_ZERO, 0)) { /* Real and imaginary part are 0.0. */ __imag__ result = signbit (__real__ x) ? M_PI : 0.0; __imag__ result = __copysignf (__imag__ result, __imag__ x); /* Yes, the following line raises an exception. */ __real__ result = -1.0 / fabsf (__real__ x); } else if (__builtin_expect (rcls != FP_NAN && icls != FP_NAN, 1)) { /* Neither real nor imaginary part is NaN. */ __real__ result = __ieee754_logf (__ieee754_hypotf (__real__ x, __imag__ x)); __imag__ result = __ieee754_atan2f (__imag__ x, __real__ x); } else { __imag__ result = __nanf (""); if (rcls == FP_INFINITE || icls == FP_INFINITE) /* Real or imaginary part is infinite. */ __real__ result = HUGE_VALF; else __real__ result = __nanf (""); } return result; }
float __ieee754_log10f(float x) { float y,z; int32_t i,k,hx; GET_FLOAT_WORD(hx,x); k=0; if (hx < 0x00800000) { /* x < 2**-126 */ if ((hx&0x7fffffff)==0) return -two25/zero; /* log(+-0)=-inf */ if (hx<0) return (x-x)/zero; /* log(-#) = NaN */ k -= 25; x *= two25; /* subnormal number, scale up x */ GET_FLOAT_WORD(hx,x); } if (hx >= 0x7f800000) return x+x; k += (hx>>23)-127; i = ((u_int32_t)k&0x80000000)>>31; hx = (hx&0x007fffff)|((0x7f-i)<<23); y = (float)(k+i); SET_FLOAT_WORD(x,hx); z = y*log10_2lo + ivln10*__ieee754_logf(x); return z+y*log10_2hi; }
float logf(float x) /* wrapper logf */ { #ifdef _IEEE_LIBM return __ieee754_logf(x); #else float z; z = __ieee754_logf(x); if(_LIB_VERSION == _IEEE_ || isnanf(x) || x > (float)0.0) return z; if(x==(float)0.0) /* logf(0) */ return (float)__kernel_standard((double)x,(double)x,116); else /* logf(x<0) */ return (float)__kernel_standard((double)x,(double)x,117); #endif }
//------------------------------------------------------------------------------ float Cmath::__ieee754_acoshf( float x ) { static const float one = 1.0; static const float ln2 = 6.9314718246e-01; // 0x3f317218 float t; Cmp_signed__int32 hx; get_float_word( hx, x ); if( hx < 0x3f800000 ) { // x < 1 return ( x - x ) / ( x - x ); } else if( hx >= 0x4d800000 ) { // x > 2**28 if( !uword_isfinite( hx ) ) { // x is inf of NaN return x + x; } else { return __ieee754_logf( x ) + ln2; // acosh(huge)=log(2x) } } else if ( hx == 0x3f800000 ) { return 0.0; // acosh(1) = 0 } else if ( hx > 0x40000000 ) { // 2**28 > x > 2 t = x * x; return __ieee754_logf( (float)2.0 * x - one / ( x + __ieee754_sqrtf( t - one ) ) ); } else { // 1<x<2 t = x - one; return log1pf( t + __ieee754_sqrtf( (float)2.0 * t + t * t ) ); } }
float __ieee754_y1f(float x) { float z, s,c,ss,cc,u,v; int32_t hx,ix; GET_FLOAT_WORD(hx,x); ix = 0x7fffffff&hx; /* if Y1(NaN) is NaN, Y1(-inf) is NaN, Y1(inf) is 0 */ if(__builtin_expect(ix>=0x7f800000, 0)) return one/(x+x*x); if(__builtin_expect(ix==0, 0)) return -HUGE_VALF+x; /* -inf and overflow exception. */ if(__builtin_expect(hx<0, 0)) return zero/(zero*x); if(ix >= 0x40000000) { /* |x| >= 2.0 */ SET_RESTORE_ROUNDF (FE_TONEAREST); __sincosf (x, &s, &c); ss = -s-c; cc = s-c; if(ix<0x7f000000) { /* make sure x+x not overflow */ z = __cosf(x+x); if ((s*c)>zero) cc = z/ss; else ss = z/cc; } /* y1(x) = sqrt(2/(pi*x))*(p1(x)*sin(x0)+q1(x)*cos(x0)) * where x0 = x-3pi/4 * Better formula: * cos(x0) = cos(x)cos(3pi/4)+sin(x)sin(3pi/4) * = 1/sqrt(2) * (sin(x) - cos(x)) * sin(x0) = sin(x)cos(3pi/4)-cos(x)sin(3pi/4) * = -1/sqrt(2) * (cos(x) + sin(x)) * To avoid cancellation, use * sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x)) * to compute the worse one. */ if(ix>0x48000000) z = (invsqrtpi*ss)/__ieee754_sqrtf(x); else { u = ponef(x); v = qonef(x); z = invsqrtpi*(u*ss+v*cc)/__ieee754_sqrtf(x); } return z; } if(__builtin_expect(ix<=0x33000000, 0)) { /* x < 2**-25 */ z = -tpi / x; if (__isinff (z)) __set_errno (ERANGE); return z; } z = x*x; u = U0[0]+z*(U0[1]+z*(U0[2]+z*(U0[3]+z*U0[4]))); v = one+z*(V0[0]+z*(V0[1]+z*(V0[2]+z*(V0[3]+z*V0[4])))); return(x*(u/v) + tpi*(__ieee754_j1f(x)*__ieee754_logf(x)-one/x)); }
float asinhf(float x) { float t,w; int32_t hx,ix; GET_FLOAT_WORD(hx,x); ix = hx&0x7fffffff; if(ix>=0x7f800000) return x+x; /* x is inf or NaN */ if(ix< 0x31800000) { /* |x|<2**-28 */ if(huge+x>one) return x; /* return x inexact except 0 */ } if(ix>0x4d800000) { /* |x| > 2**28 */ w = __ieee754_logf(fabsf(x))+ln2; } else if (ix>0x40000000) { /* 2**28 > |x| > 2.0 */ t = fabsf(x); w = __ieee754_logf((float)2.0*t+one/(__ieee754_sqrtf(x*x+one)+t)); } else { /* 2.0 > |x| > 2**-28 */ t = x*x; w =log1pf(fabsf(x)+t/(one+__ieee754_sqrtf(one+t))); } if(hx>0) return w; else return -w; }
float __ieee754_acoshf(float x) { float t; int32_t hx; GET_FLOAT_WORD(hx,x); if(hx<0x3f800000) { /* x < 1 */ return (x-x)/(x-x); } else if(hx >=0x4d800000) { /* x > 2**28 */ if(hx >=0x7f800000) { /* x is inf of NaN */ return x+x; } else return __ieee754_logf(x)+ln2; /* acosh(huge)=log(2x) */ } else if (hx==0x3f800000) { return 0.0; /* acosh(1) = 0 */ } else if (hx > 0x40000000) { /* 2**28 > x > 2 */ t=x*x; return __ieee754_logf((float)2.0*x-one/(x+__ieee754_sqrtf(t-one))); } else { /* 1<x<2 */ t = x-one; return log1pf(t+__ieee754_sqrtf((float)2.0*t+t*t)); } }
float __ieee754_y1f(float x) { float z, s,c,ss,cc,u,v; int32_t hx,ix; GET_FLOAT_WORD(hx,x); ix = 0x7fffffff&hx; /* if Y1(NaN) is NaN, Y1(-inf) is NaN, Y1(inf) is 0 */ if(ix>=0x7f800000) return one/(x+x*x); if(ix==0) return -one/zero; if(hx<0) return zero/zero; if(ix >= 0x40000000) { /* |x| >= 2.0 */ s = sinf(x); c = cosf(x); ss = -s-c; cc = s-c; if(ix<0x7f000000) { /* make sure x+x not overflow */ z = cosf(x+x); if ((s*c)>zero) cc = z/ss; else ss = z/cc; } /* y1(x) = sqrt(2/(pi*x))*(p1(x)*sin(x0)+q1(x)*cos(x0)) * where x0 = x-3pi/4 * Better formula: * cos(x0) = cos(x)cos(3pi/4)+sin(x)sin(3pi/4) * = 1/sqrt(2) * (sin(x) - cos(x)) * sin(x0) = sin(x)cos(3pi/4)-cos(x)sin(3pi/4) * = -1/sqrt(2) * (cos(x) + sin(x)) * To avoid cancellation, use * sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x)) * to compute the worse one. */ if(ix>0x48000000) z = (invsqrtpi*ss)/sqrtf(x); else { u = ponef(x); v = qonef(x); z = invsqrtpi*(u*ss+v*cc)/sqrtf(x); } return z; } if(ix<=0x24800000) { /* x < 2**-54 */ return(-tpi/x); } z = x*x; u = U0[0]+z*(U0[1]+z*(U0[2]+z*(U0[3]+z*U0[4]))); v = one+z*(V0[0]+z*(V0[1]+z*(V0[2]+z*(V0[3]+z*V0[4])))); return(x*(u/v) + tpi*(__ieee754_j1f(x)*__ieee754_logf(x)-one/x)); }
int main() { /* REQ-BL-0910 * The log and logf procedures shall return -Inf if the argument x is +-0. */ float x = -0.0f; float res = __ieee754_logf(x); // x is -0, the result shall be -inf if (!isinf_float(res)) { __VERIFIER_error(); return 1; } return 0; }
/* wrapper logf(x) */ float __logf (float x) { if (__builtin_expect (x <= 0.0f, 0) && _LIB_VERSION != _IEEE_) { if (x == 0.0f) { feraiseexcept (FE_DIVBYZERO); return __kernel_standard_f (x, x, 116); /* log(0) */ } else { feraiseexcept (FE_INVALID); return __kernel_standard_f (x, x, 117); /* log(x<0) */ } } return __ieee754_logf (x); }
float __ieee754_log10f(float x) { float y, z; __int32_t i, k, hx; do { ieee_float_shape_type gf_u; gf_u.value = (x); (hx) = gf_u.word; } while (0); k = 0; if (((hx & 0x7fffffff) == 0)) return -two25_log10 / zero; if (hx < 0) return (x - x) / zero; if (!((hx) < 0x7f800000L)) return x + x; if (((hx) < 0x00800000L)) { k -= 25; x *= two25_log10; do { ieee_float_shape_type gf_u; gf_u.value = (x); (hx) = gf_u.word; } while (0); } k += (hx >> 23) - 127; i = ((__uint32_t)k & 0x80000000) >> 31; hx = (hx & 0x007fffff) | ((0x7f - i) << 23); y = (float)(k + i); do { ieee_float_shape_type sf_u; sf_u.word = (hx); (x) = sf_u.value; } while (0); z = y * log10_2lo_log10 + ivln10_log10 * __ieee754_logf(x); return z + y * log10_2hi_log10; }
__complex__ float __cacoshf (__complex__ float x) { __complex__ float res; int rcls = fpclassify (__real__ x); int icls = fpclassify (__imag__ x); if (rcls <= FP_INFINITE || icls <= FP_INFINITE) { if (icls == FP_INFINITE) { __real__ res = HUGE_VALF; if (rcls == FP_NAN) __imag__ res = __nanf (""); else __imag__ res = __copysignf ((rcls == FP_INFINITE ? (__real__ x < 0.0 ? M_PI - M_PI_4 : M_PI_4) : M_PI_2), __imag__ x); } else if (rcls == FP_INFINITE) { __real__ res = HUGE_VALF; if (icls >= FP_ZERO) __imag__ res = __copysignf (signbit (__real__ x) ? M_PI : 0.0, __imag__ x); else __imag__ res = __nanf (""); } else { __real__ res = __nanf (""); __imag__ res = __nanf (""); } } else if (rcls == FP_ZERO && icls == FP_ZERO) { __real__ res = 0.0; __imag__ res = __copysignf (M_PI_2, __imag__ x); } else { #if 1 __complex__ float y; __real__ y = (__real__ x - __imag__ x) * (__real__ x + __imag__ x) - 1.0; __imag__ y = 2.0 * __real__ x * __imag__ x; y = __csqrtf (y); if (__real__ x < 0.0) y = -y; __real__ y += __real__ x; __imag__ y += __imag__ x; res = __clogf (y); #else float re2 = __real__ x * __real__ x; float im2 = __imag__ x * __imag__ x; float sq = re2 - im2 - 1.0; float ro = __ieee754_sqrtf (sq * sq + 4 * re2 * im2); float a = __ieee754_sqrtf ((sq + ro) / 2.0); float b = __ieee754_sqrtf ((-sq + ro) / 2.0); __real__ res = 0.5 * __ieee754_logf (re2 + __real__ x * 2 * a + im2 + __imag__ x * 2 * b + ro); __imag__ res = __ieee754_atan2f (__imag__ x + b, __real__ x + a); #endif /* We have to use the positive branch. */ if (__real__ res < 0.0) res = -res; } return res; }
float __ieee754_lgammaf_r(float x, int *signgamp) { float t,y,z,nadj,p,p1,p2,p3,q,r,w; int i,hx,ix; GET_FLOAT_WORD(hx,x); /* purge off +-inf, NaN, +-0, and negative arguments */ *signgamp = 1; ix = hx&0x7fffffff; if(__builtin_expect(ix>=0x7f800000, 0)) return x*x; if(__builtin_expect(ix==0, 0)) { if (hx < 0) *signgamp = -1; return one/fabsf(x); } if(__builtin_expect(ix<0x30800000, 0)) { /* |x|<2**-30, return -log(|x|) */ if(hx<0) { *signgamp = -1; return -__ieee754_logf(-x); } else return -__ieee754_logf(x); } if(hx<0) { if(ix>=0x4b000000) /* |x|>=2**23, must be -integer */ return x/zero; if (ix > 0x40000000 /* X < 2.0f. */ && ix < 0x41700000 /* X > -15.0f. */) return __lgamma_negf (x, signgamp); t = sin_pif(x); if(t==zero) return one/fabsf(t); /* -integer */ nadj = __ieee754_logf(pi/fabsf(t*x)); if(t<zero) *signgamp = -1; x = -x; } /* purge off 1 and 2 */ if (ix==0x3f800000||ix==0x40000000) r = 0; /* for x < 2.0 */ else if(ix<0x40000000) { if(ix<=0x3f666666) { /* lgamma(x) = lgamma(x+1)-log(x) */ r = -__ieee754_logf(x); if(ix>=0x3f3b4a20) {y = one-x; i= 0;} else if(ix>=0x3e6d3308) {y= x-(tc-one); i=1;} else {y = x; i=2;} } else { r = zero; if(ix>=0x3fdda618) {y=(float)2.0-x;i=0;} /* [1.7316,2] */ else if(ix>=0x3F9da620) {y=x-tc;i=1;} /* [1.23,1.73] */ else {y=x-one;i=2;} } switch(i) { case 0: z = y*y; p1 = a0+z*(a2+z*(a4+z*(a6+z*(a8+z*a10)))); p2 = z*(a1+z*(a3+z*(a5+z*(a7+z*(a9+z*a11))))); p = y*p1+p2; r += (p-(float)0.5*y); break; case 1: z = y*y; w = z*y; p1 = t0+w*(t3+w*(t6+w*(t9 +w*t12))); /* parallel comp */ p2 = t1+w*(t4+w*(t7+w*(t10+w*t13))); p3 = t2+w*(t5+w*(t8+w*(t11+w*t14))); p = z*p1-(tt-w*(p2+y*p3)); r += (tf + p); break; case 2: p1 = y*(u0+y*(u1+y*(u2+y*(u3+y*(u4+y*u5))))); p2 = one+y*(v1+y*(v2+y*(v3+y*(v4+y*v5)))); r += (-(float)0.5*y + p1/p2); } } else if(ix<0x41000000) { /* x < 8.0 */ i = (int)x; t = zero; y = x-(float)i; p = y*(s0+y*(s1+y*(s2+y*(s3+y*(s4+y*(s5+y*s6)))))); q = one+y*(r1+y*(r2+y*(r3+y*(r4+y*(r5+y*r6))))); r = half*y+p/q; z = one; /* lgamma(1+s) = log(s) + lgamma(s) */ switch(i) { case 7: z *= (y+(float)6.0); /* FALLTHRU */ case 6: z *= (y+(float)5.0); /* FALLTHRU */ case 5: z *= (y+(float)4.0); /* FALLTHRU */ case 4: z *= (y+(float)3.0); /* FALLTHRU */ case 3: z *= (y+(float)2.0); /* FALLTHRU */ r += __ieee754_logf(z); break; } /* 8.0 <= x < 2**26 */ } else if (ix < 0x4c800000) { t = __ieee754_logf(x); z = one/x; y = z*z; w = w0+z*(w1+y*(w2+y*(w3+y*(w4+y*(w5+y*w6))))); r = (x-half)*(t-one)+w; } else /* 2**26 <= x <= inf */ r = math_narrow_eval (x*(__ieee754_logf(x)-one)); /* NADJ is set for negative arguments but not otherwise, resulting in warnings that it may be used uninitialized although in the cases where it is used it has always been set. */ DIAG_PUSH_NEEDS_COMMENT; #if __GNUC_PREREQ (4, 7) DIAG_IGNORE_NEEDS_COMMENT (4.9, "-Wmaybe-uninitialized"); #else DIAG_IGNORE_NEEDS_COMMENT (4.9, "-Wuninitialized"); #endif if(hx<0) r = nadj - r; DIAG_POP_NEEDS_COMMENT; return r; }
float __lgamma_negf (float x, int *signgamp) { /* Determine the half-integer region X lies in, handle exact integers and determine the sign of the result. */ int i = __floorf (-2 * x); if ((i & 1) == 0 && i == -2 * x) return 1.0f / 0.0f; float xn = ((i & 1) == 0 ? -i / 2 : (-i - 1) / 2); i -= 4; *signgamp = ((i & 2) == 0 ? -1 : 1); SET_RESTORE_ROUNDF (FE_TONEAREST); /* Expand around the zero X0 = X0_HI + X0_LO. */ float x0_hi = lgamma_zeros[i][0], x0_lo = lgamma_zeros[i][1]; float xdiff = x - x0_hi - x0_lo; /* For arguments in the range -3 to -2, use polynomial approximations to an adjusted version of the gamma function. */ if (i < 2) { int j = __floorf (-8 * x) - 16; float xm = (-33 - 2 * j) * 0.0625f; float x_adj = x - xm; size_t deg = poly_deg[j]; size_t end = poly_end[j]; float g = poly_coeff[end]; for (size_t j = 1; j <= deg; j++) g = g * x_adj + poly_coeff[end - j]; return __log1pf (g * xdiff / (x - xn)); } /* The result we want is log (sinpi (X0) / sinpi (X)) + log (gamma (1 - X0) / gamma (1 - X)). */ float x_idiff = fabsf (xn - x), x0_idiff = fabsf (xn - x0_hi - x0_lo); float log_sinpi_ratio; if (x0_idiff < x_idiff * 0.5f) /* Use log not log1p to avoid inaccuracy from log1p of arguments close to -1. */ log_sinpi_ratio = __ieee754_logf (lg_sinpi (x0_idiff) / lg_sinpi (x_idiff)); else { /* Use log1p not log to avoid inaccuracy from log of arguments close to 1. X0DIFF2 has positive sign if X0 is further from XN than X is from XN, negative sign otherwise. */ float x0diff2 = ((i & 1) == 0 ? xdiff : -xdiff) * 0.5f; float sx0d2 = lg_sinpi (x0diff2); float cx0d2 = lg_cospi (x0diff2); log_sinpi_ratio = __log1pf (2 * sx0d2 * (-sx0d2 + cx0d2 * lg_cotpi (x_idiff))); } float log_gamma_ratio; float y0 = math_narrow_eval (1 - x0_hi); float y0_eps = -x0_hi + (1 - y0) - x0_lo; float y = math_narrow_eval (1 - x); float y_eps = -x + (1 - y); /* We now wish to compute LOG_GAMMA_RATIO = log (gamma (Y0 + Y0_EPS) / gamma (Y + Y_EPS)). XDIFF accurately approximates the difference Y0 + Y0_EPS - Y - Y_EPS. Use Stirling's approximation. */ float log_gamma_high = (xdiff * __log1pf ((y0 - e_hi - e_lo + y0_eps) / e_hi) + (y - 0.5f + y_eps) * __log1pf (xdiff / y)); /* Compute the sum of (B_2k / 2k(2k-1))(Y0^-(2k-1) - Y^-(2k-1)). */ float y0r = 1 / y0, yr = 1 / y; float y0r2 = y0r * y0r, yr2 = yr * yr; float rdiff = -xdiff / (y * y0); float bterm[NCOEFF]; float dlast = rdiff, elast = rdiff * yr * (yr + y0r); bterm[0] = dlast * lgamma_coeff[0]; for (size_t j = 1; j < NCOEFF; j++) { float dnext = dlast * y0r2 + elast; float enext = elast * yr2; bterm[j] = dnext * lgamma_coeff[j]; dlast = dnext; elast = enext; } float log_gamma_low = 0; for (size_t j = 0; j < NCOEFF; j++) log_gamma_low += bterm[NCOEFF - 1 - j]; log_gamma_ratio = log_gamma_high + log_gamma_low; return log_sinpi_ratio + log_gamma_ratio; }
__complex__ float __kernel_casinhf (__complex__ float x, int adj) { __complex__ float res; float rx, ix; __complex__ float y; /* Avoid cancellation by reducing to the first quadrant. */ rx = fabsf (__real__ x); ix = fabsf (__imag__ x); if (rx >= 1.0f / FLT_EPSILON || ix >= 1.0f / FLT_EPSILON) { /* For large x in the first quadrant, x + csqrt (1 + x * x) is sufficiently close to 2 * x to make no significant difference to the result; avoid possible overflow from the squaring and addition. */ __real__ y = rx; __imag__ y = ix; if (adj) { float t = __real__ y; __real__ y = __copysignf (__imag__ y, __imag__ x); __imag__ y = t; } res = __clogf (y); __real__ res += (float) M_LN2; } else if (rx >= 0.5f && ix < FLT_EPSILON / 8.0f) { float s = __ieee754_hypotf (1.0f, rx); __real__ res = __ieee754_logf (rx + s); if (adj) __imag__ res = __ieee754_atan2f (s, __imag__ x); else __imag__ res = __ieee754_atan2f (ix, s); } else if (rx < FLT_EPSILON / 8.0f && ix >= 1.5f) { float s = __ieee754_sqrtf ((ix + 1.0f) * (ix - 1.0f)); __real__ res = __ieee754_logf (ix + s); if (adj) __imag__ res = __ieee754_atan2f (rx, __copysignf (s, __imag__ x)); else __imag__ res = __ieee754_atan2f (s, rx); } else if (ix > 1.0f && ix < 1.5f && rx < 0.5f) { if (rx < FLT_EPSILON * FLT_EPSILON) { float ix2m1 = (ix + 1.0f) * (ix - 1.0f); float s = __ieee754_sqrtf (ix2m1); __real__ res = __log1pf (2.0f * (ix2m1 + ix * s)) / 2.0f; if (adj) __imag__ res = __ieee754_atan2f (rx, __copysignf (s, __imag__ x)); else __imag__ res = __ieee754_atan2f (s, rx); } else { float ix2m1 = (ix + 1.0f) * (ix - 1.0f); float rx2 = rx * rx; float f = rx2 * (2.0f + rx2 + 2.0f * ix * ix); float d = __ieee754_sqrtf (ix2m1 * ix2m1 + f); float dp = d + ix2m1; float dm = f / dp; float r1 = __ieee754_sqrtf ((dm + rx2) / 2.0f); float r2 = rx * ix / r1; __real__ res = __log1pf (rx2 + dp + 2.0f * (rx * r1 + ix * r2)) / 2.0f; if (adj) __imag__ res = __ieee754_atan2f (rx + r1, __copysignf (ix + r2, __imag__ x)); else __imag__ res = __ieee754_atan2f (ix + r2, rx + r1); } } else if (ix == 1.0f && rx < 0.5f) { if (rx < FLT_EPSILON / 8.0f) { __real__ res = __log1pf (2.0f * (rx + __ieee754_sqrtf (rx))) / 2.0f; if (adj) __imag__ res = __ieee754_atan2f (__ieee754_sqrtf (rx), __copysignf (1.0f, __imag__ x)); else __imag__ res = __ieee754_atan2f (1.0f, __ieee754_sqrtf (rx)); } else { float d = rx * __ieee754_sqrtf (4.0f + rx * rx); float s1 = __ieee754_sqrtf ((d + rx * rx) / 2.0f); float s2 = __ieee754_sqrtf ((d - rx * rx) / 2.0f); __real__ res = __log1pf (rx * rx + d + 2.0f * (rx * s1 + s2)) / 2.0f; if (adj) __imag__ res = __ieee754_atan2f (rx + s1, __copysignf (1.0f + s2, __imag__ x)); else __imag__ res = __ieee754_atan2f (1.0f + s2, rx + s1); } } else if (ix < 1.0f && rx < 0.5f) { if (ix >= FLT_EPSILON) { if (rx < FLT_EPSILON * FLT_EPSILON) { float onemix2 = (1.0f + ix) * (1.0f - ix); float s = __ieee754_sqrtf (onemix2); __real__ res = __log1pf (2.0f * rx / s) / 2.0f; if (adj) __imag__ res = __ieee754_atan2f (s, __imag__ x); else __imag__ res = __ieee754_atan2f (ix, s); } else { float onemix2 = (1.0f + ix) * (1.0f - ix); float rx2 = rx * rx; float f = rx2 * (2.0f + rx2 + 2.0f * ix * ix); float d = __ieee754_sqrtf (onemix2 * onemix2 + f); float dp = d + onemix2; float dm = f / dp; float r1 = __ieee754_sqrtf ((dp + rx2) / 2.0f); float r2 = rx * ix / r1; __real__ res = __log1pf (rx2 + dm + 2.0f * (rx * r1 + ix * r2)) / 2.0f; if (adj) __imag__ res = __ieee754_atan2f (rx + r1, __copysignf (ix + r2, __imag__ x)); else __imag__ res = __ieee754_atan2f (ix + r2, rx + r1); } } else { float s = __ieee754_hypotf (1.0f, rx); __real__ res = __log1pf (2.0f * rx * (rx + s)) / 2.0f; if (adj) __imag__ res = __ieee754_atan2f (s, __imag__ x); else __imag__ res = __ieee754_atan2f (ix, s); } if (__real__ res < FLT_MIN) { volatile float force_underflow = __real__ res * __real__ res; (void) force_underflow; } } else { __real__ y = (rx - ix) * (rx + ix) + 1.0f; __imag__ y = 2.0f * rx * ix; y = __csqrtf (y); __real__ y += rx; __imag__ y += ix; if (adj) { float t = __real__ y; __real__ y = __copysignf (__imag__ y, __imag__ x); __imag__ y = t; } res = __clogf (y); } /* Give results the correct sign for the original argument. */ __real__ res = __copysignf (__real__ res, __real__ x); __imag__ res = __copysignf (__imag__ res, (adj ? 1.0f : __imag__ x)); return res; }
__complex__ float __catanf (__complex__ float x) { __complex__ float res; int rcls = fpclassify (__real__ x); int icls = fpclassify (__imag__ x); if (__glibc_unlikely (rcls <= FP_INFINITE || icls <= FP_INFINITE)) { if (rcls == FP_INFINITE) { __real__ res = __copysignf (M_PI_2, __real__ x); __imag__ res = __copysignf (0.0, __imag__ x); } else if (icls == FP_INFINITE) { if (rcls >= FP_ZERO) __real__ res = __copysignf (M_PI_2, __real__ x); else __real__ res = __nanf (""); __imag__ res = __copysignf (0.0, __imag__ x); } else if (icls == FP_ZERO || icls == FP_INFINITE) { __real__ res = __nanf (""); __imag__ res = __copysignf (0.0, __imag__ x); } else { __real__ res = __nanf (""); __imag__ res = __nanf (""); } } else if (__glibc_unlikely (rcls == FP_ZERO && icls == FP_ZERO)) { res = x; } else { if (fabsf (__real__ x) >= 16.0f / FLT_EPSILON || fabsf (__imag__ x) >= 16.0f / FLT_EPSILON) { __real__ res = __copysignf ((float) M_PI_2, __real__ x); if (fabsf (__real__ x) <= 1.0f) __imag__ res = 1.0f / __imag__ x; else if (fabsf (__imag__ x) <= 1.0f) __imag__ res = __imag__ x / __real__ x / __real__ x; else { float h = __ieee754_hypotf (__real__ x / 2.0f, __imag__ x / 2.0f); __imag__ res = __imag__ x / h / h / 4.0f; } } else { float den, absx, absy; absx = fabsf (__real__ x); absy = fabsf (__imag__ x); if (absx < absy) { float t = absx; absx = absy; absy = t; } if (absy < FLT_EPSILON / 2.0f) { den = (1.0f - absx) * (1.0f + absx); if (den == -0.0f) den = 0.0f; } else if (absx >= 1.0f) den = (1.0f - absx) * (1.0f + absx) - absy * absy; else if (absx >= 0.75f || absy >= 0.5f) den = -__x2y2m1f (absx, absy); else den = (1.0f - absx) * (1.0f + absx) - absy * absy; __real__ res = 0.5f * __ieee754_atan2f (2.0f * __real__ x, den); if (fabsf (__imag__ x) == 1.0f && fabsf (__real__ x) < FLT_EPSILON * FLT_EPSILON) __imag__ res = (__copysignf (0.5f, __imag__ x) * ((float) M_LN2 - __ieee754_logf (fabsf (__real__ x)))); else { float r2 = 0.0f, num, f; if (fabsf (__real__ x) >= FLT_EPSILON * FLT_EPSILON) r2 = __real__ x * __real__ x; num = __imag__ x + 1.0f; num = r2 + num * num; den = __imag__ x - 1.0f; den = r2 + den * den; f = num / den; if (f < 0.5f) __imag__ res = 0.25f * __ieee754_logf (f); else { num = 4.0f * __imag__ x; __imag__ res = 0.25f * __log1pf (num / den); } } } if (fabsf (__real__ res) < FLT_MIN) { volatile float force_underflow = __real__ res * __real__ res; (void) force_underflow; } if (fabsf (__imag__ res) < FLT_MIN) { volatile float force_underflow = __imag__ res * __imag__ res; (void) force_underflow; } } return res; }
float __ieee754_lgammaf_r(float x, int *signgamp) { float t,y,z,nadj,p,p1,p2,p3,q,r,w; int32_t hx; int i,ix; GET_FLOAT_WORD(hx,x); /* purge off +-inf, NaN, +-0, tiny and negative arguments */ *signgamp = 1; ix = hx&0x7fffffff; if(ix>=0x7f800000) return x*x; if(ix==0) return one/zero; if(ix<0x35000000) { /* |x|<2**-21, return -log(|x|) */ if(hx<0) { *signgamp = -1; return -__ieee754_logf(-x); } else return -__ieee754_logf(x); } if(hx<0) { if(ix>=0x4b000000) /* |x|>=2**23, must be -integer */ return one/zero; t = sin_pif(x); if(t==zero) return one/zero; /* -integer */ nadj = __ieee754_logf(pi/fabsf(t*x)); if(t<zero) *signgamp = -1; x = -x; } /* purge off 1 and 2 */ if (ix==0x3f800000||ix==0x40000000) r = 0; /* for x < 2.0 */ else if(ix<0x40000000) { if(ix<=0x3f666666) { /* lgamma(x) = lgamma(x+1)-log(x) */ r = -__ieee754_logf(x); if(ix>=0x3f3b4a20) {y = one-x; i= 0;} else if(ix>=0x3e6d3308) {y= x-(tc-one); i=1;} else {y = x; i=2;} } else { r = zero; if(ix>=0x3fdda618) {y=(float)2.0-x;i=0;} /* [1.7316,2] */ else if(ix>=0x3F9da620) {y=x-tc;i=1;} /* [1.23,1.73] */ else {y=x-one;i=2;} } switch(i) { case 0: z = y*y; p1 = a0+z*(a2+z*(a4+z*(a6+z*(a8+z*a10)))); p2 = z*(a1+z*(a3+z*(a5+z*(a7+z*(a9+z*a11))))); p = y*p1+p2; r += (p-(float)0.5*y); break; case 1: z = y*y; w = z*y; p1 = t0+w*(t3+w*(t6+w*(t9 +w*t12))); /* parallel comp */ p2 = t1+w*(t4+w*(t7+w*(t10+w*t13))); p3 = t2+w*(t5+w*(t8+w*(t11+w*t14))); p = z*p1-(tt-w*(p2+y*p3)); r += (tf + p); break; case 2: p1 = y*(u0+y*(u1+y*(u2+y*(u3+y*(u4+y*u5))))); p2 = one+y*(v1+y*(v2+y*(v3+y*(v4+y*v5)))); r += (-(float)0.5*y + p1/p2); } } else if(ix<0x41000000) { /* x < 8.0 */ i = (int)x; y = x-(float)i; p = y*(s0+y*(s1+y*(s2+y*(s3+y*(s4+y*(s5+y*s6)))))); q = one+y*(r1+y*(r2+y*(r3+y*(r4+y*(r5+y*r6))))); r = half*y+p/q; z = one; /* lgamma(1+s) = log(s) + lgamma(s) */ switch(i) { case 7: z *= (y+(float)6.0); /* FALLTHRU */ case 6: z *= (y+(float)5.0); /* FALLTHRU */ case 5: z *= (y+(float)4.0); /* FALLTHRU */ case 4: z *= (y+(float)3.0); /* FALLTHRU */ case 3: z *= (y+(float)2.0); /* FALLTHRU */ r += __ieee754_logf(z); break; } /* 8.0 <= x < 2**58 */ } else if (ix < 0x5c800000) { t = __ieee754_logf(x); z = one/x; y = z*z; w = w0+z*(w1+y*(w2+y*(w3+y*(w4+y*(w5+y*w6))))); r = (x-half)*(t-one)+w; } else /* 2**58 <= x <= inf */ r = x*(__ieee754_logf(x)-one); if(hx<0) r = nadj - r; return r; }
static float gammaf_positive (float x, int *exp2_adj) { int local_signgam; if (x < 0.5f) { *exp2_adj = 0; return __ieee754_expf (__ieee754_lgammaf_r (x + 1, &local_signgam)) / x; } else if (x <= 1.5f) { *exp2_adj = 0; return __ieee754_expf (__ieee754_lgammaf_r (x, &local_signgam)); } else if (x < 2.5f) { *exp2_adj = 0; float x_adj = x - 1; return (__ieee754_expf (__ieee754_lgammaf_r (x_adj, &local_signgam)) * x_adj); } else { float eps = 0; float x_eps = 0; float x_adj = x; float prod = 1; if (x < 4.0f) { /* Adjust into the range for applying Stirling's approximation. */ float n = __ceilf (4.0f - x); x_adj = math_narrow_eval (x + n); x_eps = (x - (x_adj - n)); prod = __gamma_productf (x_adj - n, x_eps, n, &eps); } /* The result is now gamma (X_ADJ + X_EPS) / (PROD * (1 + EPS)). Compute gamma (X_ADJ + X_EPS) using Stirling's approximation, starting by computing pow (X_ADJ, X_ADJ) with a power of 2 factored out. */ float exp_adj = -eps; float x_adj_int = __roundf (x_adj); float x_adj_frac = x_adj - x_adj_int; int x_adj_log2; float x_adj_mant = __frexpf (x_adj, &x_adj_log2); if (x_adj_mant < (float) M_SQRT1_2) { x_adj_log2--; x_adj_mant *= 2.0f; } *exp2_adj = x_adj_log2 * (int) x_adj_int; float ret = (__ieee754_powf (x_adj_mant, x_adj) * __ieee754_exp2f (x_adj_log2 * x_adj_frac) * __ieee754_expf (-x_adj) * __ieee754_sqrtf (2 * (float) M_PI / x_adj) / prod); exp_adj += x_eps * __ieee754_logf (x_adj); float bsum = gamma_coeff[NCOEFF - 1]; float x_adj2 = x_adj * x_adj; for (size_t i = 1; i <= NCOEFF - 1; i++) bsum = bsum / x_adj2 + gamma_coeff[NCOEFF - 1 - i]; exp_adj += bsum / x_adj; return ret + ret * __expm1f (exp_adj); } }
__complex__ float __clogf (__complex__ float x) { __complex__ float result; int rcls = fpclassify (__real__ x); int icls = fpclassify (__imag__ x); if (__builtin_expect (rcls == FP_ZERO && icls == FP_ZERO, 0)) { /* Real and imaginary part are 0.0. */ __imag__ result = signbit (__real__ x) ? M_PI : 0.0; __imag__ result = __copysignf (__imag__ result, __imag__ x); /* Yes, the following line raises an exception. */ __real__ result = -1.0 / fabsf (__real__ x); } else if (__builtin_expect (rcls != FP_NAN && icls != FP_NAN, 1)) { /* Neither real nor imaginary part is NaN. */ float absx = fabsf (__real__ x), absy = fabsf (__imag__ x); int scale = 0; if (absx < absy) { float t = absx; absx = absy; absy = t; } if (absx > FLT_MAX / 2.0f) { scale = -1; absx = __scalbnf (absx, scale); absy = (absy >= FLT_MIN * 2.0f ? __scalbnf (absy, scale) : 0.0f); } else if (absx < FLT_MIN && absy < FLT_MIN) { scale = FLT_MANT_DIG; absx = __scalbnf (absx, scale); absy = __scalbnf (absy, scale); } if (absx == 1.0f && scale == 0) { float absy2 = absy * absy; if (absy2 <= FLT_MIN * 2.0f) { #if __FLT_EVAL_METHOD__ == 0 __real__ result = absy2 / 2.0f - absy2 * absy2 / 4.0f; #else volatile float force_underflow = absy2 * absy2 / 4.0f; __real__ result = absy2 / 2.0f - force_underflow; #endif } else __real__ result = __log1pf (absy2) / 2.0f; } else if (absx > 1.0f && absx < 2.0f && absy < 1.0f && scale == 0) { float d2m1 = (absx - 1.0f) * (absx + 1.0f); if (absy >= FLT_EPSILON) d2m1 += absy * absy; __real__ result = __log1pf (d2m1) / 2.0f; } else if (absx < 1.0f && absx >= 0.75f && absy < FLT_EPSILON / 2.0f && scale == 0) { float d2m1 = (absx - 1.0f) * (absx + 1.0f); __real__ result = __log1pf (d2m1) / 2.0f; } else if (absx < 1.0f && (absx >= 0.75f || absy >= 0.5f) && scale == 0) { float d2m1 = __x2y2m1f (absx, absy); __real__ result = __log1pf (d2m1) / 2.0f; } else { float d = __ieee754_hypotf (absx, absy); __real__ result = __ieee754_logf (d) - scale * (float) M_LN2; } __imag__ result = __ieee754_atan2f (__imag__ x, __real__ x); } else { __imag__ result = __nanf (""); if (rcls == FP_INFINITE || icls == FP_INFINITE) /* Real or imaginary part is infinite. */ __real__ result = HUGE_VALF; else __real__ result = __nanf (""); } return result; }
//------------------------------------------------------------------------------ float Cmath::__ieee754_lgammaf_r( float x, int* signgamp ) { static const float half = 5.0000000000e-01; // 0x3f000000 static const float one = 1.0000000000e+00; // 0x3f800000 static const float pi = 3.1415927410e+00; // 0x40490fdb static const float a0 = 7.7215664089e-02; // 0x3d9e233f static const float a1 = 3.2246702909e-01; // 0x3ea51a66 static const float a2 = 6.7352302372e-02; // 0x3d89f001 static const float a3 = 2.0580807701e-02; // 0x3ca89915 static const float a4 = 7.3855509982e-03; // 0x3bf2027e static const float a5 = 2.8905137442e-03; // 0x3b3d6ec6 static const float a6 = 1.1927076848e-03; // 0x3a9c54a1 static const float a7 = 5.1006977446e-04; // 0x3a05b634 static const float a8 = 2.2086278477e-04; // 0x39679767 static const float a9 = 1.0801156895e-04; // 0x38e28445 static const float a10 = 2.5214456400e-05; // 0x37d383a2 static const float a11 = 4.4864096708e-05; // 0x383c2c75 static const float tc = 1.4616321325e+00; // 0x3fbb16c3 static const float tf = -1.2148628384e-01; // 0xbdf8cdcd // tt = -(tail of tf) static const float tt = 6.6971006518e-09; // 0x31e61c52 static const float t0 = 4.8383611441e-01; // 0x3ef7b95e static const float t1 = -1.4758771658e-01; // 0xbe17213c static const float t2 = 6.4624942839e-02; // 0x3d845a15 static const float t3 = -3.2788541168e-02; // 0xbd064d47 static const float t4 = 1.7970675603e-02; // 0x3c93373d static const float t5 = -1.0314224288e-02; // 0xbc28fcfe static const float t6 = 6.1005386524e-03; // 0x3bc7e707 static const float t7 = -3.6845202558e-03; // 0xbb7177fe static const float t8 = 2.2596477065e-03; // 0x3b141699 static const float t9 = -1.4034647029e-03; // 0xbab7f476 static const float t10 = 8.8108185446e-04; // 0x3a66f867 static const float t11 = -5.3859531181e-04; // 0xba0d3085 static const float t12 = 3.1563205994e-04; // 0x39a57b6b static const float t13 = -3.1275415677e-04; // 0xb9a3f927 static const float t14 = 3.3552918467e-04; // 0x39afe9f7 static const float u0 = -7.7215664089e-02; // 0xbd9e233f static const float u1 = 6.3282704353e-01; // 0x3f2200f4 static const float u2 = 1.4549225569e+00; // 0x3fba3ae7 static const float u3 = 9.7771751881e-01; // 0x3f7a4bb2 static const float u4 = 2.2896373272e-01; // 0x3e6a7578 static const float u5 = 1.3381091878e-02; // 0x3c5b3c5e static const float v1 = 2.4559779167e+00; // 0x401d2ebe static const float v2 = 2.1284897327e+00; // 0x4008392d static const float v3 = 7.6928514242e-01; // 0x3f44efdf static const float v4 = 1.0422264785e-01; // 0x3dd572af static const float v5 = 3.2170924824e-03; // 0x3b52d5db static const float s0 = -7.7215664089e-02; // 0xbd9e233f static const float s1 = 2.1498242021e-01; // 0x3e5c245a static const float s2 = 3.2577878237e-01; // 0x3ea6cc7a static const float s3 = 1.4635047317e-01; // 0x3e15dce6 static const float s4 = 2.6642270386e-02; // 0x3cda40e4 static const float s5 = 1.8402845599e-03; // 0x3af135b4 static const float s6 = 3.1947532989e-05; // 0x3805ff67 static const float r1 = 1.3920053244e+00; // 0x3fb22d3b static const float r2 = 7.2193557024e-01; // 0x3f38d0c5 static const float r3 = 1.7193385959e-01; // 0x3e300f6e static const float r4 = 1.8645919859e-02; // 0x3c98bf54 static const float r5 = 7.7794247773e-04; // 0x3a4beed6 static const float r6 = 7.3266842264e-06; // 0x36f5d7bd static const float w0 = 4.1893854737e-01; // 0x3ed67f1d static const float w1 = 8.3333335817e-02; // 0x3daaaaab static const float w2 = -2.7777778450e-03; // 0xbb360b61 static const float w3 = 7.9365057172e-04; // 0x3a500cfd static const float w4 = -5.9518753551e-04; // 0xba1c065c static const float w5 = 8.3633989561e-04; // 0x3a5b3dd2 static const float w6 = -1.6309292987e-03; // 0xbad5c4e8 static const float zero= 0.0000000000e+00; float t, y, z, nadj, p, p1, p2, p3, q, r, w; Cmp_signed__int32 i, hx, ix; get_float_word( hx, x ); // purge off +-inf, NaN, +-0, and negative arguments *signgamp = 1; ix = hx & 0x7fffffff; if( ix >= 0x7f800000 ) { return x * x; } if( ix == 0 ) { return one / zero; } if( ix < 0x1c800000 ) { // |x|<2**-70, return -log(|x|) if( hx < 0 ) { *signgamp = -1; return -__ieee754_logf( -x ); } else { return -__ieee754_logf( x ); } } if( hx < 0 ) { if( ix >= 0x4b000000 ) // |x|>=2**23, must be -integer { return one / zero; } t = sin_pif( x ); if( t == zero ) { return one / zero; // -integer } nadj = __ieee754_logf( pi / fabsf( t * x ) ); if( t < zero ) { *signgamp = -1; } x = -x; } // purge off 1 and 2 if( ix == 0x3f800000 || ix == 0x40000000 ) { r = 0; }// for x < 2.0 else if( ix < 0x40000000 ) { if( ix <= 0x3f666666 ) { // lgamma(x) = lgamma(x+1)-log(x) r = -__ieee754_logf( x ); if( ix >= 0x3f3b4a20 ) { y = one - x; i = 0; } else if( ix >= 0x3e6d3308 ) { y = x - ( tc - one ); i = 1; } else { y = x; i=2; } } else { r = zero; if( ix >= 0x3fdda618 ) { y = (float)2.0 - x; i = 0; } // [1.7316,2] else if( ix >= 0x3F9da620 ) { y = x - tc; i = 1; } // [1.23,1.73] else { y = x - one; i = 2; } } switch( i ) { case 0: z = y * y; p1 = a0 + z * ( a2 + z * ( a4 + z * ( a6 + z * ( a8 + z * a10 ) ) ) ); p2 = z * ( a1 + z * ( a3 + z * ( a5 + z * ( a7 + z * ( a9 + z * a11 ) ) ) ) ); p = y * p1 + p2; r += ( p - (float)0.5 * y ); break; case 1: z = y * y; w = z * y; p1 = t0 + w * ( t3 + w * ( t6 + w * ( t9 + w * t12 ) ) ); // parallel comp p2 = t1 + w * ( t4 + w * ( t7 + w * ( t10 + w * t13 ) ) ); p3 = t2 + w * ( t5 + w * ( t8 + w * ( t11 + w * t14 ) ) ); p = z * p1 -( tt - w * ( p2 + y * p3 ) ); r += ( tf + p ); break; case 2: p1 = y * ( u0 + y * ( u1 + y * ( u2 + y * ( u3 + y * ( u4 + y * u5 ) ) ) ) ); p2 = one + y * ( v1 + y * ( v2 + y * ( v3 + y * ( v4 + y * v5 ) ) ) ); r += ( -(float)0.5 * y + p1 / p2 ); } } else if( ix <0x41000000 ) { // x < 8.0 i = (Cmp_signed__int32)x; t = zero; y = x -(float)i; p = y * ( s0 + y * ( s1 + y * ( s2 + y * ( s3 + y * ( s4 + y * ( s5 + y * s6 ) ) ) ) ) ); q = one + y * ( r1 + y * ( r2 + y * ( r3 + y * ( r4 + y * ( r5 + y * r6 ) ) ) ) ); r = half * y + p / q; z = one; // lgamma(1+s) = log(s) + lgamma(s) switch( i ) { case 7: z *= ( y + (float)6.0 ); // FALLTHRU case 6: z *= ( y + (float)5.0 ); // FALLTHRU case 5: z *= ( y + (float)4.0 ); // FALLTHRU case 4: z *= ( y + (float)3.0 ); // FALLTHRU case 3: z *= ( y + (float)2.0 ); // FALLTHRU r += __ieee754_logf( z ); break; } // 8.0 <= x < 2**58 } else if( ix < 0x5c800000 ) { t = __ieee754_logf( x ); z = one / x; y = z * z; w = w0 + z * ( w1 + y * ( w2 + y * ( w3 + y * ( w4 + y * ( w5 + y * w6 ) ) ) ) ); r = ( x - half ) * ( t - one ) + w; } else { // 2**58 <= x <= inf r = x * ( __ieee754_logf( x ) - one ); } if( hx < 0 ) { r = nadj - r; } return r; }