double sqrt(double x) { int exponent; double val; if (__IsNan(x)) { errno = EDOM; return x; } if (x <= 0) { if (x < 0) errno = EDOM; return 0; } if (x > DBL_MAX) return x; /* for infinity */ val = frexp(x, &exponent); if (exponent & 1) { exponent--; val *= 2; } val = ldexp(val + 1.0, exponent/2 - 1); /* was: val = (val + 1.0)/2.0; val = ldexp(val, exponent/2); */ for (exponent = NITER - 1; exponent >= 0; exponent--) { val = (val + x / val) / 2.0; } return val; }
double atan(double x) { /* Algorithm and coefficients from: "Software manual for the elementary functions" by W.J. Cody and W. Waite, Prentice-Hall, 1980 */ static double p[] = { -0.13688768894191926929e+2, -0.20505855195861651981e+2, -0.84946240351320683534e+1, -0.83758299368150059274e+0 }; static double q[] = { 0.41066306682575781263e+2, 0.86157349597130242515e+2, 0.59578436142597344465e+2, 0.15024001160028576121e+2, 1.0 }; static double a[] = { 0.0, 0.52359877559829887307710723554658381, /* pi/6 */ M_PI_2, 1.04719755119659774615421446109316763 /* pi/3 */ }; int neg = x < 0; int n; double g; if (__IsNan(x)) { errno = EDOM; return x; } if (neg) { x = -x; } if (x > 1.0) { x = 1.0/x; n = 2; } else n = 0; if (x > 0.26794919243112270647) { /* 2-sqtr(3) */ n = n + 1; x = (((0.73205080756887729353*x-0.5)-0.5)+x)/ (1.73205080756887729353+x); } /* ??? avoid underflow ??? */ g = x * x; x += x * g * POLYNOM3(g, p) / POLYNOM4(g, q); if (n > 1) x = -x; x += a[n]; return neg ? -x : x; }
double exp(double x) { /* Algorithm and coefficients from: "Software manual for the elementary functions" by W.J. Cody and W. Waite, Prentice-Hall, 1980 */ static double p[] = { 0.25000000000000000000e+0, 0.75753180159422776666e-2, 0.31555192765684646356e-4 }; static double q[] = { 0.50000000000000000000e+0, 0.56817302698551221787e-1, 0.63121894374398503557e-3, 0.75104028399870046114e-6 }; double xn, g; int n; int negative = x < 0; if (__IsNan(x)) { errno = EDOM; return x; } if (x < M_LN_MIN_D) { errno = ERANGE; return 0.0; } if (x > M_LN_MAX_D) { errno = ERANGE; return HUGE_VAL; } if (negative) x = -x; /* ??? avoid underflow ??? */ n = x * M_LOG2E + 0.5; /* 1/ln(2) = log2(e), 0.5 added for rounding */ xn = n; { double x1 = (long) x; double x2 = x - x1; g = ((x1-xn*0.693359375)+x2) - xn*(-2.1219444005469058277e-4); } if (negative) { g = -g; n = -n; } xn = g * g; x = g * POLYNOM2(xn, p); n += 1; return (ldexp(0.5 + x/(POLYNOM3(xn, q) - x), n)); }
static double asin_acos(double x, int cosfl) { int negative = x < 0; int i; double g; static double p[] = { -0.27368494524164255994e+2, 0.57208227877891731407e+2, -0.39688862997540877339e+2, 0.10152522233806463645e+2, -0.69674573447350646411e+0 }; static double q[] = { -0.16421096714498560795e+3, 0.41714430248260412556e+3, -0.38186303361750149284e+3, 0.15095270841030604719e+3, -0.23823859153670238830e+2, 1.0 }; if (__IsNan(x)) { errno = EDOM; return x; } if (negative) { x = -x; } if (x > 0.5) { i = 1; if (x > 1) { errno = EDOM; return 0; } g = 0.5 - 0.5 * x; x = - sqrt(g); x += x; } else { /* ??? avoid underflow ??? */ i = 0; g = x * x; } x += x * g * POLYNOM4(g, p) / POLYNOM5(g, q); if (cosfl) { if (! negative) x = -x; } if ((cosfl == 0) == (i == 1)) { x = (x + M_PI_4) + M_PI_4; } else if (cosfl && negative && i == 1) { x = (x + M_PI_2) + M_PI_2; } if (! cosfl && negative) x = -x; return x; }
static double sinh_cosh(double x, int cosh_flag) { /* Algorithm and coefficients from: "Software manual for the elementary functions" by W.J. Cody and W. Waite, Prentice-Hall, 1980 */ static double p[] = { -0.35181283430177117881e+6, -0.11563521196851768270e+5, -0.16375798202630751372e+3, -0.78966127417357099479e+0 }; static double q[] = { -0.21108770058106271242e+7, 0.36162723109421836460e+5, -0.27773523119650701167e+3, 1.0 }; int negative = x < 0; double y = negative ? -x : x; if (__IsNan(x)) { errno = EDOM; return x; } if (! cosh_flag && y <= 1.0) { /* ??? check for underflow ??? */ y = y * y; return x + x * y * POLYNOM3(y, p)/POLYNOM3(y,q); } if (y >= M_LN_MAX_D) { /* exp(y) would cause overflow */ #define LNV 0.69316101074218750000e+0 #define VD2M1 0.52820835025874852469e-4 double w = y - LNV; if (w < M_LN_MAX_D+M_LN2-LNV) { x = exp(w); x += VD2M1 * x; } else { errno = ERANGE; x = HUGE_VAL; } } else { double z = exp(y); x = 0.5 * (z + (cosh_flag ? 1.0 : -1.0)/z); } return negative ? -x : x; }
double log(double x) { /* Algorithm and coefficients from: "Software manual for the elementary functions" by W.J. Cody and W. Waite, Prentice-Hall, 1980 */ static double a[] = { -0.64124943423745581147e2, 0.16383943563021534222e2, -0.78956112887491257267e0 }; static double b[] = { -0.76949932108494879777e3, 0.31203222091924532844e3, -0.35667977739034646171e2, 1.0 }; double znum, zden, z, w; int exponent; if (__IsNan(x)) { errno = EDOM; return x; } if (x < 0) { errno = EDOM; return -HUGE_VAL; } else if (x == 0) { errno = ERANGE; return -HUGE_VAL; } if (x <= DBL_MAX) { } else return x; /* for infinity and Nan */ x = frexp(x, &exponent); if (x > M_1_SQRT2) { znum = (x - 0.5) - 0.5; zden = x * 0.5 + 0.5; } else { znum = x - 0.5; zden = znum * 0.5 + 0.5; exponent--; } z = znum/zden; w = z * z; x = z + z * w * (POLYNOM2(w,a)/POLYNOM3(w,b)); z = exponent; x += z * (-2.121944400546905827679e-4); return x + z * 0.693359375; }
double ldexp(double fl, int exp) { int sign = 1; int currexp; if (__IsNan(fl)) { errno = EDOM; return fl; } if (fl == 0.0) return 0.0; if (fl<0) { fl = -fl; sign = -1; } if (fl > DBL_MAX) { /* for infinity */ errno = ERANGE; return sign * fl; } fl = frexp(fl,&currexp); exp += currexp; if (exp > 0) { if (exp > DBL_MAX_EXP) { errno = ERANGE; return sign * HUGE_VAL; } while (exp>30) { fl *= (double) (1L << 30); exp -= 30; } fl *= (double) (1L << exp); } else { /* number need not be normalized */ if (exp < DBL_MIN_EXP - DBL_MANT_DIG) { return 0.0; } while (exp<-30) { fl /= (double) (1L << 30); exp += 30; } fl /= (double) (1L << -exp); } return sign * fl; }
double tanh(double x) { /* Algorithm and coefficients from: "Software manual for the elementary functions" by W.J. Cody and W. Waite, Prentice-Hall, 1980 */ static double p[] = { -0.16134119023996228053e+4, -0.99225929672236083313e+2, -0.96437492777225469787e+0 }; static double q[] = { 0.48402357071988688686e+4, 0.22337720718962312926e+4, 0.11274474380534949335e+3, 1.0 }; int negative = x < 0; if (__IsNan(x)) { errno = EDOM; return x; } if (negative) x = -x; if (x >= 0.5*M_LN_MAX_D) { x = 1.0; } #define LN3D2 0.54930614433405484570e+0 /* ln(3)/2 */ else if (x > LN3D2) { x = 0.5 - 1.0/(exp(x+x)+1.0); x += x; } else { /* ??? avoid underflow ??? */ double g = x*x; x += x * g * POLYNOM2(g, p)/POLYNOM3(g, q); } return negative ? -x : x; }
static double sinus(double x, int cos_flag) { /* Algorithm and coefficients from: "Software manual for the elementary functions" by W.J. Cody and W. Waite, Prentice-Hall, 1980 */ static double r[] = { -0.16666666666666665052e+0, 0.83333333333331650314e-2, -0.19841269841201840457e-3, 0.27557319210152756119e-5, -0.25052106798274584544e-7, 0.16058936490371589114e-9, -0.76429178068910467734e-12, 0.27204790957888846175e-14 }; double y; int neg = 1; if (__IsNan(x)) { errno = EDOM; return x; } if (x < 0) { x = -x; neg = -1; } if (cos_flag) { neg = 1; y = M_PI_2 + x; } else y = x; /* ??? avoid loss of significance, if y is too large, error ??? */ y = y * M_1_PI + 0.5; if (y >= DBL_MAX/M_PI) return 0.0; /* Use extended precision to calculate reduced argument. Here we used 12 bits of the mantissa for a1. Also split x in integer part x1 and fraction part x2. */ #define A1 3.1416015625 #define A2 -8.908910206761537356617e-6 { double x1, x2; modf(y, &y); if (modf(0.5*y, &x1)) neg = -neg; if (cos_flag) y -= 0.5; x2 = modf(x, &x1); x = x1 - y * A1; x += x2; x -= y * A2; #undef A1 #undef A2 } if (x < 0) { neg = -neg; x = -x; } /* ??? avoid underflow ??? */ y = x * x; x += x * y * POLYNOM7(y, r); return neg==-1 ? -x : x; }
double tan(double x) { /* Algorithm and coefficients from: "Software manual for the elementary functions" by W.J. Cody and W. Waite, Prentice-Hall, 1980 */ int negative = x < 0; int invert = 0; double y; static double p[] = { 1.0, -0.13338350006421960681e+0, 0.34248878235890589960e-2, -0.17861707342254426711e-4 }; static double q[] = { 1.0, -0.46671683339755294240e+0, 0.25663832289440112864e-1, -0.31181531907010027307e-3, 0.49819433993786512270e-6 }; if (__IsNan(x)) { errno = EDOM; return x; } if (negative) x = -x; /* ??? avoid loss of significance, error if x is too large ??? */ y = x * M_2_PI + 0.5; if (y >= DBL_MAX/M_PI_2) return 0.0; /* Use extended precision to calculate reduced argument. Here we used 12 bits of the mantissa for a1. Also split x in integer part x1 and fraction part x2. */ #define A1 1.57080078125 #define A2 -4.454455103380768678308e-6 { double x1, x2; modf(y, &y); if (modf(0.5*y, &x1)) invert = 1; x2 = modf(x, &x1); x = x1 - y * A1; x += x2; x -= y * A2; #undef A1 #undef A2 } /* ??? avoid underflow ??? */ y = x * x; x += x * y * POLYNOM2(y, p+1); y = POLYNOM4(y, q); if (negative) x = -x; return invert ? -y/x : x/y; }