Path: blob/master/waterbox/libc/functions/math/__rem_pio2.c
2 views
/* origin: FreeBSD /usr/src/lib/msun/src/e_rem_pio2.c */1/*2* ====================================================3* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.4*5* Developed at SunSoft, a Sun Microsystems, Inc. business.6* Permission to use, copy, modify, and distribute this7* software is freely granted, provided that this notice8* is preserved.9* ====================================================10*11* Optimized by Bruce D. Evans.12*/13/* __rem_pio2(x,y)14*15* return the remainder of x rem pi/2 in y[0]+y[1]16* use __rem_pio2_large() for large x17*/1819#include "libm.h"2021#if FLT_EVAL_METHOD==0 || FLT_EVAL_METHOD==122#define EPS DBL_EPSILON23#elif FLT_EVAL_METHOD==224#define EPS LDBL_EPSILON25#endif2627/*28* invpio2: 53 bits of 2/pi29* pio2_1: first 33 bit of pi/230* pio2_1t: pi/2 - pio2_131* pio2_2: second 33 bit of pi/232* pio2_2t: pi/2 - (pio2_1+pio2_2)33* pio2_3: third 33 bit of pi/234* pio2_3t: pi/2 - (pio2_1+pio2_2+pio2_3)35*/36static const double37toint = 1.5/EPS,38invpio2 = 6.36619772367581382433e-01, /* 0x3FE45F30, 0x6DC9C883 */39pio2_1 = 1.57079632673412561417e+00, /* 0x3FF921FB, 0x54400000 */40pio2_1t = 6.07710050650619224932e-11, /* 0x3DD0B461, 0x1A626331 */41pio2_2 = 6.07710050630396597660e-11, /* 0x3DD0B461, 0x1A600000 */42pio2_2t = 2.02226624879595063154e-21, /* 0x3BA3198A, 0x2E037073 */43pio2_3 = 2.02226624871116645580e-21, /* 0x3BA3198A, 0x2E000000 */44pio2_3t = 8.47842766036889956997e-32; /* 0x397B839A, 0x252049C1 */4546/* caller must handle the case when reduction is not needed: |x| ~<= pi/4 */47int __rem_pio2(double x, double *y)48{49union {double f; uint64_t i;} u = {x};50double_t z,w,t,r,fn;51double tx[3],ty[2];52uint32_t ix;53int sign, n, ex, ey, i;5455sign = u.i>>63;56ix = u.i>>32 & 0x7fffffff;57if (ix <= 0x400f6a7a) { /* |x| ~<= 5pi/4 */58if ((ix & 0xfffff) == 0x921fb) /* |x| ~= pi/2 or 2pi/2 */59goto medium; /* cancellation -- use medium case */60if (ix <= 0x4002d97c) { /* |x| ~<= 3pi/4 */61if (!sign) {62z = x - pio2_1; /* one round good to 85 bits */63y[0] = z - pio2_1t;64y[1] = (z-y[0]) - pio2_1t;65return 1;66} else {67z = x + pio2_1;68y[0] = z + pio2_1t;69y[1] = (z-y[0]) + pio2_1t;70return -1;71}72} else {73if (!sign) {74z = x - 2*pio2_1;75y[0] = z - 2*pio2_1t;76y[1] = (z-y[0]) - 2*pio2_1t;77return 2;78} else {79z = x + 2*pio2_1;80y[0] = z + 2*pio2_1t;81y[1] = (z-y[0]) + 2*pio2_1t;82return -2;83}84}85}86if (ix <= 0x401c463b) { /* |x| ~<= 9pi/4 */87if (ix <= 0x4015fdbc) { /* |x| ~<= 7pi/4 */88if (ix == 0x4012d97c) /* |x| ~= 3pi/2 */89goto medium;90if (!sign) {91z = x - 3*pio2_1;92y[0] = z - 3*pio2_1t;93y[1] = (z-y[0]) - 3*pio2_1t;94return 3;95} else {96z = x + 3*pio2_1;97y[0] = z + 3*pio2_1t;98y[1] = (z-y[0]) + 3*pio2_1t;99return -3;100}101} else {102if (ix == 0x401921fb) /* |x| ~= 4pi/2 */103goto medium;104if (!sign) {105z = x - 4*pio2_1;106y[0] = z - 4*pio2_1t;107y[1] = (z-y[0]) - 4*pio2_1t;108return 4;109} else {110z = x + 4*pio2_1;111y[0] = z + 4*pio2_1t;112y[1] = (z-y[0]) + 4*pio2_1t;113return -4;114}115}116}117if (ix < 0x413921fb) { /* |x| ~< 2^20*(pi/2), medium size */118medium:119/* rint(x/(pi/2)), Assume round-to-nearest. */120fn = (double_t)x*invpio2 + toint - toint;121n = (int32_t)fn;122r = x - fn*pio2_1;123w = fn*pio2_1t; /* 1st round, good to 85 bits */124y[0] = r - w;125u.f = y[0];126ey = u.i>>52 & 0x7ff;127ex = ix>>20;128if (ex - ey > 16) { /* 2nd round, good to 118 bits */129t = r;130w = fn*pio2_2;131r = t - w;132w = fn*pio2_2t - ((t-r)-w);133y[0] = r - w;134u.f = y[0];135ey = u.i>>52 & 0x7ff;136if (ex - ey > 49) { /* 3rd round, good to 151 bits, covers all cases */137t = r;138w = fn*pio2_3;139r = t - w;140w = fn*pio2_3t - ((t-r)-w);141y[0] = r - w;142}143}144y[1] = (r - y[0]) - w;145return n;146}147/*148* all other (large) arguments149*/150if (ix >= 0x7ff00000) { /* x is inf or NaN */151y[0] = y[1] = x - x;152return 0;153}154/* set z = scalbn(|x|,-ilogb(x)+23) */155u.f = x;156u.i &= (uint64_t)-1>>12;157u.i |= (uint64_t)(0x3ff + 23)<<52;158z = u.f;159for (i=0; i < 2; i++) {160tx[i] = (double)(int32_t)z;161z = (z-tx[i])*0x1p24;162}163tx[i] = z;164/* skip zero terms, first term is non-zero */165while (tx[i] == 0.0)166i--;167n = __rem_pio2_large(tx,ty,(int)(ix>>20)-(0x3ff+23),i+1,1);168if (sign) {169y[0] = -ty[0];170y[1] = -ty[1];171return -n;172}173y[0] = ty[0];174y[1] = ty[1];175return n;176}177178179