float __ieee754_log10f(float x) { float f,hi,lo,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; hx &= 0x007fffff; i = (hx+(0x4afb0d))&0x800000; SET_FLOAT_WORD(x,hx|(i^0x3f800000)); /* normalize x or x/2 */ k += (i>>23); y = (float)k; f = __kernel_logf(x); x = x - (float)1.0; GET_FLOAT_WORD(hx,x); SET_FLOAT_WORD(hi,hx&0xfffff000); lo = x - hi; z = y*log10_2lo + (x+f)*ivln10lo + (lo+f)*ivln10hi + hi*ivln10hi; return z+y*log10_2hi; }
float cbrtf(float x) { float r,s,t; int32_t hx; uint32_t sign; uint32_t high; GET_FLOAT_WORD(hx,x); sign=hx&0x80000000; /* sign= sign(x) */ hx ^=sign; if(hx>=0x7f800000) return(x+x); /* cbrt(NaN,INF) is itself */ if(hx==0) return(x); /* cbrt(0) is itself */ SET_FLOAT_WORD(x,hx); /* x <- |x| */ /* rough cbrt to 5 bits */ if(hx<0x00800000) /* subnormal number */ {SET_FLOAT_WORD(t,0x4b800000); /* set t= 2**24 */ t*=x; GET_FLOAT_WORD(high,t); SET_FLOAT_WORD(t,high/3+B2); } else SET_FLOAT_WORD(t,hx/3+B1); /* new cbrt to 23 bits */ r=t*t/x; s=C+r*t; t*=G+F/(s+E+D/s); /* retore the sign bit */ GET_FLOAT_WORD(high,t); SET_FLOAT_WORD(t,high|sign); return(t); }
DLLEXPORT float cbrtf(float x) { double r,T; float t; int32_t hx; u_int32_t sign; u_int32_t high; GET_FLOAT_WORD(hx,x); sign=hx&0x80000000; /* sign= sign(x) */ hx ^=sign; if(hx>=0x7f800000) return(x+x); /* cbrt(NaN,INF) is itself */ /* rough cbrt to 5 bits */ if(hx<0x00800000) { /* zero or subnormal? */ if(hx==0) return(x); /* cbrt(+-0) is itself */ SET_FLOAT_WORD(t,0x4b800000); /* set t= 2**24 */ #if _TMS320C6X float __fmpy_by_0x1p24(float); x = __fmpy_by_0x1p24(x); #endif t*=x; GET_FLOAT_WORD(high,t); SET_FLOAT_WORD(t,sign|((high&0x7fffffff)/3+B2)); } else SET_FLOAT_WORD(t,sign|(hx/3+B1)); /* * First step Newton iteration (solving t*t-x/t == 0) to 16 bits. In * double precision so that its terms can be arranged for efficiency * without causing overflow or underflow. */ T=t; r=T*T*T; T=T*((double)x+x+r)/(x+r+r); /* * Second step Newton iteration to 47 bits. In double precision for * efficiency and accuracy. */ r=T*T*T; T=T*((double)x+x+r)/(x+r+r); #if _TMS320C6X if(hx<0x00800000) { /* zero or subnormal? */ T /= 0x1p8; } #endif /* rounding to 24 bits is perfect in round-to-nearest mode */ return(T); }
float __ieee754_log2f(float x) { float f,hfsq,hi,lo,r,y; int32_t i,k,hx; GET_FLOAT_WORD(hx,x); k=0; if (hx < 0x00800000) { /* x < 2**-126 */ if ((hx&0x7fffffff)==0) return -two25/vzero; /* 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; if (hx == 0x3f800000) return zero; /* log(1) = +0 */ k += (hx>>23)-127; hx &= 0x007fffff; i = (hx+(0x4afb0d))&0x800000; SET_FLOAT_WORD(x,hx|(i^0x3f800000)); /* normalize x or x/2 */ k += (i>>23); y = (float)k; f = x - (float)1.0; hfsq = (float)0.5*f*f; r = k_log1pf(f); /* * We no longer need to avoid falling into the multi-precision * calculations due to compiler bugs breaking Dekker's theorem. * Keep avoiding this as an optimization. See e_log2.c for more * details (some details are here only because the optimization * is not yet available in double precision). * * Another compiler bug turned up. With gcc on i386, * (ivln2lo + ivln2hi) would be evaluated in float precision * despite runtime evaluations using double precision. So we * must cast one of its terms to float_t. This makes the whole * expression have type float_t, so return is forced to waste * time clobbering its extra precision. */ if (sizeof(float_t) > sizeof(float)) return (r - hfsq + f) * ((float_t)ivln2lo + ivln2hi) + y; hi = f - hfsq; GET_FLOAT_WORD(hx,hi); SET_FLOAT_WORD(hi,hx&0xfffff000); lo = (f - hi) - hfsq + r; return (lo+hi)*ivln2lo + lo*ivln2hi + hi*ivln2hi + y; }
float nextafterf(float x, float y) { int32_t hx, hy, ix, iy; GET_FLOAT_WORD(hx, x); GET_FLOAT_WORD(hy, y); ix = hx & 0x7fffffff; /* |x| */ iy = hy & 0x7fffffff; /* |y| */ /* x is nan or y is nan? */ if ((ix > 0x7f800000) || (iy > 0x7f800000)) return x + y; if (x == y) return y; if (ix == 0) { /* x == 0? */ /* glibc 2.4 does not seem to set underflow? */ /* float u; */ /* return +-minsubnormal */ SET_FLOAT_WORD(x, (hy & 0x80000000) | 1); /* u = x * x; raise underflow flag */ /* math_force_eval(u); */ return x; } if (hx >= 0) { /* x > 0 */ if (hx > hy) { /* x > y: x -= ulp */ hx -= 1; } else { /* x < y: x += ulp */ hx += 1; } } else { /* x < 0 */ if (hy >= 0 || hx > hy) { /* x < y: x -= ulp */ hx -= 1; } else { /* x > y: x += ulp */ hx += 1; } } hy = hx & 0x7f800000; if (hy >= 0x7f800000) { x = x + x; /* overflow */ return x; /* overflow */ } if (hy < 0x00800000) { float u = x * x; /* underflow */ math_force_eval(u); /* raise underflow flag */ } SET_FLOAT_WORD(x, hx); return x; }
float npy_nextafterf(float x, float y) { volatile float t; npy_int32 hx, hy, ix, iy; GET_FLOAT_WORD(hx, x); GET_FLOAT_WORD(hy, y); ix = hx & 0x7fffffff; /* |x| */ iy = hy & 0x7fffffff; /* |y| */ if ((ix > 0x7f800000) || /* x is nan */ (iy > 0x7f800000)) /* y is nan */ return x + y; if (x == y) return y; /* x=y, return y */ if (ix == 0) { /* x == 0 */ SET_FLOAT_WORD(x, (hy & 0x80000000) | 1); /* return +-minsubnormal */ t = x * x; if (t == x) return t; else return x; /* raise underflow flag */ } if (hx >= 0) { /* x > 0 */ if (hx > hy) { /* x > y, x -= ulp */ hx -= 1; } else { /* x < y, x += ulp */ hx += 1; } } else { /* x < 0 */ if (hy >= 0 || hx > hy) { /* x < y, x -= ulp */ hx -= 1; } else { /* x > y, x += ulp */ hx += 1; } } hy = hx & 0x7f800000; if (hy >= 0x7f800000) return x + x; /* overflow */ if (hy < 0x00800000) { /* underflow */ t = x * x; if (t != x) { /* raise underflow flag */ SET_FLOAT_WORD(y, hx); return y; } } SET_FLOAT_WORD(x, hx); return x; }
float __nexttowardf(float x, long double y) { int32_t hx,ix,iy; uint32_t hy,ly,esy; GET_FLOAT_WORD(hx,x); GET_LDOUBLE_WORDS(esy,hy,ly,y); ix = hx&0x7fffffff; /* |x| */ iy = esy&0x7fff; /* |y| */ if((ix>0x7f800000) || /* x is nan */ (iy>=0x7fff&&((hy|ly)!=0))) /* y is nan */ return x+y; if((long double) x==y) return y; /* x=y, return y */ if(ix==0) { /* x == 0 */ float u; SET_FLOAT_WORD(x,((esy&0x8000)<<16)|1);/* return +-minsub*/ u = math_opt_barrier (x); u = u * u; math_force_eval (u); /* raise underflow flag */ return x; } if(hx>=0) { /* x > 0 */ if(x > y) { /* x -= ulp */ hx -= 1; } else { /* x < y, x += ulp */ hx += 1; } } else { /* x < 0 */ if(x < y) { /* x -= ulp */ hx -= 1; } else { /* x > y, x += ulp */ hx += 1; } } hy = hx&0x7f800000; if(hy>=0x7f800000) { float u = x+x; /* overflow */ math_force_eval (u); __set_errno (ERANGE); } if(hy<0x00800000) { float u = x*x; /* underflow */ math_force_eval (u); /* raise underflow flag */ __set_errno (ERANGE); } SET_FLOAT_WORD(x,hx); return x; }
float nextafterf(float x, float y) { int32_t hx,hy,ix,iy; GET_FLOAT_WORD(hx,x); GET_FLOAT_WORD(hy,y); ix = hx&0x7fffffff; /* |x| */ iy = hy&0x7fffffff; /* |y| */ if((ix>0x7f800000) || /* x is nan */ (iy>0x7f800000)) /* y is nan */ return x+y; if(x==y) return y; /* x=y, return y */ if(ix==0) { /* x == 0 */ //float u; SET_FLOAT_WORD(x,(hy&0x80000000)|1);/* return +-minsubnormal */ //u = math_opt_barrier (x); //u = u*u; //math_force_eval (u); /* raise underflow flag */ return x; } if(hx>=0) { /* x > 0 */ if(hx>hy) { /* x > y, x -= ulp */ hx -= 1; } else { /* x < y, x += ulp */ hx += 1; } } else { /* x < 0 */ if(hy>=0||hx>hy){ /* x < y, x -= ulp */ hx -= 1; } else { /* x > y, x += ulp */ hx += 1; } } hy = hx&0x7f800000; if(hy>=0x7f800000) { x = x+x; /* overflow */ //if (FLT_EVAL_METHOD != 0) // asm ("" : "+m"(x)); return x; /* overflow */ } //if(hy<0x00800000) { // float u = x*x; /* underflow */ // math_force_eval (u); /* raise underflow flag */ //} SET_FLOAT_WORD(x,hx); return x; }
float __kernel_cosf(float x, float y) { float a,hz,z,r,qx; int32_t ix; GET_FLOAT_WORD(ix,x); ix &= 0x7fffffff; /* ix = |x|'s high word*/ if(ix<0x32000000) { /* if x < 2**27 */ if(((int)x)==0) return one; /* generate inexact */ } z = x*x; r = z*(C1+z*(C2+z*(C3+z*(C4+z*(C5+z*C6))))); if(ix < 0x3e99999a) /* if |x| < 0.3 */ return one - ((float)0.5*z - (z*r - x*y)); else { if(ix > 0x3f480000) { /* x > 0.78125 */ qx = (float)0.28125; } else { SET_FLOAT_WORD(qx,ix-0x01000000); /* x/4 */ } hz = (float)0.5*z-qx; a = one-qx; return a - (hz - (z*r-x*y)); } }
float nanf(const char *unused) { float x; SET_FLOAT_WORD(x,0x7fc00000); return x; }
float log10f(float x) { float y, z; s32_t i, k, hx; GET_FLOAT_WORD(hx,x); k = 0; if (hx < 0x00800000) { if ((hx & 0x7fffffff) == 0) return -two25 / zero; if (hx < 0) return (x - x) / zero; k -= 25; x *= two25; GET_FLOAT_WORD(hx,x); } if (hx >= 0x7f800000) return x + x; k += (hx >> 23) - 127; i = ((u32_t) k & 0x80000000) >> 31; hx = (hx & 0x007fffff) | ((0x7f - i) << 23); y = (float) (k + i); SET_FLOAT_WORD(x,hx); z = y * log10_2lo + ivln10 * logf(x); return z + y * log10_2hi; }
float frexpf(float x, int *eptr) { s32_t hx, ix; GET_FLOAT_WORD(hx,x); ix = 0x7fffffff & hx; *eptr = 0; if (ix >= 0x7f800000 || (ix == 0)) return x; if (ix < 0x00800000) { x *= two25; GET_FLOAT_WORD(hx,x); ix = hx & 0x7fffffff; *eptr = -25; } *eptr += (ix >> 23) - 126; hx = (hx & 0x807fffff) | 0x3f000000; SET_FLOAT_WORD(x,hx); return x; }
float 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*logf(x); return z+y*log10_2hi; }
float complex ctanhf(float complex z) { float x, y; float t, beta, s, rho, denom; uint32_t hx, ix; x = crealf(z); y = cimagf(z); GET_FLOAT_WORD(hx, x); ix = hx & 0x7fffffff; if (ix >= 0x7f800000) { if (ix & 0x7fffff) return CMPLXF(x, (y == 0 ? y : x * y)); SET_FLOAT_WORD(x, hx - 0x40000000); return CMPLXF(x, copysignf(0, isinf(y) ? y : sinf(y) * cosf(y))); } if (!isfinite(y)) return CMPLXF(y - y, y - y); if (ix >= 0x41300000) { /* x >= 11 */ float exp_mx = expf(-fabsf(x)); return CMPLXF(copysignf(1, x), 4 * sinf(y) * cosf(y) * exp_mx * exp_mx); } t = tanf(y); beta = 1.0 + t * t; s = sinhf(x); rho = sqrtf(1 + s * s); denom = 1 + beta * s * s; return CMPLXF((beta * rho * s) / denom, t / denom); }
float scalbnf(float x, int n) { float scale; if (n > 127) { x *= 0x1p127f; n -= 127; if (n > 127) { x *= 0x1p127f; n -= 127; if (n > 127) { x = (float)(x * 0x1p127f); return x; } } } else if (n < -126) { x *= 0x1p-126f; n += 126; if (n < -126) { x *= 0x1p-126f; n += 126; if (n < -126) { x = (float)(x * 0x1p-126f); return x; } } } SET_FLOAT_WORD(scale, (uint32_t)(0x7f+n)<<23); x = (float)(x * scale); return x; }
DLLEXPORT float __ieee754_log10f(float x) { float f,hfsq,hi,lo,r,y; 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; #if _TMS320C6X float __fmpy_by_0x1p25(float); x = __fmpy_by_0x1p25(x); #else x *= two25; /* subnormal number, scale up x */ #endif GET_FLOAT_WORD(hx,x); } if (hx >= 0x7f800000) return x+x; if (hx == 0x3f800000) return zero; /* log(1) = +0 */ k += (hx>>23)-127; hx &= 0x007fffff; i = (hx+(0x4afb0d))&0x800000; SET_FLOAT_WORD(x,hx|(i^0x3f800000)); /* normalize x or x/2 */ k += (i>>23); y = (float)k; f = x - (float)1.0; hfsq = (float)0.5*f*f; r = k_log1pf(f); /* See e_log2f.c and e_log2.c for details. */ if (sizeof(float_t) > sizeof(float)) return (r - hfsq + f) * ((float_t)ivln10lo + ivln10hi) + y * ((float_t)log10_2lo + log10_2hi); hi = f - hfsq; GET_FLOAT_WORD(hx,hi); SET_FLOAT_WORD(hi,hx&0xfffff000); lo = (f - hi) - hfsq + r; return y*log10_2lo + (lo+hi)*ivln10lo + lo*ivln10hi + hi*ivln10hi + y*log10_2hi; }
float __nldbl_nexttowardf(float x, double y) { int32_t hx,hy,ix,iy; u_int32_t ly; GET_FLOAT_WORD(hx,x); EXTRACT_WORDS(hy,ly,y); ix = hx&0x7fffffff; /* |x| */ iy = hy&0x7fffffff; /* |y| */ if((ix>0x7f800000) || /* x is nan */ ((iy>=0x7ff00000)&&((iy-0x7ff00000)|ly)!=0)) /* y is nan */ return x+y; if((double) x==y) return y; /* x=y, return y */ if(ix==0) { /* x == 0 */ float u; SET_FLOAT_WORD(x,(u_int32_t)(hy&0x80000000)|1);/* return +-minsub*/ u = math_opt_barrier (x); u = u * u; math_force_eval (u); /* raise underflow flag */ return x; } if(hx>=0) { /* x > 0 */ if(x > y) /* x -= ulp */ hx -= 1; else /* x < y, x += ulp */ hx += 1; } else { /* x < 0 */ if(x < y) /* x -= ulp */ hx -= 1; else /* x > y, x += ulp */ hx += 1; } hy = hx&0x7f800000; if(hy>=0x7f800000) { float u = x+x; /* overflow */ math_force_eval (u); __set_errno (ERANGE); } if(hy<0x00800000) { float u = x*x; /* underflow */ math_force_eval (u); /* raise underflow flag */ __set_errno (ERANGE); } SET_FLOAT_WORD(x,hx); return x; }
float __copysignf(float x, float y) { uint32_t ix,iy; GET_FLOAT_WORD(ix,x); GET_FLOAT_WORD(iy,y); SET_FLOAT_WORD(x,(ix&0x7fffffff)|(iy&0x80000000)); return x; }
float fabsf(float x) { u_int32_t ix; GET_FLOAT_WORD(ix,x); SET_FLOAT_WORD(x,ix&0x7fffffff); return x; }
/* expf(x)/2 for x >= log(FLT_MAX), slightly better than 0.5f*expf(x/2)*expf(x/2) */ float __expo2f(float x) { float scale; /* note that k is odd and scale*scale overflows */ SET_FLOAT_WORD(scale, (uint32_t)(0x7f + k/2) << 23); /* exp(x - k ln2) * 2**(k-1) */ return expf(x - kln2) * scale * scale; }
float log10f(float x) { float f,hfsq,hi,lo,r,y; int32_t i,k,hx; GET_FLOAT_WORD(hx, x); k = 0; if (hx < 0x00800000) { /* x < 2**-126 */ if ((hx&0x7fffffff) == 0) return -two25/0.0f; /* log(+-0)=-inf */ if (hx < 0) return (x-x)/0.0f; /* log(-#) = NaN */ /* subnormal number, scale up x */ k -= 25; x *= two25; GET_FLOAT_WORD(hx, x); } if (hx >= 0x7f800000) return x+x; if (hx == 0x3f800000) return 0.0f; /* log(1) = +0 */ k += (hx>>23) - 127; hx &= 0x007fffff; i = (hx+(0x4afb0d))&0x800000; SET_FLOAT_WORD(x, hx|(i^0x3f800000)); /* normalize x or x/2 */ k += i>>23; y = (float)k; f = x - 1.0f; hfsq = 0.5f * f * f; r = __log1pf(f); // FIXME // /* See log2f.c and log2.c for details. */ // if (sizeof(float_t) > sizeof(float)) // return (r - hfsq + f) * ((float_t)ivln10lo + ivln10hi) + // y * ((float_t)log10_2lo + log10_2hi); hi = f - hfsq; GET_FLOAT_WORD(hx, hi); SET_FLOAT_WORD(hi, hx&0xfffff000); lo = (f - hi) - hfsq + r; return y*log10_2lo + (lo+hi)*ivln10lo + lo*ivln10hi + hi*ivln10hi + y*log10_2hi; }
float __ieee754_logf(float x) { float hfsq,f,s,z,R,w,t1,t2,dk; int32_t k,ix,i,j; GET_FLOAT_WORD(ix,x); k=0; if (ix < 0x00800000) { /* x < 2**-126 */ if ((ix&0x7fffffff)==0) return -two25/vzero; /* log(+-0)=-inf */ if (ix<0) return (x-x)/zero; /* log(-#) = NaN */ k -= 25; x *= two25; /* subnormal number, scale up x */ GET_FLOAT_WORD(ix,x); } if (ix >= 0x7f800000) return x+x; k += (ix>>23)-127; ix &= 0x007fffff; i = (ix+(0x95f64<<3))&0x800000; SET_FLOAT_WORD(x,ix|(i^0x3f800000)); /* normalize x or x/2 */ k += (i>>23); f = x-(float)1.0; if((0x007fffff&(0x8000+ix))<0xc000) { /* -2**-9 <= f < 2**-9 */ if(f==zero) { if(k==0) { return zero; } else { dk=(float)k; return dk*ln2_hi+dk*ln2_lo; } } R = f*f*((float)0.5-(float)0.33333333333333333*f); if(k==0) return f-R; else {dk=(float)k; return dk*ln2_hi-((R-dk*ln2_lo)-f);} } s = f/((float)2.0+f); dk = (float)k; z = s*s; i = ix-(0x6147a<<3); w = z*z; j = (0x6b851<<3)-ix; t1= w*(Lg2+w*Lg4); t2= z*(Lg1+w*Lg3); i |= j; R = t2+t1; if(i>0) { hfsq=(float)0.5*f*f; if(k==0) return f-(hfsq-s*(hfsq+R)); else return dk*ln2_hi-((hfsq-(s*(hfsq+R)+dk*ln2_lo))-f); } else { if(k==0) return f-s*(f-R); else return dk*ln2_hi-((s*(f-R)-dk*ln2_lo)-f); } }
float acosf(float x) { float z, p, q, r, w, s, c, df; s32_t hx, ix; GET_FLOAT_WORD(hx,x); ix = hx & 0x7fffffff; if (ix == 0x3f800000) { if (hx > 0) return 0.0; else return pi + (float) 2.0 * pio2_lo; } else if (ix > 0x3f800000) { return (x - x) / (x - x); } if (ix < 0x3f000000) { if (ix <= 0x23000000) return pio2_hi + pio2_lo; z = x * x; p = z * (pS0 + z * (pS1 + z * (pS2 + z * (pS3 + z * (pS4 + z * pS5))))); q = one + z * (qS1 + z * (qS2 + z * (qS3 + z * qS4))); r = p / q; return pio2_hi - (x - (pio2_lo - x * r)); } else if (hx < 0) { z = (one + x) * (float) 0.5; p = z * (pS0 + z * (pS1 + z * (pS2 + z * (pS3 + z * (pS4 + z * pS5))))); q = one + z * (qS1 + z * (qS2 + z * (qS3 + z * qS4))); s = sqrtf(z); r = p / q; w = r * s - pio2_lo; return pi - (float) 2.0 * (s + w); } else { s32_t idf; z = (one - x) * (float) 0.5; s = sqrtf(z); df = s; GET_FLOAT_WORD(idf,df); SET_FLOAT_WORD(df,idf&0xfffff000); c = (z - df * df) / (s + df); p = z * (pS0 + z * (pS1 + z * (pS2 + z * (pS3 + z * (pS4 + z * pS5))))); q = one + z * (qS1 + z * (qS2 + z * (qS3 + z * qS4))); r = p / q; w = r * s + c; return (float) 2.0 * (df + w); } }
float nextafterf(float x, float y) { int32_t hx, hy, ix, iy; GET_FLOAT_WORD(hx, x); GET_FLOAT_WORD(hy, y); ix = hx & 0x7fffffff; /* |x| */ iy = hy & 0x7fffffff; /* |y| */ /* x is nan or y is nan? */ if ((ix > 0x7f800000) || (iy > 0x7f800000)) return x + y; if (x == y) return y; if (ix == 0) { /* x == 0? */ SET_FLOAT_WORD(x, (hy & 0x80000000) | 1); return x; } if (hx >= 0) { /* x > 0 */ if (hx > hy) { /* x > y: x -= ulp */ hx -= 1; } else { /* x < y: x += ulp */ hx += 1; } } else { /* x < 0 */ if (hy >= 0 || hx > hy) { /* x < y: x -= ulp */ hx -= 1; } else { /* x > y: x += ulp */ hx += 1; } } hy = hx & 0x7f800000; if (hy >= 0x7f800000) { x = x + x; /* overflow */ return x; /* overflow */ } SET_FLOAT_WORD(x, hx); return x; }
float _nextf(float x, int p) { volatile float t; npy_int32 hx, hy, ix; GET_FLOAT_WORD(hx, x); ix = hx & 0x7fffffff; /* |x| */ if ((ix > 0x7f800000)) /* x is nan */ return x; if (ix == 0) { /* x == 0 */ if (p >= 0) { SET_FLOAT_WORD(x, 0x0 | 1); /* return +minsubnormal */ } else { SET_FLOAT_WORD(x, 0x80000000 | 1); /* return -minsubnormal */ } t = x * x; if (t == x) return t; else return x; /* raise underflow flag */ } if (p < 0) { /* x -= ulp */ hx -= 1; } else { /* x += ulp */ hx += 1; } hy = hx & 0x7f800000; if (hy >= 0x7f800000) return x + x; /* overflow */ if (hy < 0x00800000) { /* underflow */ t = x * x; if (t != x) { /* raise underflow flag */ SET_FLOAT_WORD(x, hx); return x; } } SET_FLOAT_WORD(x, hx); return x; }
float nexttowardf(float x, long double y) { union IEEEl2bits uy; volatile float t; int32_t hx,ix; GET_FLOAT_WORD(hx,x); ix = hx&0x7fffffff; /* |x| */ uy.e = y; if((ix>0x7f800000) || (uy.bits.exp == LDBL_INFNAN_EXP && ((uy.bits.manh&~LDBL_NBIT)|uy.bits.manl) != 0)) return x+y; /* x or y is nan */ if(x==y) return (float)y; /* x=y, return y */ if(ix==0) { /* x == 0 */ SET_FLOAT_WORD(x,(uy.bits.sign<<31)|1);/* return +-minsubnormal */ t = x*x; if(t==x) return t; else return x; /* raise underflow flag */ } if(hx>=0 ^ x < y) /* x -= ulp */ hx -= 1; else /* x += ulp */ hx += 1; ix = hx&0x7f800000; if(ix>=0x7f800000) return x+x; /* overflow */ if(ix<0x00800000) { /* underflow */ t = x*x; if(t!=x) { /* raise underflow flag */ SET_FLOAT_WORD(x,hx); return x; } } SET_FLOAT_WORD(x,hx); return x; }
float acosf(float x) { float z,p,q,r,w,s,c,df; int32_t hx,ix; GET_FLOAT_WORD(hx, x); ix = hx & 0x7fffffff; if (ix >= 0x3f800000) { /* |x| >= 1 */ if (ix == 0x3f800000) { /* |x| == 1 */ if (hx > 0) return 0.0f; /* acos(1) = 0 */ return pi + 2.0f*pio2_lo; /* acos(-1)= pi */ } return (x-x)/(x-x); /* acos(|x|>1) is NaN */ } if (ix < 0x3f000000) { /* |x| < 0.5 */ if (ix <= 0x32800000) /* |x| < 2**-26 */ return pio2_hi + pio2_lo; z = x*x; p = z*(pS0+z*(pS1+z*pS2)); q = 1.0f+z*qS1; r = p/q; return pio2_hi - (x - (pio2_lo-x*r)); } else if (hx < 0) { /* x < -0.5 */ z = (1.0f+x)*0.5f; p = z*(pS0+z*(pS1+z*pS2)); q = 1.0f+z*qS1; s = sqrtf(z); r = p/q; w = r*s-pio2_lo; return pi - 2.0f*(s+w); } else { /* x > 0.5 */ int32_t idf; z = (1.0f-x)*0.5f; s = sqrtf(z); df = s; GET_FLOAT_WORD(idf,df); SET_FLOAT_WORD(df,idf&0xfffff000); c = (z-df*df)/(s+df); p = z*(pS0+z*(pS1+z*pS2)); q = 1.0f+z*qS1; r = p/q; w = r*s+c; return 2.0f*(df+w); } }
float __ieee754_asinf(float x) { float t,w,p,q,c,r,s; int32_t hx,ix; t = 0; GET_FLOAT_WORD(hx,x); ix = hx&0x7fffffff; if(ix==0x3f800000) { /* asin(1)=+-pi/2 with inexact */ return x*pio2_hi+x*pio2_lo; } else if(ix> 0x3f800000) { /* |x|>= 1 */ return (x-x)/(x-x); /* asin(|x|>1) is NaN */ } else if (ix<0x3f000000) { /* |x|<0.5 */ if(ix<0x32000000) { /* if |x| < 2**-27 */ if(huge+x>one) return x;/* return x with inexact if x!=0*/ } else t = x*x; p = t*(pS0+t*(pS1+t*(pS2+t*(pS3+t*(pS4+t*pS5))))); q = one+t*(qS1+t*(qS2+t*(qS3+t*qS4))); w = p/q; return x+x*w; } /* 1> |x|>= 0.5 */ w = one-fabsf(x); t = w*(float)0.5; p = t*(pS0+t*(pS1+t*(pS2+t*(pS3+t*(pS4+t*pS5))))); q = one+t*(qS1+t*(qS2+t*(qS3+t*qS4))); s = __ieee754_sqrtf(t); if(ix>=0x3F79999A) { /* if |x| > 0.975 */ w = p/q; t = pio2_hi-((float)2.0*(s+s*w)-pio2_lo); } else { int32_t iw; w = s; GET_FLOAT_WORD(iw,w); SET_FLOAT_WORD(w,iw&0xfffff000); c = (t-w*w)/(s+w); r = p/q; p = (float)2.0*s*r-(pio2_lo-(float)2.0*c); q = pio4_hi-(float)2.0*w; t = pio4_hi-(p-q); } if(hx>0) return t; else return -t; }
float log2f(float x) { float hfsq,f,s,z,R,w,t1,t2,dk; int32_t k,ix,i,j; GET_FLOAT_WORD(ix,x); k=0; if (ix < 0x00800000) { /* x < 2**-126 */ if ((ix&0x7fffffff)==0) return -two25/zero; /* log(+-0)=-inf */ if (ix<0) return (x-x)/zero; /* log(-#) = NaN */ k -= 25; x *= two25; /* subnormal number, scale up x */ GET_FLOAT_WORD(ix,x); } if (ix >= 0x7f800000) return x+x; k += (ix>>23)-127; ix &= 0x007fffff; i = (ix+(0x95f64<<3))&0x800000; SET_FLOAT_WORD(x,ix|(i^0x3f800000)); /* normalize x or x/2 */ k += (i>>23); dk = (float)k; f = x-(float)1.0; if((0x007fffff&(15+ix))<16) { /* |f| < 2**-20 */ if (f==zero) return (dk); R = f*f*((float)0.5-(float)0.33333333333333333*f); return (dk-(R-f)/ln2); } s = f/((float)2.0+f); z = s*s; i = ix-(0x6147a<<3); w = z*z; j = (0x6b851<<3)-ix; t1= w*(Lg2+w*(Lg4+w*Lg6)); t2= z*(Lg1+w*(Lg3+w*(Lg5+w*Lg7))); i |= j; R = t2+t1; if(i>0) { hfsq=(float)0.5*f*f; return (dk-(hfsq-s*(hfsq+R)-f)/ln2); } else return (dk-((s*(f-R))-f)/ln2); }
float __frexpf(float x, int *eptr) { int32_t hx,ix; GET_FLOAT_WORD(hx,x); ix = 0x7fffffff&hx; *eptr = 0; if(ix>=0x7f800000||(ix==0)) return x + x; /* 0,inf,nan */ if (ix<0x00800000) { /* subnormal */ x *= two25; GET_FLOAT_WORD(hx,x); ix = hx&0x7fffffff; *eptr = -25; } *eptr += (ix>>23)-126; hx = (hx&0x807fffff)|0x3f000000; SET_FLOAT_WORD(x,hx); return x; }