Mercurial > sdl-ios-xcode
changeset 2756:a98604b691c8
Expanded the libm support and put it into a separate directory.
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Mon, 15 Sep 2008 06:33:23 +0000 |
parents | 2a3ec308d995 |
children | 0581f49c9294 |
files | src/libm/e_log.c src/libm/e_pow.c src/libm/e_rem_pio2.c src/libm/e_sqrt.c src/libm/k_cos.c src/libm/k_sin.c src/libm/math.h src/libm/math_private.h src/libm/s_copysign.c src/libm/s_cos.c src/libm/s_fabs.c src/libm/s_scalbn.c src/libm/s_sin.c src/video/SDL_gamma.c src/video/e_log.h src/video/e_pow.h src/video/e_sqrt.h src/video/math_private.h |
diffstat | 18 files changed, 1945 insertions(+), 1199 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/libm/e_log.c Mon Sep 15 06:33:23 2008 +0000 @@ -0,0 +1,166 @@ +/* @(#)e_log.c 5.1 93/09/24 */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: e_log.c,v 1.8 1995/05/10 20:45:49 jtc Exp $"; +#endif + +/* __ieee754_log(x) + * Return the logrithm of x + * + * Method : + * 1. Argument Reduction: find k and f such that + * x = 2^k * (1+f), + * where sqrt(2)/2 < 1+f < sqrt(2) . + * + * 2. Approximation of log(1+f). + * Let s = f/(2+f) ; based on log(1+f) = log(1+s) - log(1-s) + * = 2s + 2/3 s**3 + 2/5 s**5 + ....., + * = 2s + s*R + * We use a special Reme algorithm on [0,0.1716] to generate + * a polynomial of degree 14 to approximate R The maximum error + * of this polynomial approximation is bounded by 2**-58.45. In + * other words, + * 2 4 6 8 10 12 14 + * R(z) ~ Lg1*s +Lg2*s +Lg3*s +Lg4*s +Lg5*s +Lg6*s +Lg7*s + * (the values of Lg1 to Lg7 are listed in the program) + * and + * | 2 14 | -58.45 + * | Lg1*s +...+Lg7*s - R(z) | <= 2 + * | | + * Note that 2s = f - s*f = f - hfsq + s*hfsq, where hfsq = f*f/2. + * In order to guarantee error in log below 1ulp, we compute log + * by + * log(1+f) = f - s*(f - R) (if f is not too large) + * log(1+f) = f - (hfsq - s*(hfsq+R)). (better accuracy) + * + * 3. Finally, log(x) = k*ln2 + log(1+f). + * = k*ln2_hi+(f-(hfsq-(s*(hfsq+R)+k*ln2_lo))) + * Here ln2 is split into two floating point number: + * ln2_hi + ln2_lo, + * where n*ln2_hi is always exact for |n| < 2000. + * + * Special cases: + * log(x) is NaN with signal if x < 0 (including -INF) ; + * log(+INF) is +INF; log(0) is -INF with signal; + * log(NaN) is that NaN with no signal. + * + * Accuracy: + * according to an error analysis, the error is always less than + * 1 ulp (unit in the last place). + * + * Constants: + * The hexadecimal values are the intended ones for the following + * constants. The decimal values may be used, provided that the + * compiler will convert from decimal to binary accurately enough + * to produce the hexadecimal values shown. + */ + +#include "math.h" +#include "math_private.h" + +#ifdef __STDC__ +static const double +#else +static double +#endif + ln2_hi = 6.93147180369123816490e-01, /* 3fe62e42 fee00000 */ + ln2_lo = 1.90821492927058770002e-10, /* 3dea39ef 35793c76 */ + two54 = 1.80143985094819840000e+16, /* 43500000 00000000 */ + Lg1 = 6.666666666666735130e-01, /* 3FE55555 55555593 */ + Lg2 = 3.999999999940941908e-01, /* 3FD99999 9997FA04 */ + Lg3 = 2.857142874366239149e-01, /* 3FD24924 94229359 */ + Lg4 = 2.222219843214978396e-01, /* 3FCC71C5 1D8E78AF */ + Lg5 = 1.818357216161805012e-01, /* 3FC74664 96CB03DE */ + Lg6 = 1.531383769920937332e-01, /* 3FC39A09 D078C69F */ + Lg7 = 1.479819860511658591e-01; /* 3FC2F112 DF3E5244 */ + +#ifdef __STDC__ +static const double zero = 0.0; +#else +static double zero = 0.0; +#endif + +#ifdef __STDC__ +double attribute_hidden +__ieee754_log(double x) +#else +double attribute_hidden +__ieee754_log(x) + double x; +#endif +{ + double hfsq, f, s, z, R, w, t1, t2, dk; + int32_t k, hx, i, j; + u_int32_t lx; + + EXTRACT_WORDS(hx, lx, x); + + k = 0; + if (hx < 0x00100000) { /* x < 2**-1022 */ + if (((hx & 0x7fffffff) | lx) == 0) + return -two54 / zero; /* log(+-0)=-inf */ + if (hx < 0) + return (x - x) / zero; /* log(-#) = NaN */ + k -= 54; + x *= two54; /* subnormal number, scale up x */ + GET_HIGH_WORD(hx, x); + } + if (hx >= 0x7ff00000) + return x + x; + k += (hx >> 20) - 1023; + hx &= 0x000fffff; + i = (hx + 0x95f64) & 0x100000; + SET_HIGH_WORD(x, hx | (i ^ 0x3ff00000)); /* normalize x or x/2 */ + k += (i >> 20); + f = x - 1.0; + if ((0x000fffff & (2 + hx)) < 3) { /* |f| < 2**-20 */ + if (f == zero) { + if (k == 0) + return zero; + else { + dk = (double) k; + return dk * ln2_hi + dk * ln2_lo; + } + } + R = f * f * (0.5 - 0.33333333333333333 * f); + if (k == 0) + return f - R; + else { + dk = (double) k; + return dk * ln2_hi - ((R - dk * ln2_lo) - f); + } + } + s = f / (2.0 + f); + dk = (double) k; + z = s * s; + i = hx - 0x6147a; + w = z * z; + j = 0x6b851 - hx; + 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 = 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); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/libm/e_pow.c Mon Sep 15 06:33:23 2008 +0000 @@ -0,0 +1,342 @@ +/* @(#)e_pow.c 5.1 93/09/24 */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: e_pow.c,v 1.9 1995/05/12 04:57:32 jtc Exp $"; +#endif + +/* __ieee754_pow(x,y) return x**y + * + * n + * Method: Let x = 2 * (1+f) + * 1. Compute and return log2(x) in two pieces: + * log2(x) = w1 + w2, + * where w1 has 53-24 = 29 bit trailing zeros. + * 2. Perform y*log2(x) = n+y' by simulating muti-precision + * arithmetic, where |y'|<=0.5. + * 3. Return x**y = 2**n*exp(y'*log2) + * + * Special cases: + * 1. (anything) ** 0 is 1 + * 2. (anything) ** 1 is itself + * 3. (anything) ** NAN is NAN + * 4. NAN ** (anything except 0) is NAN + * 5. +-(|x| > 1) ** +INF is +INF + * 6. +-(|x| > 1) ** -INF is +0 + * 7. +-(|x| < 1) ** +INF is +0 + * 8. +-(|x| < 1) ** -INF is +INF + * 9. +-1 ** +-INF is NAN + * 10. +0 ** (+anything except 0, NAN) is +0 + * 11. -0 ** (+anything except 0, NAN, odd integer) is +0 + * 12. +0 ** (-anything except 0, NAN) is +INF + * 13. -0 ** (-anything except 0, NAN, odd integer) is +INF + * 14. -0 ** (odd integer) = -( +0 ** (odd integer) ) + * 15. +INF ** (+anything except 0,NAN) is +INF + * 16. +INF ** (-anything except 0,NAN) is +0 + * 17. -INF ** (anything) = -0 ** (-anything) + * 18. (-anything) ** (integer) is (-1)**(integer)*(+anything**integer) + * 19. (-anything except 0 and inf) ** (non-integer) is NAN + * + * Accuracy: + * pow(x,y) returns x**y nearly rounded. In particular + * pow(integer,integer) + * always returns the correct integer provided it is + * representable. + * + * Constants : + * The hexadecimal values are the intended ones for the following + * constants. The decimal values may be used, provided that the + * compiler will convert from decimal to binary accurately enough + * to produce the hexadecimal values shown. + */ + +#include "math.h" +#include "math_private.h" + +libm_hidden_proto(scalbn) + libm_hidden_proto(fabs) +#ifdef __STDC__ + static const double +#else + static double +#endif + bp[] = { 1.0, 1.5, }, dp_h[] = { + 0.0, 5.84962487220764160156e-01,}, /* 0x3FE2B803, 0x40000000 */ + + dp_l[] = { + 0.0, 1.35003920212974897128e-08,}, /* 0x3E4CFDEB, 0x43CFD006 */ + + zero = 0.0, one = 1.0, two = 2.0, two53 = 9007199254740992.0, /* 0x43400000, 0x00000000 */ + huge = 1.0e300, tiny = 1.0e-300, + /* poly coefs for (3/2)*(log(x)-2s-2/3*s**3 */ + L1 = 5.99999999999994648725e-01, /* 0x3FE33333, 0x33333303 */ + L2 = 4.28571428578550184252e-01, /* 0x3FDB6DB6, 0xDB6FABFF */ + L3 = 3.33333329818377432918e-01, /* 0x3FD55555, 0x518F264D */ + L4 = 2.72728123808534006489e-01, /* 0x3FD17460, 0xA91D4101 */ + L5 = 2.30660745775561754067e-01, /* 0x3FCD864A, 0x93C9DB65 */ + L6 = 2.06975017800338417784e-01, /* 0x3FCA7E28, 0x4A454EEF */ + P1 = 1.66666666666666019037e-01, /* 0x3FC55555, 0x5555553E */ + P2 = -2.77777777770155933842e-03, /* 0xBF66C16C, 0x16BEBD93 */ + P3 = 6.61375632143793436117e-05, /* 0x3F11566A, 0xAF25DE2C */ + P4 = -1.65339022054652515390e-06, /* 0xBEBBBD41, 0xC5D26BF1 */ + P5 = 4.13813679705723846039e-08, /* 0x3E663769, 0x72BEA4D0 */ + lg2 = 6.93147180559945286227e-01, /* 0x3FE62E42, 0xFEFA39EF */ + lg2_h = 6.93147182464599609375e-01, /* 0x3FE62E43, 0x00000000 */ + lg2_l = -1.90465429995776804525e-09, /* 0xBE205C61, 0x0CA86C39 */ + ovt = 8.0085662595372944372e-0017, /* -(1024-log2(ovfl+.5ulp)) */ + cp = 9.61796693925975554329e-01, /* 0x3FEEC709, 0xDC3A03FD =2/(3ln2) */ + cp_h = 9.61796700954437255859e-01, /* 0x3FEEC709, 0xE0000000 =(float)cp */ + cp_l = -7.02846165095275826516e-09, /* 0xBE3E2FE0, 0x145B01F5 =tail of cp_h */ + ivln2 = 1.44269504088896338700e+00, /* 0x3FF71547, 0x652B82FE =1/ln2 */ + ivln2_h = 1.44269502162933349609e+00, /* 0x3FF71547, 0x60000000 =24b 1/ln2 */ + ivln2_l = 1.92596299112661746887e-08; /* 0x3E54AE0B, 0xF85DDF44 =1/ln2 tail */ + +#ifdef __STDC__ + double attribute_hidden __ieee754_pow(double x, double y) +#else + double attribute_hidden __ieee754_pow(x, y) + double x, y; +#endif + { + double z, ax, z_h, z_l, p_h, p_l; + double y1, t1, t2, r, s, t, u, v, w; + int32_t i, j, k, yisint, n; + int32_t hx, hy, ix, iy; + u_int32_t lx, ly; + + EXTRACT_WORDS(hx, lx, x); + EXTRACT_WORDS(hy, ly, y); + ix = hx & 0x7fffffff; + iy = hy & 0x7fffffff; + + /* y==zero: x**0 = 1 */ + if ((iy | ly) == 0) + return one; + + /* +-NaN return x+y */ + if (ix > 0x7ff00000 || ((ix == 0x7ff00000) && (lx != 0)) || + iy > 0x7ff00000 || ((iy == 0x7ff00000) && (ly != 0))) + return x + y; + + /* determine if y is an odd int when x < 0 + * yisint = 0 ... y is not an integer + * yisint = 1 ... y is an odd int + * yisint = 2 ... y is an even int + */ + yisint = 0; + if (hx < 0) { + if (iy >= 0x43400000) + yisint = 2; /* even integer y */ + else if (iy >= 0x3ff00000) { + k = (iy >> 20) - 0x3ff; /* exponent */ + if (k > 20) { + j = ly >> (52 - k); + if ((j << (52 - k)) == ly) + yisint = 2 - (j & 1); + } else if (ly == 0) { + j = iy >> (20 - k); + if ((j << (20 - k)) == iy) + yisint = 2 - (j & 1); + } + } + } + + /* special value of y */ + if (ly == 0) { + if (iy == 0x7ff00000) { /* y is +-inf */ + if (((ix - 0x3ff00000) | lx) == 0) + return y - y; /* inf**+-1 is NaN */ + else if (ix >= 0x3ff00000) /* (|x|>1)**+-inf = inf,0 */ + return (hy >= 0) ? y : zero; + else /* (|x|<1)**-,+inf = inf,0 */ + return (hy < 0) ? -y : zero; + } + if (iy == 0x3ff00000) { /* y is +-1 */ + if (hy < 0) + return one / x; + else + return x; + } + if (hy == 0x40000000) + return x * x; /* y is 2 */ + if (hy == 0x3fe00000) { /* y is 0.5 */ + if (hx >= 0) /* x >= +0 */ + return __ieee754_sqrt(x); + } + } + + ax = fabs(x); + /* special value of x */ + if (lx == 0) { + if (ix == 0x7ff00000 || ix == 0 || ix == 0x3ff00000) { + z = ax; /*x is +-0,+-inf,+-1 */ + if (hy < 0) + z = one / z; /* z = (1/|x|) */ + if (hx < 0) { + if (((ix - 0x3ff00000) | yisint) == 0) { + z = (z - z) / (z - z); /* (-1)**non-int is NaN */ + } else if (yisint == 1) + z = -z; /* (x<0)**odd = -(|x|**odd) */ + } + return z; + } + } + + /* (x<0)**(non-int) is NaN */ + if (((((u_int32_t) hx >> 31) - 1) | yisint) == 0) + return (x - x) / (x - x); + + /* |y| is huge */ + if (iy > 0x41e00000) { /* if |y| > 2**31 */ + if (iy > 0x43f00000) { /* if |y| > 2**64, must o/uflow */ + if (ix <= 0x3fefffff) + return (hy < 0) ? huge * huge : tiny * tiny; + if (ix >= 0x3ff00000) + return (hy > 0) ? huge * huge : tiny * tiny; + } + /* over/underflow if x is not close to one */ + if (ix < 0x3fefffff) + return (hy < 0) ? huge * huge : tiny * tiny; + if (ix > 0x3ff00000) + return (hy > 0) ? huge * huge : tiny * tiny; + /* now |1-x| is tiny <= 2**-20, suffice to compute + log(x) by x-x^2/2+x^3/3-x^4/4 */ + t = x - 1; /* t has 20 trailing zeros */ + w = (t * t) * (0.5 - t * (0.3333333333333333333333 - t * 0.25)); + u = ivln2_h * t; /* ivln2_h has 21 sig. bits */ + v = t * ivln2_l - w * ivln2; + t1 = u + v; + SET_LOW_WORD(t1, 0); + t2 = v - (t1 - u); + } else { + double s2, s_h, s_l, t_h, t_l; + n = 0; + /* take care subnormal number */ + if (ix < 0x00100000) { + ax *= two53; + n -= 53; + GET_HIGH_WORD(ix, ax); + } + n += ((ix) >> 20) - 0x3ff; + j = ix & 0x000fffff; + /* determine interval */ + ix = j | 0x3ff00000; /* normalize ix */ + if (j <= 0x3988E) + k = 0; /* |x|<sqrt(3/2) */ + else if (j < 0xBB67A) + k = 1; /* |x|<sqrt(3) */ + else { + k = 0; + n += 1; + ix -= 0x00100000; + } + SET_HIGH_WORD(ax, ix); + + /* compute s = s_h+s_l = (x-1)/(x+1) or (x-1.5)/(x+1.5) */ + u = ax - bp[k]; /* bp[0]=1.0, bp[1]=1.5 */ + v = one / (ax + bp[k]); + s = u * v; + s_h = s; + SET_LOW_WORD(s_h, 0); + /* t_h=ax+bp[k] High */ + t_h = zero; + SET_HIGH_WORD(t_h, + ((ix >> 1) | 0x20000000) + 0x00080000 + (k << 18)); + t_l = ax - (t_h - bp[k]); + s_l = v * ((u - s_h * t_h) - s_h * t_l); + /* compute log(ax) */ + s2 = s * s; + r = s2 * s2 * (L1 + + s2 * (L2 + + s2 * (L3 + + s2 * (L4 + s2 * (L5 + s2 * L6))))); + r += s_l * (s_h + s); + s2 = s_h * s_h; + t_h = 3.0 + s2 + r; + SET_LOW_WORD(t_h, 0); + t_l = r - ((t_h - 3.0) - s2); + /* u+v = s*(1+...) */ + u = s_h * t_h; + v = s_l * t_h + t_l * s; + /* 2/(3log2)*(s+...) */ + p_h = u + v; + SET_LOW_WORD(p_h, 0); + p_l = v - (p_h - u); + z_h = cp_h * p_h; /* cp_h+cp_l = 2/(3*log2) */ + z_l = cp_l * p_h + p_l * cp + dp_l[k]; + /* log2(ax) = (s+..)*2/(3*log2) = n + dp_h + z_h + z_l */ + t = (double) n; + t1 = (((z_h + z_l) + dp_h[k]) + t); + SET_LOW_WORD(t1, 0); + t2 = z_l - (((t1 - t) - dp_h[k]) - z_h); + } + + s = one; /* s (sign of result -ve**odd) = -1 else = 1 */ + if (((((u_int32_t) hx >> 31) - 1) | (yisint - 1)) == 0) + s = -one; /* (-ve)**(odd int) */ + + /* split up y into y1+y2 and compute (y1+y2)*(t1+t2) */ + y1 = y; + SET_LOW_WORD(y1, 0); + p_l = (y - y1) * t1 + y * t2; + p_h = y1 * t1; + z = p_l + p_h; + EXTRACT_WORDS(j, i, z); + if (j >= 0x40900000) { /* z >= 1024 */ + if (((j - 0x40900000) | i) != 0) /* if z > 1024 */ + return s * huge * huge; /* overflow */ + else { + if (p_l + ovt > z - p_h) + return s * huge * huge; /* overflow */ + } + } else if ((j & 0x7fffffff) >= 0x4090cc00) { /* z <= -1075 */ + if (((j - 0xc090cc00) | i) != 0) /* z < -1075 */ + return s * tiny * tiny; /* underflow */ + else { + if (p_l <= z - p_h) + return s * tiny * tiny; /* underflow */ + } + } + /* + * compute 2**(p_h+p_l) + */ + i = j & 0x7fffffff; + k = (i >> 20) - 0x3ff; + n = 0; + if (i > 0x3fe00000) { /* if |z| > 0.5, set n = [z+0.5] */ + n = j + (0x00100000 >> (k + 1)); + k = ((n & 0x7fffffff) >> 20) - 0x3ff; /* new k for n */ + t = zero; + SET_HIGH_WORD(t, n & ~(0x000fffff >> k)); + n = ((n & 0x000fffff) | 0x00100000) >> (20 - k); + if (j < 0) + n = -n; + p_h -= t; + } + t = p_l + p_h; + SET_LOW_WORD(t, 0); + u = t * lg2_h; + v = (p_l - (t - p_h)) * lg2 + t * lg2_l; + z = u + v; + w = v - (z - u); + t = z * z; + t1 = z - t * (P1 + t * (P2 + t * (P3 + t * (P4 + t * P5)))); + r = (z * t1) / (t1 - two) - (w + z * w); + z = one - (r - z); + GET_HIGH_WORD(j, z); + j += (n << 20); + if ((j >> 20) <= 0) + z = scalbn(z, n); /* subnormal output */ + else + SET_HIGH_WORD(z, j); + return s * z; + }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/libm/e_rem_pio2.c Mon Sep 15 06:33:23 2008 +0000 @@ -0,0 +1,201 @@ +/* @(#)e_rem_pio2.c 5.1 93/09/24 */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = + "$NetBSD: e_rem_pio2.c,v 1.8 1995/05/10 20:46:02 jtc Exp $"; +#endif + +/* __ieee754_rem_pio2(x,y) + * + * return the remainder of x rem pi/2 in y[0]+y[1] + * use __kernel_rem_pio2() + */ + +#include "math.h" +#include "math_private.h" + +libm_hidden_proto(fabs) + +/* + * Table of constants for 2/pi, 396 Hex digits (476 decimal) of 2/pi + */ +#ifdef __STDC__ + static const int32_t two_over_pi[] = { +#else + static int32_t two_over_pi[] = { +#endif + 0xA2F983, 0x6E4E44, 0x1529FC, 0x2757D1, 0xF534DD, 0xC0DB62, + 0x95993C, 0x439041, 0xFE5163, 0xABDEBB, 0xC561B7, 0x246E3A, + 0x424DD2, 0xE00649, 0x2EEA09, 0xD1921C, 0xFE1DEB, 0x1CB129, + 0xA73EE8, 0x8235F5, 0x2EBB44, 0x84E99C, 0x7026B4, 0x5F7E41, + 0x3991D6, 0x398353, 0x39F49C, 0x845F8B, 0xBDF928, 0x3B1FF8, + 0x97FFDE, 0x05980F, 0xEF2F11, 0x8B5A0A, 0x6D1F6D, 0x367ECF, + 0x27CB09, 0xB74F46, 0x3F669E, 0x5FEA2D, 0x7527BA, 0xC7EBE5, + 0xF17B3D, 0x0739F7, 0x8A5292, 0xEA6BFB, 0x5FB11F, 0x8D5D08, + 0x560330, 0x46FC7B, 0x6BABF0, 0xCFBC20, 0x9AF436, 0x1DA9E3, + 0x91615E, 0xE61B08, 0x659985, 0x5F14A0, 0x68408D, 0xFFD880, + 0x4D7327, 0x310606, 0x1556CA, 0x73A8C9, 0x60E27B, 0xC08C6B, + }; + +#ifdef __STDC__ +static const int32_t npio2_hw[] = { +#else +static int32_t npio2_hw[] = { +#endif + 0x3FF921FB, 0x400921FB, 0x4012D97C, 0x401921FB, 0x401F6A7A, 0x4022D97C, + 0x4025FDBB, 0x402921FB, 0x402C463A, 0x402F6A7A, 0x4031475C, 0x4032D97C, + 0x40346B9C, 0x4035FDBB, 0x40378FDB, 0x403921FB, 0x403AB41B, 0x403C463A, + 0x403DD85A, 0x403F6A7A, 0x40407E4C, 0x4041475C, 0x4042106C, 0x4042D97C, + 0x4043A28C, 0x40446B9C, 0x404534AC, 0x4045FDBB, 0x4046C6CB, 0x40478FDB, + 0x404858EB, 0x404921FB, +}; + +/* + * invpio2: 53 bits of 2/pi + * pio2_1: first 33 bit of pi/2 + * pio2_1t: pi/2 - pio2_1 + * pio2_2: second 33 bit of pi/2 + * pio2_2t: pi/2 - (pio2_1+pio2_2) + * pio2_3: third 33 bit of pi/2 + * pio2_3t: pi/2 - (pio2_1+pio2_2+pio2_3) + */ + +#ifdef __STDC__ +static const double +#else +static double +#endif + zero = 0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */ + half = 5.00000000000000000000e-01, /* 0x3FE00000, 0x00000000 */ + two24 = 1.67772160000000000000e+07, /* 0x41700000, 0x00000000 */ + invpio2 = 6.36619772367581382433e-01, /* 0x3FE45F30, 0x6DC9C883 */ + pio2_1 = 1.57079632673412561417e+00, /* 0x3FF921FB, 0x54400000 */ + pio2_1t = 6.07710050650619224932e-11, /* 0x3DD0B461, 0x1A626331 */ + pio2_2 = 6.07710050630396597660e-11, /* 0x3DD0B461, 0x1A600000 */ + pio2_2t = 2.02226624879595063154e-21, /* 0x3BA3198A, 0x2E037073 */ + pio2_3 = 2.02226624871116645580e-21, /* 0x3BA3198A, 0x2E000000 */ + pio2_3t = 8.47842766036889956997e-32; /* 0x397B839A, 0x252049C1 */ + +#ifdef __STDC__ +int32_t attribute_hidden +__ieee754_rem_pio2(double x, double *y) +#else +int32_t attribute_hidden +__ieee754_rem_pio2(x, y) + double x, y[]; +#endif +{ + double z = 0.0, w, t, r, fn; + double tx[3]; + int32_t e0, i, j, nx, n, ix, hx; + u_int32_t low; + + GET_HIGH_WORD(hx, x); /* high word of x */ + ix = hx & 0x7fffffff; + if (ix <= 0x3fe921fb) { /* |x| ~<= pi/4 , no need for reduction */ + y[0] = x; + y[1] = 0; + return 0; + } + if (ix < 0x4002d97c) { /* |x| < 3pi/4, special case with n=+-1 */ + if (hx > 0) { + z = x - pio2_1; + if (ix != 0x3ff921fb) { /* 33+53 bit pi is good enough */ + y[0] = z - pio2_1t; + y[1] = (z - y[0]) - pio2_1t; + } else { /* near pi/2, use 33+33+53 bit pi */ + z -= pio2_2; + y[0] = z - pio2_2t; + y[1] = (z - y[0]) - pio2_2t; + } + return 1; + } else { /* negative x */ + z = x + pio2_1; + if (ix != 0x3ff921fb) { /* 33+53 bit pi is good enough */ + y[0] = z + pio2_1t; + y[1] = (z - y[0]) + pio2_1t; + } else { /* near pi/2, use 33+33+53 bit pi */ + z += pio2_2; + y[0] = z + pio2_2t; + y[1] = (z - y[0]) + pio2_2t; + } + return -1; + } + } + if (ix <= 0x413921fb) { /* |x| ~<= 2^19*(pi/2), medium size */ + t = fabs(x); + n = (int32_t) (t * invpio2 + half); + fn = (double) n; + r = t - fn * pio2_1; + w = fn * pio2_1t; /* 1st round good to 85 bit */ + if (n < 32 && ix != npio2_hw[n - 1]) { + y[0] = r - w; /* quick check no cancellation */ + } else { + u_int32_t high; + j = ix >> 20; + y[0] = r - w; + GET_HIGH_WORD(high, y[0]); + i = j - ((high >> 20) & 0x7ff); + if (i > 16) { /* 2nd iteration needed, good to 118 */ + t = r; + w = fn * pio2_2; + r = t - w; + w = fn * pio2_2t - ((t - r) - w); + y[0] = r - w; + GET_HIGH_WORD(high, y[0]); + i = j - ((high >> 20) & 0x7ff); + if (i > 49) { /* 3rd iteration need, 151 bits acc */ + t = r; /* will cover all possible cases */ + w = fn * pio2_3; + r = t - w; + w = fn * pio2_3t - ((t - r) - w); + y[0] = r - w; + } + } + } + y[1] = (r - y[0]) - w; + if (hx < 0) { + y[0] = -y[0]; + y[1] = -y[1]; + return -n; + } else + return n; + } + /* + * all other (large) arguments + */ + if (ix >= 0x7ff00000) { /* x is inf or NaN */ + y[0] = y[1] = x - x; + return 0; + } + /* set z = scalbn(|x|,ilogb(x)-23) */ + GET_LOW_WORD(low, x); + SET_LOW_WORD(z, low); + e0 = (ix >> 20) - 1046; /* e0 = ilogb(z)-23; */ + SET_HIGH_WORD(z, ix - ((int32_t) (e0 << 20))); + for (i = 0; i < 2; i++) { + tx[i] = (double) ((int32_t) (z)); + z = (z - tx[i]) * two24; + } + tx[2] = z; + nx = 3; + while (tx[nx - 1] == zero) + nx--; /* skip zero term */ + n = __kernel_rem_pio2(tx, y, e0, nx, 2, two_over_pi); + if (hx < 0) { + y[0] = -y[0]; + y[1] = -y[1]; + return -n; + } + return n; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/libm/e_sqrt.c Mon Sep 15 06:33:23 2008 +0000 @@ -0,0 +1,463 @@ +/* @(#)e_sqrt.c 5.1 93/09/24 */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: e_sqrt.c,v 1.8 1995/05/10 20:46:17 jtc Exp $"; +#endif + +/* __ieee754_sqrt(x) + * Return correctly rounded sqrt. + * ------------------------------------------ + * | Use the hardware sqrt if you have one | + * ------------------------------------------ + * Method: + * Bit by bit method using integer arithmetic. (Slow, but portable) + * 1. Normalization + * Scale x to y in [1,4) with even powers of 2: + * find an integer k such that 1 <= (y=x*2^(2k)) < 4, then + * sqrt(x) = 2^k * sqrt(y) + * 2. Bit by bit computation + * Let q = sqrt(y) truncated to i bit after binary point (q = 1), + * i 0 + * i+1 2 + * s = 2*q , and y = 2 * ( y - q ). (1) + * i i i i + * + * To compute q from q , one checks whether + * i+1 i + * + * -(i+1) 2 + * (q + 2 ) <= y. (2) + * i + * -(i+1) + * If (2) is false, then q = q ; otherwise q = q + 2 . + * i+1 i i+1 i + * + * With some algebric manipulation, it is not difficult to see + * that (2) is equivalent to + * -(i+1) + * s + 2 <= y (3) + * i i + * + * The advantage of (3) is that s and y can be computed by + * i i + * the following recurrence formula: + * if (3) is false + * + * s = s , y = y ; (4) + * i+1 i i+1 i + * + * otherwise, + * -i -(i+1) + * s = s + 2 , y = y - s - 2 (5) + * i+1 i i+1 i i + * + * One may easily use induction to prove (4) and (5). + * Note. Since the left hand side of (3) contain only i+2 bits, + * it does not necessary to do a full (53-bit) comparison + * in (3). + * 3. Final rounding + * After generating the 53 bits result, we compute one more bit. + * Together with the remainder, we can decide whether the + * result is exact, bigger than 1/2ulp, or less than 1/2ulp + * (it will never equal to 1/2ulp). + * The rounding mode can be detected by checking whether + * huge + tiny is equal to huge, and whether huge - tiny is + * equal to huge for some floating point number "huge" and "tiny". + * + * Special cases: + * sqrt(+-0) = +-0 ... exact + * sqrt(inf) = inf + * sqrt(-ve) = NaN ... with invalid signal + * sqrt(NaN) = NaN ... with invalid signal for signaling NaN + * + * Other methods : see the appended file at the end of the program below. + *--------------- + */ + +#include "math.h" +#include "math_private.h" + +#ifdef __STDC__ +static const double one = 1.0, tiny = 1.0e-300; +#else +static double one = 1.0, tiny = 1.0e-300; +#endif + +#ifdef __STDC__ +double attribute_hidden +__ieee754_sqrt(double x) +#else +double attribute_hidden +__ieee754_sqrt(x) + double x; +#endif +{ + double z; + int32_t sign = (int) 0x80000000; + int32_t ix0, s0, q, m, t, i; + u_int32_t r, t1, s1, ix1, q1; + + EXTRACT_WORDS(ix0, ix1, x); + + /* take care of Inf and NaN */ + if ((ix0 & 0x7ff00000) == 0x7ff00000) { + return x * x + x; /* sqrt(NaN)=NaN, sqrt(+inf)=+inf + sqrt(-inf)=sNaN */ + } + /* take care of zero */ + if (ix0 <= 0) { + if (((ix0 & (~sign)) | ix1) == 0) + return x; /* sqrt(+-0) = +-0 */ + else if (ix0 < 0) + return (x - x) / (x - x); /* sqrt(-ve) = sNaN */ + } + /* normalize x */ + m = (ix0 >> 20); + if (m == 0) { /* subnormal x */ + while (ix0 == 0) { + m -= 21; + ix0 |= (ix1 >> 11); + ix1 <<= 21; + } + for (i = 0; (ix0 & 0x00100000) == 0; i++) + ix0 <<= 1; + m -= i - 1; + ix0 |= (ix1 >> (32 - i)); + ix1 <<= i; + } + m -= 1023; /* unbias exponent */ + ix0 = (ix0 & 0x000fffff) | 0x00100000; + if (m & 1) { /* odd m, double x to make it even */ + ix0 += ix0 + ((ix1 & sign) >> 31); + ix1 += ix1; + } + m >>= 1; /* m = [m/2] */ + + /* generate sqrt(x) bit by bit */ + ix0 += ix0 + ((ix1 & sign) >> 31); + ix1 += ix1; + q = q1 = s0 = s1 = 0; /* [q,q1] = sqrt(x) */ + r = 0x00200000; /* r = moving bit from right to left */ + + while (r != 0) { + t = s0 + r; + if (t <= ix0) { + s0 = t + r; + ix0 -= t; + q += r; + } + ix0 += ix0 + ((ix1 & sign) >> 31); + ix1 += ix1; + r >>= 1; + } + + r = sign; + while (r != 0) { + t1 = s1 + r; + t = s0; + if ((t < ix0) || ((t == ix0) && (t1 <= ix1))) { + s1 = t1 + r; + if (((t1 & sign) == sign) && (s1 & sign) == 0) + s0 += 1; + ix0 -= t; + if (ix1 < t1) + ix0 -= 1; + ix1 -= t1; + q1 += r; + } + ix0 += ix0 + ((ix1 & sign) >> 31); + ix1 += ix1; + r >>= 1; + } + + /* use floating add to find out rounding direction */ + if ((ix0 | ix1) != 0) { + z = one - tiny; /* trigger inexact flag */ + if (z >= one) { + z = one + tiny; + if (q1 == (u_int32_t) 0xffffffff) { + q1 = 0; + q += 1; + } else if (z > one) { + if (q1 == (u_int32_t) 0xfffffffe) + q += 1; + q1 += 2; + } else + q1 += (q1 & 1); + } + } + ix0 = (q >> 1) + 0x3fe00000; + ix1 = q1 >> 1; + if ((q & 1) == 1) + ix1 |= sign; + ix0 += (m << 20); + INSERT_WORDS(z, ix0, ix1); + return z; +} + +/* +Other methods (use floating-point arithmetic) +------------- +(This is a copy of a drafted paper by Prof W. Kahan +and K.C. Ng, written in May, 1986) + + Two algorithms are given here to implement sqrt(x) + (IEEE double precision arithmetic) in software. + Both supply sqrt(x) correctly rounded. The first algorithm (in + Section A) uses newton iterations and involves four divisions. + The second one uses reciproot iterations to avoid division, but + requires more multiplications. Both algorithms need the ability + to chop results of arithmetic operations instead of round them, + and the INEXACT flag to indicate when an arithmetic operation + is executed exactly with no roundoff error, all part of the + standard (IEEE 754-1985). The ability to perform shift, add, + subtract and logical AND operations upon 32-bit words is needed + too, though not part of the standard. + +A. sqrt(x) by Newton Iteration + + (1) Initial approximation + + Let x0 and x1 be the leading and the trailing 32-bit words of + a floating point number x (in IEEE double format) respectively + + 1 11 52 ...widths + ------------------------------------------------------ + x: |s| e | f | + ------------------------------------------------------ + msb lsb msb lsb ...order + + + ------------------------ ------------------------ + x0: |s| e | f1 | x1: | f2 | + ------------------------ ------------------------ + + By performing shifts and subtracts on x0 and x1 (both regarded + as integers), we obtain an 8-bit approximation of sqrt(x) as + follows. + + k := (x0>>1) + 0x1ff80000; + y0 := k - T1[31&(k>>15)]. ... y ~ sqrt(x) to 8 bits + Here k is a 32-bit integer and T1[] is an integer array containing + correction terms. Now magically the floating value of y (y's + leading 32-bit word is y0, the value of its trailing word is 0) + approximates sqrt(x) to almost 8-bit. + + Value of T1: + static int T1[32]= { + 0, 1024, 3062, 5746, 9193, 13348, 18162, 23592, + 29598, 36145, 43202, 50740, 58733, 67158, 75992, 85215, + 83599, 71378, 60428, 50647, 41945, 34246, 27478, 21581, + 16499, 12183, 8588, 5674, 3403, 1742, 661, 130,}; + + (2) Iterative refinement + + Apply Heron's rule three times to y, we have y approximates + sqrt(x) to within 1 ulp (Unit in the Last Place): + + y := (y+x/y)/2 ... almost 17 sig. bits + y := (y+x/y)/2 ... almost 35 sig. bits + y := y-(y-x/y)/2 ... within 1 ulp + + + Remark 1. + Another way to improve y to within 1 ulp is: + + y := (y+x/y) ... almost 17 sig. bits to 2*sqrt(x) + y := y - 0x00100006 ... almost 18 sig. bits to sqrt(x) + + 2 + (x-y )*y + y := y + 2* ---------- ...within 1 ulp + 2 + 3y + x + + + This formula has one division fewer than the one above; however, + it requires more multiplications and additions. Also x must be + scaled in advance to avoid spurious overflow in evaluating the + expression 3y*y+x. Hence it is not recommended uless division + is slow. If division is very slow, then one should use the + reciproot algorithm given in section B. + + (3) Final adjustment + + By twiddling y's last bit it is possible to force y to be + correctly rounded according to the prevailing rounding mode + as follows. Let r and i be copies of the rounding mode and + inexact flag before entering the square root program. Also we + use the expression y+-ulp for the next representable floating + numbers (up and down) of y. Note that y+-ulp = either fixed + point y+-1, or multiply y by nextafter(1,+-inf) in chopped + mode. + + I := FALSE; ... reset INEXACT flag I + R := RZ; ... set rounding mode to round-toward-zero + z := x/y; ... chopped quotient, possibly inexact + If(not I) then { ... if the quotient is exact + if(z=y) { + I := i; ... restore inexact flag + R := r; ... restore rounded mode + return sqrt(x):=y. + } else { + z := z - ulp; ... special rounding + } + } + i := TRUE; ... sqrt(x) is inexact + If (r=RN) then z=z+ulp ... rounded-to-nearest + If (r=RP) then { ... round-toward-+inf + y = y+ulp; z=z+ulp; + } + y := y+z; ... chopped sum + y0:=y0-0x00100000; ... y := y/2 is correctly rounded. + I := i; ... restore inexact flag + R := r; ... restore rounded mode + return sqrt(x):=y. + + (4) Special cases + + Square root of +inf, +-0, or NaN is itself; + Square root of a negative number is NaN with invalid signal. + + +B. sqrt(x) by Reciproot Iteration + + (1) Initial approximation + + Let x0 and x1 be the leading and the trailing 32-bit words of + a floating point number x (in IEEE double format) respectively + (see section A). By performing shifs and subtracts on x0 and y0, + we obtain a 7.8-bit approximation of 1/sqrt(x) as follows. + + k := 0x5fe80000 - (x0>>1); + y0:= k - T2[63&(k>>14)]. ... y ~ 1/sqrt(x) to 7.8 bits + + Here k is a 32-bit integer and T2[] is an integer array + containing correction terms. Now magically the floating + value of y (y's leading 32-bit word is y0, the value of + its trailing word y1 is set to zero) approximates 1/sqrt(x) + to almost 7.8-bit. + + Value of T2: + static int T2[64]= { + 0x1500, 0x2ef8, 0x4d67, 0x6b02, 0x87be, 0xa395, 0xbe7a, 0xd866, + 0xf14a, 0x1091b,0x11fcd,0x13552,0x14999,0x15c98,0x16e34,0x17e5f, + 0x18d03,0x19a01,0x1a545,0x1ae8a,0x1b5c4,0x1bb01,0x1bfde,0x1c28d, + 0x1c2de,0x1c0db,0x1ba73,0x1b11c,0x1a4b5,0x1953d,0x18266,0x16be0, + 0x1683e,0x179d8,0x18a4d,0x19992,0x1a789,0x1b445,0x1bf61,0x1c989, + 0x1d16d,0x1d77b,0x1dddf,0x1e2ad,0x1e5bf,0x1e6e8,0x1e654,0x1e3cd, + 0x1df2a,0x1d635,0x1cb16,0x1be2c,0x1ae4e,0x19bde,0x1868e,0x16e2e, + 0x1527f,0x1334a,0x11051,0xe951, 0xbe01, 0x8e0d, 0x5924, 0x1edd,}; + + (2) Iterative refinement + + Apply Reciproot iteration three times to y and multiply the + result by x to get an approximation z that matches sqrt(x) + to about 1 ulp. To be exact, we will have + -1ulp < sqrt(x)-z<1.0625ulp. + + ... set rounding mode to Round-to-nearest + y := y*(1.5-0.5*x*y*y) ... almost 15 sig. bits to 1/sqrt(x) + y := y*((1.5-2^-30)+0.5*x*y*y)... about 29 sig. bits to 1/sqrt(x) + ... special arrangement for better accuracy + z := x*y ... 29 bits to sqrt(x), with z*y<1 + z := z + 0.5*z*(1-z*y) ... about 1 ulp to sqrt(x) + + Remark 2. The constant 1.5-2^-30 is chosen to bias the error so that + (a) the term z*y in the final iteration is always less than 1; + (b) the error in the final result is biased upward so that + -1 ulp < sqrt(x) - z < 1.0625 ulp + instead of |sqrt(x)-z|<1.03125ulp. + + (3) Final adjustment + + By twiddling y's last bit it is possible to force y to be + correctly rounded according to the prevailing rounding mode + as follows. Let r and i be copies of the rounding mode and + inexact flag before entering the square root program. Also we + use the expression y+-ulp for the next representable floating + numbers (up and down) of y. Note that y+-ulp = either fixed + point y+-1, or multiply y by nextafter(1,+-inf) in chopped + mode. + + R := RZ; ... set rounding mode to round-toward-zero + switch(r) { + case RN: ... round-to-nearest + if(x<= z*(z-ulp)...chopped) z = z - ulp; else + if(x<= z*(z+ulp)...chopped) z = z; else z = z+ulp; + break; + case RZ:case RM: ... round-to-zero or round-to--inf + R:=RP; ... reset rounding mod to round-to-+inf + if(x<z*z ... rounded up) z = z - ulp; else + if(x>=(z+ulp)*(z+ulp) ...rounded up) z = z+ulp; + break; + case RP: ... round-to-+inf + if(x>(z+ulp)*(z+ulp)...chopped) z = z+2*ulp; else + if(x>z*z ...chopped) z = z+ulp; + break; + } + + Remark 3. The above comparisons can be done in fixed point. For + example, to compare x and w=z*z chopped, it suffices to compare + x1 and w1 (the trailing parts of x and w), regarding them as + two's complement integers. + + ...Is z an exact square root? + To determine whether z is an exact square root of x, let z1 be the + trailing part of z, and also let x0 and x1 be the leading and + trailing parts of x. + + If ((z1&0x03ffffff)!=0) ... not exact if trailing 26 bits of z!=0 + I := 1; ... Raise Inexact flag: z is not exact + else { + j := 1 - [(x0>>20)&1] ... j = logb(x) mod 2 + k := z1 >> 26; ... get z's 25-th and 26-th + fraction bits + I := i or (k&j) or ((k&(j+j+1))!=(x1&3)); + } + R:= r ... restore rounded mode + return sqrt(x):=z. + + If multiplication is cheaper then the foregoing red tape, the + Inexact flag can be evaluated by + + I := i; + I := (z*z!=x) or I. + + Note that z*z can overwrite I; this value must be sensed if it is + True. + + Remark 4. If z*z = x exactly, then bit 25 to bit 0 of z1 must be + zero. + + -------------------- + z1: | f2 | + -------------------- + bit 31 bit 0 + + Further more, bit 27 and 26 of z1, bit 0 and 1 of x1, and the odd + or even of logb(x) have the following relations: + + ------------------------------------------------- + bit 27,26 of z1 bit 1,0 of x1 logb(x) + ------------------------------------------------- + 00 00 odd and even + 01 01 even + 10 10 odd + 10 00 even + 11 01 even + ------------------------------------------------- + + (4) Special cases (see (4) of Section A). + + */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/libm/k_cos.c Mon Sep 15 06:33:23 2008 +0000 @@ -0,0 +1,99 @@ +/* @(#)k_cos.c 5.1 93/09/24 */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: k_cos.c,v 1.8 1995/05/10 20:46:22 jtc Exp $"; +#endif + +/* + * __kernel_cos( x, y ) + * kernel cos function on [-pi/4, pi/4], pi/4 ~ 0.785398164 + * Input x is assumed to be bounded by ~pi/4 in magnitude. + * Input y is the tail of x. + * + * Algorithm + * 1. Since cos(-x) = cos(x), we need only to consider positive x. + * 2. if x < 2^-27 (hx<0x3e400000 0), return 1 with inexact if x!=0. + * 3. cos(x) is approximated by a polynomial of degree 14 on + * [0,pi/4] + * 4 14 + * cos(x) ~ 1 - x*x/2 + C1*x + ... + C6*x + * where the remez error is + * + * | 2 4 6 8 10 12 14 | -58 + * |cos(x)-(1-.5*x +C1*x +C2*x +C3*x +C4*x +C5*x +C6*x )| <= 2 + * | | + * + * 4 6 8 10 12 14 + * 4. let r = C1*x +C2*x +C3*x +C4*x +C5*x +C6*x , then + * cos(x) = 1 - x*x/2 + r + * since cos(x+y) ~ cos(x) - sin(x)*y + * ~ cos(x) - x*y, + * a correction term is necessary in cos(x) and hence + * cos(x+y) = 1 - (x*x/2 - (r - x*y)) + * For better accuracy when x > 0.3, let qx = |x|/4 with + * the last 32 bits mask off, and if x > 0.78125, let qx = 0.28125. + * Then + * cos(x+y) = (1-qx) - ((x*x/2-qx) - (r-x*y)). + * Note that 1-qx and (x*x/2-qx) is EXACT here, and the + * magnitude of the latter is at least a quarter of x*x/2, + * thus, reducing the rounding error in the subtraction. + */ + +#include "math.h" +#include "math_private.h" + +#ifdef __STDC__ +static const double +#else +static double +#endif + one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */ + C1 = 4.16666666666666019037e-02, /* 0x3FA55555, 0x5555554C */ + C2 = -1.38888888888741095749e-03, /* 0xBF56C16C, 0x16C15177 */ + C3 = 2.48015872894767294178e-05, /* 0x3EFA01A0, 0x19CB1590 */ + C4 = -2.75573143513906633035e-07, /* 0xBE927E4F, 0x809C52AD */ + C5 = 2.08757232129817482790e-09, /* 0x3E21EE9E, 0xBDB4B1C4 */ + C6 = -1.13596475577881948265e-11; /* 0xBDA8FAE9, 0xBE8838D4 */ + +#ifdef __STDC__ +double attribute_hidden +__kernel_cos(double x, double y) +#else +double attribute_hidden +__kernel_cos(x, y) + double x, y; +#endif +{ + double a, hz, z, r, qx; + int32_t ix; + GET_HIGH_WORD(ix, x); + ix &= 0x7fffffff; /* ix = |x|'s high word */ + if (ix < 0x3e400000) { /* 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 < 0x3FD33333) /* if |x| < 0.3 */ + return one - (0.5 * z - (z * r - x * y)); + else { + if (ix > 0x3fe90000) { /* x > 0.78125 */ + qx = 0.28125; + } else { + INSERT_WORDS(qx, ix - 0x00200000, 0); /* x/4 */ + } + hz = 0.5 * z - qx; + a = one - qx; + return a - (hz - (z * r - x * y)); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/libm/k_sin.c Mon Sep 15 06:33:23 2008 +0000 @@ -0,0 +1,86 @@ +/* @(#)k_sin.c 5.1 93/09/24 */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: k_sin.c,v 1.8 1995/05/10 20:46:31 jtc Exp $"; +#endif + +/* __kernel_sin( x, y, iy) + * kernel sin function on [-pi/4, pi/4], pi/4 ~ 0.7854 + * Input x is assumed to be bounded by ~pi/4 in magnitude. + * Input y is the tail of x. + * Input iy indicates whether y is 0. (if iy=0, y assume to be 0). + * + * Algorithm + * 1. Since sin(-x) = -sin(x), we need only to consider positive x. + * 2. if x < 2^-27 (hx<0x3e400000 0), return x with inexact if x!=0. + * 3. sin(x) is approximated by a polynomial of degree 13 on + * [0,pi/4] + * 3 13 + * sin(x) ~ x + S1*x + ... + S6*x + * where + * + * |sin(x) 2 4 6 8 10 12 | -58 + * |----- - (1+S1*x +S2*x +S3*x +S4*x +S5*x +S6*x )| <= 2 + * | x | + * + * 4. sin(x+y) = sin(x) + sin'(x')*y + * ~ sin(x) + (1-x*x/2)*y + * For better accuracy, let + * 3 2 2 2 2 + * r = x *(S2+x *(S3+x *(S4+x *(S5+x *S6)))) + * then 3 2 + * sin(x) = x + (S1*x + (x *(r-y/2)+y)) + */ + +#include "math.h" +#include "math_private.h" + +#ifdef __STDC__ +static const double +#else +static double +#endif + half = 5.00000000000000000000e-01, /* 0x3FE00000, 0x00000000 */ + S1 = -1.66666666666666324348e-01, /* 0xBFC55555, 0x55555549 */ + S2 = 8.33333333332248946124e-03, /* 0x3F811111, 0x1110F8A6 */ + S3 = -1.98412698298579493134e-04, /* 0xBF2A01A0, 0x19C161D5 */ + S4 = 2.75573137070700676789e-06, /* 0x3EC71DE3, 0x57B1FE7D */ + S5 = -2.50507602534068634195e-08, /* 0xBE5AE5E6, 0x8A2B9CEB */ + S6 = 1.58969099521155010221e-10; /* 0x3DE5D93A, 0x5ACFD57C */ + +#ifdef __STDC__ +double attribute_hidden +__kernel_sin(double x, double y, int iy) +#else +double attribute_hidden +__kernel_sin(x, y, iy) + double x, y; + int iy; /* iy=0 if y is zero */ +#endif +{ + double z, r, v; + int32_t ix; + GET_HIGH_WORD(ix, x); + ix &= 0x7fffffff; /* high word of x */ + if (ix < 0x3e400000) { /* |x| < 2**-27 */ + if ((int) x == 0) + return x; + } /* generate inexact */ + z = x * x; + v = z * x; + r = S2 + z * (S3 + z * (S4 + z * (S5 + z * S6))); + if (iy == 0) + return x + v * (S1 + z * r); + else + return x - ((z * (half * y - v * r) - y) - v * S1); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/libm/math.h Mon Sep 15 06:33:23 2008 +0000 @@ -0,0 +1,44 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2006 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifdef HAVE_MATH_H +#include <math.h> +#else + +extern double __ieee754_log(double x); +extern double __ieee754_pow(double x, double y); +extern double __ieee754_sqrt(double x); + +#define log(x) __ieee754_log(x) +#define pow(x, y) __ieee754_pow(x, y) +#define sqrt(x) __ieee754_sqrt(x) + +extern double copysign(double x, double y); +extern double cos(double x); +extern double fabs(double x); +extern double scalbn(double x, int n); +extern double sin(double x); + +#endif /* HAVE_MATH_H */ + +/* vi: set ts=4 sw=4 expandtab: */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/libm/math_private.h Mon Sep 15 06:33:23 2008 +0000 @@ -0,0 +1,204 @@ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* + * from: @(#)fdlibm.h 5.1 93/09/24 + * $Id: math_private.h,v 1.3 2004/02/09 07:10:38 andersen Exp $ + */ + +#ifndef _MATH_PRIVATE_H_ +#define _MATH_PRIVATE_H_ + +/*#include <endian.h>*/ +#include <sys/types.h> + +#define attribute_hidden +#define libm_hidden_proto(x) +#define libm_hidden_def(x) + +/* The original fdlibm code used statements like: + n0 = ((*(int*)&one)>>29)^1; * index of high word * + ix0 = *(n0+(int*)&x); * high word of x * + ix1 = *((1-n0)+(int*)&x); * low word of x * + to dig two 32 bit words out of the 64 bit IEEE floating point + value. That is non-ANSI, and, moreover, the gcc instruction + scheduler gets it wrong. We instead use the following macros. + Unlike the original code, we determine the endianness at compile + time, not at run time; I don't see much benefit to selecting + endianness at run time. */ + +/* A union which permits us to convert between a double and two 32 bit + ints. */ + +/* + * Math on arm is special: + * For FPA, float words are always big-endian. + * For VFP, floats words follow the memory system mode. + */ + +#if (__BYTE_ORDER == __BIG_ENDIAN) || \ + (!defined(__VFP_FP__) && (defined(__arm__) || defined(__thumb__))) + +typedef union +{ + double value; + struct + { + u_int32_t msw; + u_int32_t lsw; + } parts; +} ieee_double_shape_type; + +#else + +typedef union +{ + double value; + struct + { + u_int32_t lsw; + u_int32_t msw; + } parts; +} ieee_double_shape_type; + +#endif + +/* Get two 32 bit ints from a double. */ + +#define EXTRACT_WORDS(ix0,ix1,d) \ +do { \ + ieee_double_shape_type ew_u; \ + ew_u.value = (d); \ + (ix0) = ew_u.parts.msw; \ + (ix1) = ew_u.parts.lsw; \ +} while (0) + +/* Get the more significant 32 bit int from a double. */ + +#define GET_HIGH_WORD(i,d) \ +do { \ + ieee_double_shape_type gh_u; \ + gh_u.value = (d); \ + (i) = gh_u.parts.msw; \ +} while (0) + +/* Get the less significant 32 bit int from a double. */ + +#define GET_LOW_WORD(i,d) \ +do { \ + ieee_double_shape_type gl_u; \ + gl_u.value = (d); \ + (i) = gl_u.parts.lsw; \ +} while (0) + +/* Set a double from two 32 bit ints. */ + +#define INSERT_WORDS(d,ix0,ix1) \ +do { \ + ieee_double_shape_type iw_u; \ + iw_u.parts.msw = (ix0); \ + iw_u.parts.lsw = (ix1); \ + (d) = iw_u.value; \ +} while (0) + +/* Set the more significant 32 bits of a double from an int. */ + +#define SET_HIGH_WORD(d,v) \ +do { \ + ieee_double_shape_type sh_u; \ + sh_u.value = (d); \ + sh_u.parts.msw = (v); \ + (d) = sh_u.value; \ +} while (0) + +/* Set the less significant 32 bits of a double from an int. */ + +#define SET_LOW_WORD(d,v) \ +do { \ + ieee_double_shape_type sl_u; \ + sl_u.value = (d); \ + sl_u.parts.lsw = (v); \ + (d) = sl_u.value; \ +} while (0) + +/* A union which permits us to convert between a float and a 32 bit + int. */ + +typedef union +{ + float value; + u_int32_t word; +} ieee_float_shape_type; + +/* Get a 32 bit int from a float. */ + +#define GET_FLOAT_WORD(i,d) \ +do { \ + ieee_float_shape_type gf_u; \ + gf_u.value = (d); \ + (i) = gf_u.word; \ +} while (0) + +/* Set a float from a 32 bit int. */ + +#define SET_FLOAT_WORD(d,i) \ +do { \ + ieee_float_shape_type sf_u; \ + sf_u.word = (i); \ + (d) = sf_u.value; \ +} while (0) + +/* ieee style elementary functions */ +extern double +__ieee754_sqrt(double) + attribute_hidden; + extern double __ieee754_acos(double) attribute_hidden; + extern double __ieee754_acosh(double) attribute_hidden; + extern double __ieee754_log(double) attribute_hidden; + extern double __ieee754_atanh(double) attribute_hidden; + extern double __ieee754_asin(double) attribute_hidden; + extern double __ieee754_atan2(double, double) attribute_hidden; + extern double __ieee754_exp(double) attribute_hidden; + extern double __ieee754_cosh(double) attribute_hidden; + extern double __ieee754_fmod(double, double) attribute_hidden; + extern double __ieee754_pow(double, double) attribute_hidden; + extern double __ieee754_lgamma_r(double, int *) attribute_hidden; + extern double __ieee754_gamma_r(double, int *) attribute_hidden; + extern double __ieee754_lgamma(double) attribute_hidden; + extern double __ieee754_gamma(double) attribute_hidden; + extern double __ieee754_log10(double) attribute_hidden; + extern double __ieee754_sinh(double) attribute_hidden; + extern double __ieee754_hypot(double, double) attribute_hidden; + extern double __ieee754_j0(double) attribute_hidden; + extern double __ieee754_j1(double) attribute_hidden; + extern double __ieee754_y0(double) attribute_hidden; + extern double __ieee754_y1(double) attribute_hidden; + extern double __ieee754_jn(int, double) attribute_hidden; + extern double __ieee754_yn(int, double) attribute_hidden; + extern double __ieee754_remainder(double, double) attribute_hidden; + extern int __ieee754_rem_pio2(double, double *) attribute_hidden; +#if defined(_SCALB_INT) + extern double __ieee754_scalb(double, int) attribute_hidden; +#else + extern double __ieee754_scalb(double, double) attribute_hidden; +#endif + +/* fdlibm kernel function */ +#ifndef _IEEE_LIBM + extern double __kernel_standard(double, double, int) attribute_hidden; +#endif + extern double __kernel_sin(double, double, int) attribute_hidden; + extern double __kernel_cos(double, double) attribute_hidden; + extern double __kernel_tan(double, double, int) attribute_hidden; + extern int __kernel_rem_pio2(double *, double *, int, int, int, + const int *) attribute_hidden; + +#endif /* _MATH_PRIVATE_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/libm/s_copysign.c Mon Sep 15 06:33:23 2008 +0000 @@ -0,0 +1,42 @@ +/* @(#)s_copysign.c 5.1 93/09/24 */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = + "$NetBSD: s_copysign.c,v 1.8 1995/05/10 20:46:57 jtc Exp $"; +#endif + +/* + * copysign(double x, double y) + * copysign(x,y) returns a value with the magnitude of x and + * with the sign bit of y. + */ + +#include "math.h" +#include "math_private.h" + +libm_hidden_proto(copysign) +#ifdef __STDC__ + double copysign(double x, double y) +#else + double copysign(x, y) + double x, y; +#endif +{ + u_int32_t hx, hy; + GET_HIGH_WORD(hx, x); + GET_HIGH_WORD(hy, y); + SET_HIGH_WORD(x, (hx & 0x7fffffff) | (hy & 0x80000000)); + return x; +} + +libm_hidden_def(copysign)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/libm/s_cos.c Mon Sep 15 06:33:23 2008 +0000 @@ -0,0 +1,90 @@ +/* @(#)s_cos.c 5.1 93/09/24 */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: s_cos.c,v 1.7 1995/05/10 20:47:02 jtc Exp $"; +#endif + +/* cos(x) + * Return cosine function of x. + * + * kernel function: + * __kernel_sin ... sine function on [-pi/4,pi/4] + * __kernel_cos ... cosine function on [-pi/4,pi/4] + * __ieee754_rem_pio2 ... argument reduction routine + * + * Method. + * Let S,C and T denote the sin, cos and tan respectively on + * [-PI/4, +PI/4]. Reduce the argument x to y1+y2 = x-k*pi/2 + * in [-pi/4 , +pi/4], and let n = k mod 4. + * We have + * + * n sin(x) cos(x) tan(x) + * ---------------------------------------------------------- + * 0 S C T + * 1 C -S -1/T + * 2 -S -C T + * 3 -C S -1/T + * ---------------------------------------------------------- + * + * Special cases: + * Let trig be any of sin, cos, or tan. + * trig(+-INF) is NaN, with signals; + * trig(NaN) is that NaN; + * + * Accuracy: + * TRIG(x) returns trig(x) nearly rounded + */ + +#include "math.h" +#include "math_private.h" + +libm_hidden_proto(cos) +#ifdef __STDC__ + double cos(double x) +#else + double cos(x) + double x; +#endif +{ + double y[2], z = 0.0; + int32_t n, ix; + + /* High word of x. */ + GET_HIGH_WORD(ix, x); + + /* |x| ~< pi/4 */ + ix &= 0x7fffffff; + if (ix <= 0x3fe921fb) + return __kernel_cos(x, z); + + /* cos(Inf or NaN) is NaN */ + else if (ix >= 0x7ff00000) + return x - x; + + /* argument reduction needed */ + else { + n = __ieee754_rem_pio2(x, y); + switch (n & 3) { + case 0: + return __kernel_cos(y[0], y[1]); + case 1: + return -__kernel_sin(y[0], y[1], 1); + case 2: + return -__kernel_cos(y[0], y[1]); + default: + return __kernel_sin(y[0], y[1], 1); + } + } +} + +libm_hidden_def(cos)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/libm/s_fabs.c Mon Sep 15 06:33:23 2008 +0000 @@ -0,0 +1,38 @@ +/* @(#)s_fabs.c 5.1 93/09/24 */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: s_fabs.c,v 1.7 1995/05/10 20:47:13 jtc Exp $"; +#endif + +/* + * fabs(x) returns the absolute value of x. + */ + +#include "math.h" +#include "math_private.h" + +libm_hidden_proto(fabs) +#ifdef __STDC__ + double fabs(double x) +#else + double fabs(x) + double x; +#endif +{ + u_int32_t high; + GET_HIGH_WORD(high, x); + SET_HIGH_WORD(x, high & 0x7fffffff); + return x; +} + +libm_hidden_def(fabs)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/libm/s_scalbn.c Mon Sep 15 06:33:23 2008 +0000 @@ -0,0 +1,79 @@ +/* @(#)s_scalbn.c 5.1 93/09/24 */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = + "$NetBSD: s_scalbn.c,v 1.8 1995/05/10 20:48:08 jtc Exp $"; +#endif + +/* + * scalbn (double x, int n) + * scalbn(x,n) returns x* 2**n computed by exponent + * manipulation rather than by actually performing an + * exponentiation or a multiplication. + */ + +#include "math.h" +#include "math_private.h" + +libm_hidden_proto(copysign) +#ifdef __STDC__ + static const double +#else + static double +#endif + two54 = 1.80143985094819840000e+16, /* 0x43500000, 0x00000000 */ + twom54 = 5.55111512312578270212e-17, /* 0x3C900000, 0x00000000 */ + huge = 1.0e+300, tiny = 1.0e-300; + +libm_hidden_proto(scalbn) +#ifdef __STDC__ + double scalbn(double x, int n) +#else + double scalbn(x, n) + double x; + int n; +#endif +{ + int32_t k, hx, lx; + EXTRACT_WORDS(hx, lx, x); + k = (hx & 0x7ff00000) >> 20; /* extract exponent */ + if (k == 0) { /* 0 or subnormal x */ + if ((lx | (hx & 0x7fffffff)) == 0) + return x; /* +-0 */ + x *= two54; + GET_HIGH_WORD(hx, x); + k = ((hx & 0x7ff00000) >> 20) - 54; + if (n < -50000) + return tiny * x; /*underflow */ + } + if (k == 0x7ff) + return x + x; /* NaN or Inf */ + k = k + n; + if (k > 0x7fe) + return huge * copysign(huge, x); /* overflow */ + if (k > 0) { /* normal result */ + SET_HIGH_WORD(x, (hx & 0x800fffff) | (k << 20)); + return x; + } + if (k <= -54) { + if (n > 50000) /* in case integer overflow in n+k */ + return huge * copysign(huge, x); /*overflow */ + else + return tiny * copysign(tiny, x); /*underflow */ + } + k += 54; /* subnormal result */ + SET_HIGH_WORD(x, (hx & 0x800fffff) | (k << 20)); + return x * twom54; +} + +libm_hidden_def(scalbn)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/libm/s_sin.c Mon Sep 15 06:33:23 2008 +0000 @@ -0,0 +1,90 @@ +/* @(#)s_sin.c 5.1 93/09/24 */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: s_sin.c,v 1.7 1995/05/10 20:48:15 jtc Exp $"; +#endif + +/* sin(x) + * Return sine function of x. + * + * kernel function: + * __kernel_sin ... sine function on [-pi/4,pi/4] + * __kernel_cos ... cose function on [-pi/4,pi/4] + * __ieee754_rem_pio2 ... argument reduction routine + * + * Method. + * Let S,C and T denote the sin, cos and tan respectively on + * [-PI/4, +PI/4]. Reduce the argument x to y1+y2 = x-k*pi/2 + * in [-pi/4 , +pi/4], and let n = k mod 4. + * We have + * + * n sin(x) cos(x) tan(x) + * ---------------------------------------------------------- + * 0 S C T + * 1 C -S -1/T + * 2 -S -C T + * 3 -C S -1/T + * ---------------------------------------------------------- + * + * Special cases: + * Let trig be any of sin, cos, or tan. + * trig(+-INF) is NaN, with signals; + * trig(NaN) is that NaN; + * + * Accuracy: + * TRIG(x) returns trig(x) nearly rounded + */ + +#include "math.h" +#include "math_private.h" + +libm_hidden_proto(sin) +#ifdef __STDC__ + double sin(double x) +#else + double sin(x) + double x; +#endif +{ + double y[2], z = 0.0; + int32_t n, ix; + + /* High word of x. */ + GET_HIGH_WORD(ix, x); + + /* |x| ~< pi/4 */ + ix &= 0x7fffffff; + if (ix <= 0x3fe921fb) + return __kernel_sin(x, z, 0); + + /* sin(Inf or NaN) is NaN */ + else if (ix >= 0x7ff00000) + return x - x; + + /* argument reduction needed */ + else { + n = __ieee754_rem_pio2(x, y); + switch (n & 3) { + case 0: + return __kernel_sin(y[0], y[1], 1); + case 1: + return __kernel_cos(y[0], y[1]); + case 2: + return -__kernel_sin(y[0], y[1], 1); + default: + return -__kernel_cos(y[0], y[1]); + } + } +} + +libm_hidden_def(sin)
--- a/src/video/SDL_gamma.c Mon Sep 15 05:14:11 2008 +0000 +++ b/src/video/SDL_gamma.c Mon Sep 15 06:33:23 2008 +0000 @@ -23,17 +23,7 @@ /* Gamma correction support */ -#ifdef HAVE_MATH_H -#include <math.h> /* Used for calculating gamma ramps */ -#else -/* Math routines from uClibc: http://www.uclibc.org */ -#include "math_private.h" -#include "e_sqrt.h" -#include "e_pow.h" -#include "e_log.h" -#define pow(x, y) __ieee754_pow(x, y) -#define log(x) __ieee754_log(x) -#endif +#include "../libm/math.h" #include "SDL_sysvideo.h"
--- a/src/video/e_log.h Mon Sep 15 05:14:11 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,161 +0,0 @@ -/* @(#)e_log.c 5.1 93/09/24 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunPro, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -#if defined(LIBM_SCCS) && !defined(lint) -static char rcsid[] = "$NetBSD: e_log.c,v 1.8 1995/05/10 20:45:49 jtc Exp $"; -#endif - -/* __ieee754_log(x) - * Return the logrithm of x - * - * Method : - * 1. Argument Reduction: find k and f such that - * x = 2^k * (1+f), - * where sqrt(2)/2 < 1+f < sqrt(2) . - * - * 2. Approximation of log(1+f). - * Let s = f/(2+f) ; based on log(1+f) = log(1+s) - log(1-s) - * = 2s + 2/3 s**3 + 2/5 s**5 + ....., - * = 2s + s*R - * We use a special Reme algorithm on [0,0.1716] to generate - * a polynomial of degree 14 to approximate R The maximum error - * of this polynomial approximation is bounded by 2**-58.45. In - * other words, - * 2 4 6 8 10 12 14 - * R(z) ~ Lg1*s +Lg2*s +Lg3*s +Lg4*s +Lg5*s +Lg6*s +Lg7*s - * (the values of Lg1 to Lg7 are listed in the program) - * and - * | 2 14 | -58.45 - * | Lg1*s +...+Lg7*s - R(z) | <= 2 - * | | - * Note that 2s = f - s*f = f - hfsq + s*hfsq, where hfsq = f*f/2. - * In order to guarantee error in log below 1ulp, we compute log - * by - * log(1+f) = f - s*(f - R) (if f is not too large) - * log(1+f) = f - (hfsq - s*(hfsq+R)). (better accuracy) - * - * 3. Finally, log(x) = k*ln2 + log(1+f). - * = k*ln2_hi+(f-(hfsq-(s*(hfsq+R)+k*ln2_lo))) - * Here ln2 is split into two floating point number: - * ln2_hi + ln2_lo, - * where n*ln2_hi is always exact for |n| < 2000. - * - * Special cases: - * log(x) is NaN with signal if x < 0 (including -INF) ; - * log(+INF) is +INF; log(0) is -INF with signal; - * log(NaN) is that NaN with no signal. - * - * Accuracy: - * according to an error analysis, the error is always less than - * 1 ulp (unit in the last place). - * - * Constants: - * The hexadecimal values are the intended ones for the following - * constants. The decimal values may be used, provided that the - * compiler will convert from decimal to binary accurately enough - * to produce the hexadecimal values shown. - */ - -/*#include "math.h"*/ -#include "math_private.h" - -#ifdef __STDC__ -static const double -#else -static double -#endif - ln2_hi = 6.93147180369123816490e-01, /* 3fe62e42 fee00000 */ - ln2_lo = 1.90821492927058770002e-10, /* 3dea39ef 35793c76 */ - Lg1 = 6.666666666666735130e-01, /* 3FE55555 55555593 */ - Lg2 = 3.999999999940941908e-01, /* 3FD99999 9997FA04 */ - Lg3 = 2.857142874366239149e-01, /* 3FD24924 94229359 */ - Lg4 = 2.222219843214978396e-01, /* 3FCC71C5 1D8E78AF */ - Lg5 = 1.818357216161805012e-01, /* 3FC74664 96CB03DE */ - Lg6 = 1.531383769920937332e-01, /* 3FC39A09 D078C69F */ - Lg7 = 1.479819860511658591e-01; /* 3FC2F112 DF3E5244 */ - -#ifdef __STDC__ -double -__ieee754_log(double x) -#else -double -__ieee754_log(x) - double x; -#endif -{ - double hfsq, f, s, z, R, w, t1, t2, dk; - int32_t k, hx, i, j; - u_int32_t lx; - - EXTRACT_WORDS(hx, lx, x); - - k = 0; - if (hx < 0x00100000) { /* x < 2**-1022 */ - if (((hx & 0x7fffffff) | lx) == 0) - return -two54 / zero; /* log(+-0)=-inf */ - if (hx < 0) - return (x - x) / zero; /* log(-#) = NaN */ - k -= 54; - x *= two54; /* subnormal number, scale up x */ - GET_HIGH_WORD(hx, x); - } - if (hx >= 0x7ff00000) - return x + x; - k += (hx >> 20) - 1023; - hx &= 0x000fffff; - i = (hx + 0x95f64) & 0x100000; - SET_HIGH_WORD(x, hx | (i ^ 0x3ff00000)); /* normalize x or x/2 */ - k += (i >> 20); - f = x - 1.0; - if ((0x000fffff & (2 + hx)) < 3) { /* |f| < 2**-20 */ - if (f == zero) { - if (k == 0) - return zero; - else { - dk = (double) k; - return dk * ln2_hi + dk * ln2_lo; - } - } - R = f * f * (0.5 - 0.33333333333333333 * f); - if (k == 0) - return f - R; - else { - dk = (double) k; - return dk * ln2_hi - ((R - dk * ln2_lo) - f); - } - } - s = f / (2.0 + f); - dk = (double) k; - z = s * s; - i = hx - 0x6147a; - w = z * z; - j = 0x6b851 - hx; - 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 = 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); - } -} - -/* vi: set ts=4 sw=4 expandtab: */
--- a/src/video/e_pow.h Mon Sep 15 05:14:11 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,340 +0,0 @@ -/* @(#)e_pow.c 5.1 93/09/24 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunPro, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -#if defined(LIBM_SCCS) && !defined(lint) -static char rcsid[] = "$NetBSD: e_pow.c,v 1.9 1995/05/12 04:57:32 jtc Exp $"; -#endif - -/* __ieee754_pow(x,y) return x**y - * - * n - * Method: Let x = 2 * (1+f) - * 1. Compute and return log2(x) in two pieces: - * log2(x) = w1 + w2, - * where w1 has 53-24 = 29 bit trailing zeros. - * 2. Perform y*log2(x) = n+y' by simulating muti-precision - * arithmetic, where |y'|<=0.5. - * 3. Return x**y = 2**n*exp(y'*log2) - * - * Special cases: - * 1. (anything) ** 0 is 1 - * 2. (anything) ** 1 is itself - * 3. (anything) ** NAN is NAN - * 4. NAN ** (anything except 0) is NAN - * 5. +-(|x| > 1) ** +INF is +INF - * 6. +-(|x| > 1) ** -INF is +0 - * 7. +-(|x| < 1) ** +INF is +0 - * 8. +-(|x| < 1) ** -INF is +INF - * 9. +-1 ** +-INF is NAN - * 10. +0 ** (+anything except 0, NAN) is +0 - * 11. -0 ** (+anything except 0, NAN, odd integer) is +0 - * 12. +0 ** (-anything except 0, NAN) is +INF - * 13. -0 ** (-anything except 0, NAN, odd integer) is +INF - * 14. -0 ** (odd integer) = -( +0 ** (odd integer) ) - * 15. +INF ** (+anything except 0,NAN) is +INF - * 16. +INF ** (-anything except 0,NAN) is +0 - * 17. -INF ** (anything) = -0 ** (-anything) - * 18. (-anything) ** (integer) is (-1)**(integer)*(+anything**integer) - * 19. (-anything except 0 and inf) ** (non-integer) is NAN - * - * Accuracy: - * pow(x,y) returns x**y nearly rounded. In particular - * pow(integer,integer) - * always returns the correct integer provided it is - * representable. - * - * Constants : - * The hexadecimal values are the intended ones for the following - * constants. The decimal values may be used, provided that the - * compiler will convert from decimal to binary accurately enough - * to produce the hexadecimal values shown. - */ - -/*#include "math.h"*/ -#include "math_private.h" - -#ifdef __STDC__ -static const double -#else -static double -#endif - bp[] = { 1.0, 1.5, }, dp_h[] = { -0.0, 5.84962487220764160156e-01,}, /* 0x3FE2B803, 0x40000000 */ - - dp_l[] = { -0.0, 1.35003920212974897128e-08,}, /* 0x3E4CFDEB, 0x43CFD006 */ - - /* poly coefs for (3/2)*(log(x)-2s-2/3*s**3 */ - L1 = 5.99999999999994648725e-01, /* 0x3FE33333, 0x33333303 */ - L2 = 4.28571428578550184252e-01, /* 0x3FDB6DB6, 0xDB6FABFF */ - L3 = 3.33333329818377432918e-01, /* 0x3FD55555, 0x518F264D */ - L4 = 2.72728123808534006489e-01, /* 0x3FD17460, 0xA91D4101 */ - L5 = 2.30660745775561754067e-01, /* 0x3FCD864A, 0x93C9DB65 */ - L6 = 2.06975017800338417784e-01, /* 0x3FCA7E28, 0x4A454EEF */ - P1 = 1.66666666666666019037e-01, /* 0x3FC55555, 0x5555553E */ - P2 = -2.77777777770155933842e-03, /* 0xBF66C16C, 0x16BEBD93 */ - P3 = 6.61375632143793436117e-05, /* 0x3F11566A, 0xAF25DE2C */ - P4 = -1.65339022054652515390e-06, /* 0xBEBBBD41, 0xC5D26BF1 */ - P5 = 4.13813679705723846039e-08, /* 0x3E663769, 0x72BEA4D0 */ - lg2 = 6.93147180559945286227e-01, /* 0x3FE62E42, 0xFEFA39EF */ - lg2_h = 6.93147182464599609375e-01, /* 0x3FE62E43, 0x00000000 */ - lg2_l = -1.90465429995776804525e-09, /* 0xBE205C61, 0x0CA86C39 */ - ovt = 8.0085662595372944372e-0017, /* -(1024-log2(ovfl+.5ulp)) */ - cp = 9.61796693925975554329e-01, /* 0x3FEEC709, 0xDC3A03FD =2/(3ln2) */ - cp_h = 9.61796700954437255859e-01, /* 0x3FEEC709, 0xE0000000 =(float)cp */ - cp_l = -7.02846165095275826516e-09, /* 0xBE3E2FE0, 0x145B01F5 =tail of cp_h */ - ivln2 = 1.44269504088896338700e+00, /* 0x3FF71547, 0x652B82FE =1/ln2 */ - ivln2_h = 1.44269502162933349609e+00, /* 0x3FF71547, 0x60000000 =24b 1/ln2 */ - ivln2_l = 1.92596299112661746887e-08; /* 0x3E54AE0B, 0xF85DDF44 =1/ln2 tail */ - -#ifdef __STDC__ -double -__ieee754_pow(double x, double y) -#else -double -__ieee754_pow(x, y) - double x, y; -#endif -{ - double z, ax, z_h, z_l, p_h, p_l; - double y1, t1, t2, r, s, t, u, v, w; - int32_t i, j, k, yisint, n; - int32_t hx, hy, ix, iy; - u_int32_t lx, ly; - - EXTRACT_WORDS(hx, lx, x); - EXTRACT_WORDS(hy, ly, y); - ix = hx & 0x7fffffff; - iy = hy & 0x7fffffff; - - /* y==zero: x**0 = 1 */ - if ((iy | ly) == 0) - return one; - - /* +-NaN return x+y */ - if (ix > 0x7ff00000 || ((ix == 0x7ff00000) && (lx != 0)) || - iy > 0x7ff00000 || ((iy == 0x7ff00000) && (ly != 0))) - return x + y; - - /* determine if y is an odd int when x < 0 - * yisint = 0 ... y is not an integer - * yisint = 1 ... y is an odd int - * yisint = 2 ... y is an even int - */ - yisint = 0; - if (hx < 0) { - if (iy >= 0x43400000) - yisint = 2; /* even integer y */ - else if (iy >= 0x3ff00000) { - k = (iy >> 20) - 0x3ff; /* exponent */ - if (k > 20) { - j = ly >> (52 - k); - if ((u_int32_t) (j << (52 - k)) == ly) - yisint = 2 - (j & 1); - } else if (ly == 0) { - j = iy >> (20 - k); - if ((j << (20 - k)) == iy) - yisint = 2 - (j & 1); - } - } - } - - /* special value of y */ - if (ly == 0) { - if (iy == 0x7ff00000) { /* y is +-inf */ - if (((ix - 0x3ff00000) | lx) == 0) - return y - y; /* inf**+-1 is NaN */ - else if (ix >= 0x3ff00000) /* (|x|>1)**+-inf = inf,0 */ - return (hy >= 0) ? y : zero; - else /* (|x|<1)**-,+inf = inf,0 */ - return (hy < 0) ? -y : zero; - } - if (iy == 0x3ff00000) { /* y is +-1 */ - if (hy < 0) - return one / x; - else - return x; - } - if (hy == 0x40000000) - return x * x; /* y is 2 */ - if (hy == 0x3fe00000) { /* y is 0.5 */ - if (hx >= 0) /* x >= +0 */ - return __ieee754_sqrt(x); - } - } - - ax = x < 0 ? -x : x; /*fabs(x); */ - /* special value of x */ - if (lx == 0) { - if (ix == 0x7ff00000 || ix == 0 || ix == 0x3ff00000) { - z = ax; /*x is +-0,+-inf,+-1 */ - if (hy < 0) - z = one / z; /* z = (1/|x|) */ - if (hx < 0) { - if (((ix - 0x3ff00000) | yisint) == 0) { - z = (z - z) / (z - z); /* (-1)**non-int is NaN */ - } else if (yisint == 1) - z = -z; /* (x<0)**odd = -(|x|**odd) */ - } - return z; - } - } - - /* (x<0)**(non-int) is NaN */ - if (((((u_int32_t) hx >> 31) - 1) | yisint) == 0) - return (x - x) / (x - x); - - /* |y| is huge */ - if (iy > 0x41e00000) { /* if |y| > 2**31 */ - if (iy > 0x43f00000) { /* if |y| > 2**64, must o/uflow */ - if (ix <= 0x3fefffff) - return (hy < 0) ? huge * huge : tiny * tiny; - if (ix >= 0x3ff00000) - return (hy > 0) ? huge * huge : tiny * tiny; - } - /* over/underflow if x is not close to one */ - if (ix < 0x3fefffff) - return (hy < 0) ? huge * huge : tiny * tiny; - if (ix > 0x3ff00000) - return (hy > 0) ? huge * huge : tiny * tiny; - /* now |1-x| is tiny <= 2**-20, suffice to compute - log(x) by x-x^2/2+x^3/3-x^4/4 */ - t = ax - 1; /* t has 20 trailing zeros */ - w = (t * t) * (0.5 - t * (0.3333333333333333333333 - t * 0.25)); - u = ivln2_h * t; /* ivln2_h has 21 sig. bits */ - v = t * ivln2_l - w * ivln2; - t1 = u + v; - SET_LOW_WORD(t1, 0); - t2 = v - (t1 - u); - } else { - double s2, s_h, s_l, t_h, t_l; - n = 0; - /* take care subnormal number */ - if (ix < 0x00100000) { - ax *= two53; - n -= 53; - GET_HIGH_WORD(ix, ax); - } - n += ((ix) >> 20) - 0x3ff; - j = ix & 0x000fffff; - /* determine interval */ - ix = j | 0x3ff00000; /* normalize ix */ - if (j <= 0x3988E) - k = 0; /* |x|<sqrt(3/2) */ - else if (j < 0xBB67A) - k = 1; /* |x|<sqrt(3) */ - else { - k = 0; - n += 1; - ix -= 0x00100000; - } - SET_HIGH_WORD(ax, ix); - - /* compute s = s_h+s_l = (x-1)/(x+1) or (x-1.5)/(x+1.5) */ - u = ax - bp[k]; /* bp[0]=1.0, bp[1]=1.5 */ - v = one / (ax + bp[k]); - s = u * v; - s_h = s; - SET_LOW_WORD(s_h, 0); - /* t_h=ax+bp[k] High */ - t_h = zero; - SET_HIGH_WORD(t_h, ((ix >> 1) | 0x20000000) + 0x00080000 + (k << 18)); - t_l = ax - (t_h - bp[k]); - s_l = v * ((u - s_h * t_h) - s_h * t_l); - /* compute log(ax) */ - s2 = s * s; - r = s2 * s2 * (L1 + - s2 * (L2 + - s2 * (L3 + s2 * (L4 + s2 * (L5 + s2 * L6))))); - r += s_l * (s_h + s); - s2 = s_h * s_h; - t_h = 3.0 + s2 + r; - SET_LOW_WORD(t_h, 0); - t_l = r - ((t_h - 3.0) - s2); - /* u+v = s*(1+...) */ - u = s_h * t_h; - v = s_l * t_h + t_l * s; - /* 2/(3log2)*(s+...) */ - p_h = u + v; - SET_LOW_WORD(p_h, 0); - p_l = v - (p_h - u); - z_h = cp_h * p_h; /* cp_h+cp_l = 2/(3*log2) */ - z_l = cp_l * p_h + p_l * cp + dp_l[k]; - /* log2(ax) = (s+..)*2/(3*log2) = n + dp_h + z_h + z_l */ - t = (double) n; - t1 = (((z_h + z_l) + dp_h[k]) + t); - SET_LOW_WORD(t1, 0); - t2 = z_l - (((t1 - t) - dp_h[k]) - z_h); - } - - s = one; /* s (sign of result -ve**odd) = -1 else = 1 */ - if (((((u_int32_t) hx >> 31) - 1) | (yisint - 1)) == 0) - s = -one; /* (-ve)**(odd int) */ - - /* split up y into y1+y2 and compute (y1+y2)*(t1+t2) */ - y1 = y; - SET_LOW_WORD(y1, 0); - p_l = (y - y1) * t1 + y * t2; - p_h = y1 * t1; - z = p_l + p_h; - EXTRACT_WORDS(j, i, z); - if (j >= 0x40900000) { /* z >= 1024 */ - if (((j - 0x40900000) | i) != 0) /* if z > 1024 */ - return s * huge * huge; /* overflow */ - else { - if (p_l + ovt > z - p_h) - return s * huge * huge; /* overflow */ - } - } else if ((j & 0x7fffffff) >= 0x4090cc00) { /* z <= -1075 */ - if (((j - 0xc090cc00) | i) != 0) /* z < -1075 */ - return s * tiny * tiny; /* underflow */ - else { - if (p_l <= z - p_h) - return s * tiny * tiny; /* underflow */ - } - } - /* - * compute 2**(p_h+p_l) - */ - i = j & 0x7fffffff; - k = (i >> 20) - 0x3ff; - n = 0; - if (i > 0x3fe00000) { /* if |z| > 0.5, set n = [z+0.5] */ - n = j + (0x00100000 >> (k + 1)); - k = ((n & 0x7fffffff) >> 20) - 0x3ff; /* new k for n */ - t = zero; - SET_HIGH_WORD(t, n & ~(0x000fffff >> k)); - n = ((n & 0x000fffff) | 0x00100000) >> (20 - k); - if (j < 0) - n = -n; - p_h -= t; - } - t = p_l + p_h; - SET_LOW_WORD(t, 0); - u = t * lg2_h; - v = (p_l - (t - p_h)) * lg2 + t * lg2_l; - z = u + v; - w = v - (z - u); - t = z * z; - t1 = z - t * (P1 + t * (P2 + t * (P3 + t * (P4 + t * P5)))); - r = (z * t1) / (t1 - two) - (w + z * w); - z = one - (r - z); - GET_HIGH_WORD(j, z); - j += (n << 20); - if ((j >> 20) <= 0) - z = SDL_NAME(scalbn) (z, n); /* subnormal output */ - else - SET_HIGH_WORD(z, j); - return s * z; -} - -/* vi: set ts=4 sw=4 expandtab: */
--- a/src/video/e_sqrt.h Mon Sep 15 05:14:11 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,516 +0,0 @@ -/* @(#)e_sqrt.c 5.1 93/09/24 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunPro, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -#if defined(LIBM_SCCS) && !defined(lint) -static char rcsid[] = "$NetBSD: e_sqrt.c,v 1.8 1995/05/10 20:46:17 jtc Exp $"; -#endif - -/* __ieee754_sqrt(x) - * Return correctly rounded sqrt. - * ------------------------------------------ - * | Use the hardware sqrt if you have one | - * ------------------------------------------ - * Method: - * Bit by bit method using integer arithmetic. (Slow, but portable) - * 1. Normalization - * Scale x to y in [1,4) with even powers of 2: - * find an integer k such that 1 <= (y=x*2^(2k)) < 4, then - * sqrt(x) = 2^k * sqrt(y) - * 2. Bit by bit computation - * Let q = sqrt(y) truncated to i bit after binary point (q = 1), - * i 0 - * i+1 2 - * s = 2*q , and y = 2 * ( y - q ). (1) - * i i i i - * - * To compute q from q , one checks whether - * i+1 i - * - * -(i+1) 2 - * (q + 2 ) <= y. (2) - * i - * -(i+1) - * If (2) is false, then q = q ; otherwise q = q + 2 . - * i+1 i i+1 i - * - * With some algebric manipulation, it is not difficult to see - * that (2) is equivalent to - * -(i+1) - * s + 2 <= y (3) - * i i - * - * The advantage of (3) is that s and y can be computed by - * i i - * the following recurrence formula: - * if (3) is false - * - * s = s , y = y ; (4) - * i+1 i i+1 i - * - * otherwise, - * -i -(i+1) - * s = s + 2 , y = y - s - 2 (5) - * i+1 i i+1 i i - * - * One may easily use induction to prove (4) and (5). - * Note. Since the left hand side of (3) contain only i+2 bits, - * it does not necessary to do a full (53-bit) comparison - * in (3). - * 3. Final rounding - * After generating the 53 bits result, we compute one more bit. - * Together with the remainder, we can decide whether the - * result is exact, bigger than 1/2ulp, or less than 1/2ulp - * (it will never equal to 1/2ulp). - * The rounding mode can be detected by checking whether - * huge + tiny is equal to huge, and whether huge - tiny is - * equal to huge for some floating point number "huge" and "tiny". - * - * Special cases: - * sqrt(+-0) = +-0 ... exact - * sqrt(inf) = inf - * sqrt(-ve) = NaN ... with invalid signal - * sqrt(NaN) = NaN ... with invalid signal for signaling NaN - * - * Other methods : see the appended file at the end of the program below. - *--------------- - */ - -/*#include "math.h"*/ -#include "math_private.h" - -#ifdef __STDC__ -double SDL_NAME(copysign) (double x, double y) -#else -double SDL_NAME(copysign) (x, y) - double - x, - y; -#endif -{ - u_int32_t hx, hy; - GET_HIGH_WORD(hx, x); - GET_HIGH_WORD(hy, y); - SET_HIGH_WORD(x, (hx & 0x7fffffff) | (hy & 0x80000000)); - return x; -} - -#ifdef __STDC__ -double SDL_NAME(scalbn) (double x, int n) -#else -double SDL_NAME(scalbn) (x, n) - double - x; - int - n; -#endif -{ - int32_t k, hx, lx; - EXTRACT_WORDS(hx, lx, x); - k = (hx & 0x7ff00000) >> 20; /* extract exponent */ - if (k == 0) { /* 0 or subnormal x */ - if ((lx | (hx & 0x7fffffff)) == 0) - return x; /* +-0 */ - x *= two54; - GET_HIGH_WORD(hx, x); - k = ((hx & 0x7ff00000) >> 20) - 54; - if (n < -50000) - return tiny * x; /*underflow */ - } - if (k == 0x7ff) - return x + x; /* NaN or Inf */ - k = k + n; - if (k > 0x7fe) - return huge * SDL_NAME(copysign) (huge, x); /* overflow */ - if (k > 0) { /* normal result */ - SET_HIGH_WORD(x, (hx & 0x800fffff) | (k << 20)); - return x; - } - if (k <= -54) { - if (n > 50000) /* in case integer overflow in n+k */ - return huge * SDL_NAME(copysign) (huge, x); /*overflow */ - else - return tiny * SDL_NAME(copysign) (tiny, x); /*underflow */ - } - k += 54; /* subnormal result */ - SET_HIGH_WORD(x, (hx & 0x800fffff) | (k << 20)); - return x * twom54; -} - -#ifdef __STDC__ -double -__ieee754_sqrt(double x) -#else -double -__ieee754_sqrt(x) - double x; -#endif -{ - double z; - int32_t sign = (int) 0x80000000; - int32_t ix0, s0, q, m, t, i; - u_int32_t r, t1, s1, ix1, q1; - - EXTRACT_WORDS(ix0, ix1, x); - - /* take care of Inf and NaN */ - if ((ix0 & 0x7ff00000) == 0x7ff00000) { - return x * x + x; /* sqrt(NaN)=NaN, sqrt(+inf)=+inf - sqrt(-inf)=sNaN */ - } - /* take care of zero */ - if (ix0 <= 0) { - if (((ix0 & (~sign)) | ix1) == 0) - return x; /* sqrt(+-0) = +-0 */ - else if (ix0 < 0) - return (x - x) / (x - x); /* sqrt(-ve) = sNaN */ - } - /* normalize x */ - m = (ix0 >> 20); - if (m == 0) { /* subnormal x */ - while (ix0 == 0) { - m -= 21; - ix0 |= (ix1 >> 11); - ix1 <<= 21; - } - for (i = 0; (ix0 & 0x00100000) == 0; i++) - ix0 <<= 1; - m -= i - 1; - ix0 |= (ix1 >> (32 - i)); - ix1 <<= i; - } - m -= 1023; /* unbias exponent */ - ix0 = (ix0 & 0x000fffff) | 0x00100000; - if (m & 1) { /* odd m, double x to make it even */ - ix0 += ix0 + ((ix1 & sign) >> 31); - ix1 += ix1; - } - m >>= 1; /* m = [m/2] */ - - /* generate sqrt(x) bit by bit */ - ix0 += ix0 + ((ix1 & sign) >> 31); - ix1 += ix1; - q = q1 = s0 = s1 = 0; /* [q,q1] = sqrt(x) */ - r = 0x00200000; /* r = moving bit from right to left */ - - while (r != 0) { - t = s0 + r; - if (t <= ix0) { - s0 = t + r; - ix0 -= t; - q += r; - } - ix0 += ix0 + ((ix1 & sign) >> 31); - ix1 += ix1; - r >>= 1; - } - - r = sign; - while (r != 0) { - t1 = s1 + r; - t = s0; - if ((t < ix0) || ((t == ix0) && (t1 <= ix1))) { - s1 = t1 + r; - if (((int32_t) (t1 & sign) == sign) && (s1 & sign) == 0) - s0 += 1; - ix0 -= t; - if (ix1 < t1) - ix0 -= 1; - ix1 -= t1; - q1 += r; - } - ix0 += ix0 + ((ix1 & sign) >> 31); - ix1 += ix1; - r >>= 1; - } - - /* use floating add to find out rounding direction */ - if ((ix0 | ix1) != 0) { - z = one - tiny; /* trigger inexact flag */ - if (z >= one) { - z = one + tiny; - if (q1 == (u_int32_t) 0xffffffff) { - q1 = 0; - q += 1; - } else if (z > one) { - if (q1 == (u_int32_t) 0xfffffffe) - q += 1; - q1 += 2; - } else - q1 += (q1 & 1); - } - } - ix0 = (q >> 1) + 0x3fe00000; - ix1 = q1 >> 1; - if ((q & 1) == 1) - ix1 |= sign; - ix0 += (m << 20); - INSERT_WORDS(z, ix0, ix1); - return z; -} - -/* -Other methods (use floating-point arithmetic) -------------- -(This is a copy of a drafted paper by Prof W. Kahan -and K.C. Ng, written in May, 1986) - - Two algorithms are given here to implement sqrt(x) - (IEEE double precision arithmetic) in software. - Both supply sqrt(x) correctly rounded. The first algorithm (in - Section A) uses newton iterations and involves four divisions. - The second one uses reciproot iterations to avoid division, but - requires more multiplications. Both algorithms need the ability - to chop results of arithmetic operations instead of round them, - and the INEXACT flag to indicate when an arithmetic operation - is executed exactly with no roundoff error, all part of the - standard (IEEE 754-1985). The ability to perform shift, add, - subtract and logical AND operations upon 32-bit words is needed - too, though not part of the standard. - -A. sqrt(x) by Newton Iteration - - (1) Initial approximation - - Let x0 and x1 be the leading and the trailing 32-bit words of - a floating point number x (in IEEE double format) respectively - - 1 11 52 ...widths - ------------------------------------------------------ - x: |s| e | f | - ------------------------------------------------------ - msb lsb msb lsb ...order - - - ------------------------ ------------------------ - x0: |s| e | f1 | x1: | f2 | - ------------------------ ------------------------ - - By performing shifts and subtracts on x0 and x1 (both regarded - as integers), we obtain an 8-bit approximation of sqrt(x) as - follows. - - k := (x0>>1) + 0x1ff80000; - y0 := k - T1[31&(k>>15)]. ... y ~ sqrt(x) to 8 bits - Here k is a 32-bit integer and T1[] is an integer array containing - correction terms. Now magically the floating value of y (y's - leading 32-bit word is y0, the value of its trailing word is 0) - approximates sqrt(x) to almost 8-bit. - - Value of T1: - static int T1[32]= { - 0, 1024, 3062, 5746, 9193, 13348, 18162, 23592, - 29598, 36145, 43202, 50740, 58733, 67158, 75992, 85215, - 83599, 71378, 60428, 50647, 41945, 34246, 27478, 21581, - 16499, 12183, 8588, 5674, 3403, 1742, 661, 130,}; - - (2) Iterative refinement - - Apply Heron's rule three times to y, we have y approximates - sqrt(x) to within 1 ulp (Unit in the Last Place): - - y := (y+x/y)/2 ... almost 17 sig. bits - y := (y+x/y)/2 ... almost 35 sig. bits - y := y-(y-x/y)/2 ... within 1 ulp - - - Remark 1. - Another way to improve y to within 1 ulp is: - - y := (y+x/y) ... almost 17 sig. bits to 2*sqrt(x) - y := y - 0x00100006 ... almost 18 sig. bits to sqrt(x) - - 2 - (x-y )*y - y := y + 2* ---------- ...within 1 ulp - 2 - 3y + x - - - This formula has one division fewer than the one above; however, - it requires more multiplications and additions. Also x must be - scaled in advance to avoid spurious overflow in evaluating the - expression 3y*y+x. Hence it is not recommended uless division - is slow. If division is very slow, then one should use the - reciproot algorithm given in section B. - - (3) Final adjustment - - By twiddling y's last bit it is possible to force y to be - correctly rounded according to the prevailing rounding mode - as follows. Let r and i be copies of the rounding mode and - inexact flag before entering the square root program. Also we - use the expression y+-ulp for the next representable floating - numbers (up and down) of y. Note that y+-ulp = either fixed - point y+-1, or multiply y by nextafter(1,+-inf) in chopped - mode. - - I := FALSE; ... reset INEXACT flag I - R := RZ; ... set rounding mode to round-toward-zero - z := x/y; ... chopped quotient, possibly inexact - If(not I) then { ... if the quotient is exact - if(z=y) { - I := i; ... restore inexact flag - R := r; ... restore rounded mode - return sqrt(x):=y. - } else { - z := z - ulp; ... special rounding - } - } - i := TRUE; ... sqrt(x) is inexact - If (r=RN) then z=z+ulp ... rounded-to-nearest - If (r=RP) then { ... round-toward-+inf - y = y+ulp; z=z+ulp; - } - y := y+z; ... chopped sum - y0:=y0-0x00100000; ... y := y/2 is correctly rounded. - I := i; ... restore inexact flag - R := r; ... restore rounded mode - return sqrt(x):=y. - - (4) Special cases - - Square root of +inf, +-0, or NaN is itself; - Square root of a negative number is NaN with invalid signal. - - -B. sqrt(x) by Reciproot Iteration - - (1) Initial approximation - - Let x0 and x1 be the leading and the trailing 32-bit words of - a floating point number x (in IEEE double format) respectively - (see section A). By performing shifs and subtracts on x0 and y0, - we obtain a 7.8-bit approximation of 1/sqrt(x) as follows. - - k := 0x5fe80000 - (x0>>1); - y0:= k - T2[63&(k>>14)]. ... y ~ 1/sqrt(x) to 7.8 bits - - Here k is a 32-bit integer and T2[] is an integer array - containing correction terms. Now magically the floating - value of y (y's leading 32-bit word is y0, the value of - its trailing word y1 is set to zero) approximates 1/sqrt(x) - to almost 7.8-bit. - - Value of T2: - static int T2[64]= { - 0x1500, 0x2ef8, 0x4d67, 0x6b02, 0x87be, 0xa395, 0xbe7a, 0xd866, - 0xf14a, 0x1091b,0x11fcd,0x13552,0x14999,0x15c98,0x16e34,0x17e5f, - 0x18d03,0x19a01,0x1a545,0x1ae8a,0x1b5c4,0x1bb01,0x1bfde,0x1c28d, - 0x1c2de,0x1c0db,0x1ba73,0x1b11c,0x1a4b5,0x1953d,0x18266,0x16be0, - 0x1683e,0x179d8,0x18a4d,0x19992,0x1a789,0x1b445,0x1bf61,0x1c989, - 0x1d16d,0x1d77b,0x1dddf,0x1e2ad,0x1e5bf,0x1e6e8,0x1e654,0x1e3cd, - 0x1df2a,0x1d635,0x1cb16,0x1be2c,0x1ae4e,0x19bde,0x1868e,0x16e2e, - 0x1527f,0x1334a,0x11051,0xe951, 0xbe01, 0x8e0d, 0x5924, 0x1edd,}; - - (2) Iterative refinement - - Apply Reciproot iteration three times to y and multiply the - result by x to get an approximation z that matches sqrt(x) - to about 1 ulp. To be exact, we will have - -1ulp < sqrt(x)-z<1.0625ulp. - - ... set rounding mode to Round-to-nearest - y := y*(1.5-0.5*x*y*y) ... almost 15 sig. bits to 1/sqrt(x) - y := y*((1.5-2^-30)+0.5*x*y*y)... about 29 sig. bits to 1/sqrt(x) - ... special arrangement for better accuracy - z := x*y ... 29 bits to sqrt(x), with z*y<1 - z := z + 0.5*z*(1-z*y) ... about 1 ulp to sqrt(x) - - Remark 2. The constant 1.5-2^-30 is chosen to bias the error so that - (a) the term z*y in the final iteration is always less than 1; - (b) the error in the final result is biased upward so that - -1 ulp < sqrt(x) - z < 1.0625 ulp - instead of |sqrt(x)-z|<1.03125ulp. - - (3) Final adjustment - - By twiddling y's last bit it is possible to force y to be - correctly rounded according to the prevailing rounding mode - as follows. Let r and i be copies of the rounding mode and - inexact flag before entering the square root program. Also we - use the expression y+-ulp for the next representable floating - numbers (up and down) of y. Note that y+-ulp = either fixed - point y+-1, or multiply y by nextafter(1,+-inf) in chopped - mode. - - R := RZ; ... set rounding mode to round-toward-zero - switch(r) { - case RN: ... round-to-nearest - if(x<= z*(z-ulp)...chopped) z = z - ulp; else - if(x<= z*(z+ulp)...chopped) z = z; else z = z+ulp; - break; - case RZ:case RM: ... round-to-zero or round-to--inf - R:=RP; ... reset rounding mod to round-to-+inf - if(x<z*z ... rounded up) z = z - ulp; else - if(x>=(z+ulp)*(z+ulp) ...rounded up) z = z+ulp; - break; - case RP: ... round-to-+inf - if(x>(z+ulp)*(z+ulp)...chopped) z = z+2*ulp; else - if(x>z*z ...chopped) z = z+ulp; - break; - } - - Remark 3. The above comparisons can be done in fixed point. For - example, to compare x and w=z*z chopped, it suffices to compare - x1 and w1 (the trailing parts of x and w), regarding them as - two's complement integers. - - ...Is z an exact square root? - To determine whether z is an exact square root of x, let z1 be the - trailing part of z, and also let x0 and x1 be the leading and - trailing parts of x. - - If ((z1&0x03ffffff)!=0) ... not exact if trailing 26 bits of z!=0 - I := 1; ... Raise Inexact flag: z is not exact - else { - j := 1 - [(x0>>20)&1] ... j = logb(x) mod 2 - k := z1 >> 26; ... get z's 25-th and 26-th - fraction bits - I := i or (k&j) or ((k&(j+j+1))!=(x1&3)); - } - R:= r ... restore rounded mode - return sqrt(x):=z. - - If multiplication is cheaper then the foregoing red tape, the - Inexact flag can be evaluated by - - I := i; - I := (z*z!=x) or I. - - Note that z*z can overwrite I; this value must be sensed if it is - True. - - Remark 4. If z*z = x exactly, then bit 25 to bit 0 of z1 must be - zero. - - -------------------- - z1: | f2 | - -------------------- - bit 31 bit 0 - - Further more, bit 27 and 26 of z1, bit 0 and 1 of x1, and the odd - or even of logb(x) have the following relations: - - ------------------------------------------------- - bit 27,26 of z1 bit 1,0 of x1 logb(x) - ------------------------------------------------- - 00 00 odd and even - 01 01 even - 10 10 odd - 10 00 even - 11 01 even - ------------------------------------------------- - - (4) Special cases (see (4) of Section A). - - */ -/* vi: set ts=4 sw=4 expandtab: */
--- a/src/video/math_private.h Mon Sep 15 05:14:11 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,171 +0,0 @@ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunPro, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* - * from: @(#)fdlibm.h 5.1 93/09/24 - * $Id$ - */ - -#ifndef _MATH_PRIVATE_H_ -#define _MATH_PRIVATE_H_ - -#include "SDL_name.h" -#include "SDL_endian.h" - -#define huge really_big /* huge is a reserved keyword in VC++ 6.0 */ -#define u_int32_t uint32_t - -/* The original fdlibm code used statements like: - n0 = ((*(int*)&one)>>29)^1; * index of high word * - ix0 = *(n0+(int*)&x); * high word of x * - ix1 = *((1-n0)+(int*)&x); * low word of x * - to dig two 32 bit words out of the 64 bit IEEE floating point - value. That is non-ANSI, and, moreover, the gcc instruction - scheduler gets it wrong. We instead use the following macros. - Unlike the original code, we determine the endianness at compile - time, not at run time; I don't see much benefit to selecting - endianness at run time. */ - -/* A union which permits us to convert between a double and two 32 bit - ints. */ - -/* - * Math on arm is special: - * For FPA, float words are always big-endian. - * For VFP, floats words follow the memory system mode. - */ - -#if (SDL_BYTEORDER == SDL_BIG_ENDIAN) || \ - (!defined(__VFP_FP__) && (defined(__arm__) || defined(__thumb__))) - -typedef union -{ - double value; - struct - { - u_int32_t msw; - u_int32_t lsw; - } parts; -} ieee_double_shape_type; - -#else - -typedef union -{ - double value; - struct - { - u_int32_t lsw; - u_int32_t msw; - } parts; -} ieee_double_shape_type; - -#endif - -/* Get two 32 bit ints from a double. */ - -#define EXTRACT_WORDS(ix0,ix1,d) \ -do { \ - ieee_double_shape_type ew_u; \ - ew_u.value = (d); \ - (ix0) = ew_u.parts.msw; \ - (ix1) = ew_u.parts.lsw; \ -} while (0) - -/* Get the more significant 32 bit int from a double. */ - -#define GET_HIGH_WORD(i,d) \ -do { \ - ieee_double_shape_type gh_u; \ - gh_u.value = (d); \ - (i) = gh_u.parts.msw; \ -} while (0) - -/* Get the less significant 32 bit int from a double. */ - -#define GET_LOW_WORD(i,d) \ -do { \ - ieee_double_shape_type gl_u; \ - gl_u.value = (d); \ - (i) = gl_u.parts.lsw; \ -} while (0) - -/* Set a double from two 32 bit ints. */ - -#define INSERT_WORDS(d,ix0,ix1) \ -do { \ - ieee_double_shape_type iw_u; \ - iw_u.parts.msw = (ix0); \ - iw_u.parts.lsw = (ix1); \ - (d) = iw_u.value; \ -} while (0) - -/* Set the more significant 32 bits of a double from an int. */ - -#define SET_HIGH_WORD(d,v) \ -do { \ - ieee_double_shape_type sh_u; \ - sh_u.value = (d); \ - sh_u.parts.msw = (v); \ - (d) = sh_u.value; \ -} while (0) - -/* Set the less significant 32 bits of a double from an int. */ - -#define SET_LOW_WORD(d,v) \ -do { \ - ieee_double_shape_type sl_u; \ - sl_u.value = (d); \ - sl_u.parts.lsw = (v); \ - (d) = sl_u.value; \ -} while (0) - -/* A union which permits us to convert between a float and a 32 bit - int. */ - -typedef union -{ - float value; - u_int32_t word; -} ieee_float_shape_type; - -/* Get a 32 bit int from a float. */ - -#define GET_FLOAT_WORD(i,d) \ -do { \ - ieee_float_shape_type gf_u; \ - gf_u.value = (d); \ - (i) = gf_u.word; \ -} while (0) - -/* Set a float from a 32 bit int. */ - -#define SET_FLOAT_WORD(d,i) \ -do { \ - ieee_float_shape_type sf_u; \ - sf_u.word = (i); \ - (d) = sf_u.value; \ -} while (0) - - -#ifdef __STDC__ -static const double -#else -static double -#endif - zero = 0.0, one = 1.0, two = 2.0, two53 = 9007199254740992.0, /* 0x43400000, 0x00000000 */ - two54 = 1.80143985094819840000e+16, /* 0x43500000, 0x00000000 */ - twom54 = 5.55111512312578270212e-17, /* 0x3C900000, 0x00000000 */ - huge = 1.0e+300, tiny = 1.0e-300; - -#endif /* _MATH_PRIVATE_H_ */ - -/* vi: set ts=4 sw=4 expandtab: */