| OLD | NEW |
| 1 // The following is adapted from fdlibm (http://www.netlib.org/fdlibm), | 1 // The following is adapted from fdlibm (http://www.netlib.org/fdlibm), |
| 2 // | 2 // |
| 3 // ==================================================== | 3 // ==================================================== |
| 4 // Copyright (C) 1993-2004 by Sun Microsystems, Inc. All rights reserved. | 4 // Copyright (C) 1993-2004 by Sun Microsystems, Inc. All rights reserved. |
| 5 // | 5 // |
| 6 // Developed at SunSoft, a Sun Microsystems, Inc. business. | 6 // Developed at SunSoft, a Sun Microsystems, Inc. business. |
| 7 // Permission to use, copy, modify, and distribute this | 7 // Permission to use, copy, modify, and distribute this |
| 8 // software is freely granted, provided that this notice | 8 // software is freely granted, provided that this notice |
| 9 // is preserved. | 9 // is preserved. |
| 10 // ==================================================== | 10 // ==================================================== |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 134 // | x | | 134 // | x | |
| 135 // | 135 // |
| 136 // 3. ieee_sin(X+Y) = ieee_sin(X) + sin'(X')*Y | 136 // 3. ieee_sin(X+Y) = ieee_sin(X) + sin'(X')*Y |
| 137 // ~ ieee_sin(X) + (1-X*X/2)*Y | 137 // ~ ieee_sin(X) + (1-X*X/2)*Y |
| 138 // For better accuracy, let | 138 // For better accuracy, let |
| 139 // 3 2 2 2 2 | 139 // 3 2 2 2 2 |
| 140 // r = X *(S2+X *(S3+X *(S4+X *(S5+X *S6)))) | 140 // r = X *(S2+X *(S3+X *(S4+X *(S5+X *S6)))) |
| 141 // then 3 2 | 141 // then 3 2 |
| 142 // sin(x) = X + (S1*X + (X *(r-Y/2)+Y)) | 142 // sin(x) = X + (S1*X + (X *(r-Y/2)+Y)) |
| 143 // | 143 // |
| 144 macro KSIN(x) | 144 const S1 = -1.66666666666666324348e-01; |
| 145 kMath[7+x] | 145 const S2 = 8.33333333332248946124e-03; |
| 146 endmacro | 146 const S3 = -1.98412698298579493134e-04; |
| 147 const S4 = 2.75573137070700676789e-06; |
| 148 const S5 = -2.50507602534068634195e-08; |
| 149 const S6 = 1.58969099521155010221e-10; |
| 147 | 150 |
| 148 macro RETURN_KERNELSIN(X, Y, SIGN) | 151 macro RETURN_KERNELSIN(X, Y, SIGN) |
| 149 var z = X * X; | 152 var z = X * X; |
| 150 var v = z * X; | 153 var v = z * X; |
| 151 var r = KSIN(1) + z * (KSIN(2) + z * (KSIN(3) + | 154 var r = S2 + z * (S3 + z * (S4 + z * (S5 + z * S6))); |
| 152 z * (KSIN(4) + z * KSIN(5)))); | 155 return (X - ((z * (0.5 * Y - v * r) - Y) - v * S1)) SIGN; |
| 153 return (X - ((z * (0.5 * Y - v * r) - Y) - v * KSIN(0))) SIGN; | |
| 154 endmacro | 156 endmacro |
| 155 | 157 |
| 156 // __kernel_cos(X, Y) | 158 // __kernel_cos(X, Y) |
| 157 // kernel cos function on [-pi/4, pi/4], pi/4 ~ 0.785398164 | 159 // kernel cos function on [-pi/4, pi/4], pi/4 ~ 0.785398164 |
| 158 // Input X is assumed to be bounded by ~pi/4 in magnitude. | 160 // Input X is assumed to be bounded by ~pi/4 in magnitude. |
| 159 // Input Y is the tail of X so that x = X + Y. | 161 // Input Y is the tail of X so that x = X + Y. |
| 160 // | 162 // |
| 161 // Algorithm | 163 // Algorithm |
| 162 // 1. Since ieee_cos(-x) = ieee_cos(x), we need only to consider positive x. | 164 // 1. Since ieee_cos(-x) = ieee_cos(x), we need only to consider positive x. |
| 163 // 2. ieee_cos(x) is approximated by a polynomial of degree 14 on | 165 // 2. ieee_cos(x) is approximated by a polynomial of degree 14 on |
| (...skipping 14 matching lines...) Expand all Loading... |
| 178 // a correction term is necessary in ieee_cos(x) and hence | 180 // a correction term is necessary in ieee_cos(x) and hence |
| 179 // cos(X+Y) = 1 - (X*X/2 - (r - X*Y)) | 181 // cos(X+Y) = 1 - (X*X/2 - (r - X*Y)) |
| 180 // For better accuracy when x > 0.3, let qx = |x|/4 with | 182 // For better accuracy when x > 0.3, let qx = |x|/4 with |
| 181 // the last 32 bits mask off, and if x > 0.78125, let qx = 0.28125. | 183 // the last 32 bits mask off, and if x > 0.78125, let qx = 0.28125. |
| 182 // Then | 184 // Then |
| 183 // cos(X+Y) = (1-qx) - ((X*X/2-qx) - (r-X*Y)). | 185 // cos(X+Y) = (1-qx) - ((X*X/2-qx) - (r-X*Y)). |
| 184 // Note that 1-qx and (X*X/2-qx) is EXACT here, and the | 186 // Note that 1-qx and (X*X/2-qx) is EXACT here, and the |
| 185 // magnitude of the latter is at least a quarter of X*X/2, | 187 // magnitude of the latter is at least a quarter of X*X/2, |
| 186 // thus, reducing the rounding error in the subtraction. | 188 // thus, reducing the rounding error in the subtraction. |
| 187 // | 189 // |
| 188 macro KCOS(x) | 190 const C1 = 4.16666666666666019037e-02; |
| 189 kMath[13+x] | 191 const C2 = -1.38888888888741095749e-03; |
| 190 endmacro | 192 const C3 = 2.48015872894767294178e-05; |
| 193 const C4 = -2.75573143513906633035e-07; |
| 194 const C5 = 2.08757232129817482790e-09; |
| 195 const C6 = -1.13596475577881948265e-11; |
| 191 | 196 |
| 192 macro RETURN_KERNELCOS(X, Y, SIGN) | 197 macro RETURN_KERNELCOS(X, Y, SIGN) |
| 193 var ix = %_DoubleHi(X) & 0x7fffffff; | 198 var ix = %_DoubleHi(X) & 0x7fffffff; |
| 194 var z = X * X; | 199 var z = X * X; |
| 195 var r = z * (KCOS(0) + z * (KCOS(1) + z * (KCOS(2)+ | 200 var r = z * (C1 + z * (C2 + z * (C3 + z * (C4 + z * (C5 + z * C6))))); |
| 196 z * (KCOS(3) + z * (KCOS(4) + z * KCOS(5)))))); | |
| 197 if (ix < 0x3fd33333) { // |x| ~< 0.3 | 201 if (ix < 0x3fd33333) { // |x| ~< 0.3 |
| 198 return (1 - (0.5 * z - (z * r - X * Y))) SIGN; | 202 return (1 - (0.5 * z - (z * r - X * Y))) SIGN; |
| 199 } else { | 203 } else { |
| 200 var qx; | 204 var qx; |
| 201 if (ix > 0x3fe90000) { // |x| > 0.78125 | 205 if (ix > 0x3fe90000) { // |x| > 0.78125 |
| 202 qx = 0.28125; | 206 qx = 0.28125; |
| 203 } else { | 207 } else { |
| 204 qx = %_ConstructDouble(%_DoubleHi(0.25 * X), 0); | 208 qx = %_ConstructDouble(%_DoubleHi(0.25 * X), 0); |
| 205 } | 209 } |
| 206 var hz = 0.5 * z - qx; | 210 var hz = 0.5 * z - qx; |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 329 var sign = (n & 2) - 1; | 333 var sign = (n & 2) - 1; |
| 330 RETURN_KERNELSIN(y0, y1, * sign); | 334 RETURN_KERNELSIN(y0, y1, * sign); |
| 331 } else { | 335 } else { |
| 332 var sign = 1 - (n & 2); | 336 var sign = 1 - (n & 2); |
| 333 RETURN_KERNELCOS(y0, y1, * sign); | 337 RETURN_KERNELCOS(y0, y1, * sign); |
| 334 } | 338 } |
| 335 } | 339 } |
| 336 | 340 |
| 337 // ECMA 262 - 15.8.2.16 | 341 // ECMA 262 - 15.8.2.16 |
| 338 function MathSin(x) { | 342 function MathSin(x) { |
| 339 x = x * 1; // Convert to number. | 343 x = +x; // Convert to number. |
| 340 if ((%_DoubleHi(x) & 0x7fffffff) <= 0x3fe921fb) { | 344 if ((%_DoubleHi(x) & 0x7fffffff) <= 0x3fe921fb) { |
| 341 // |x| < pi/4, approximately. No reduction needed. | 345 // |x| < pi/4, approximately. No reduction needed. |
| 342 RETURN_KERNELSIN(x, 0, /* empty */); | 346 RETURN_KERNELSIN(x, 0, /* empty */); |
| 343 } | 347 } |
| 344 return MathSinSlow(x); | 348 return +MathSinSlow(x); |
| 345 } | 349 } |
| 346 | 350 |
| 347 // ECMA 262 - 15.8.2.7 | 351 // ECMA 262 - 15.8.2.7 |
| 348 function MathCos(x) { | 352 function MathCos(x) { |
| 349 x = x * 1; // Convert to number. | 353 x = +x; // Convert to number. |
| 350 if ((%_DoubleHi(x) & 0x7fffffff) <= 0x3fe921fb) { | 354 if ((%_DoubleHi(x) & 0x7fffffff) <= 0x3fe921fb) { |
| 351 // |x| < pi/4, approximately. No reduction needed. | 355 // |x| < pi/4, approximately. No reduction needed. |
| 352 RETURN_KERNELCOS(x, 0, /* empty */); | 356 RETURN_KERNELCOS(x, 0, /* empty */); |
| 353 } | 357 } |
| 354 return MathCosSlow(x); | 358 return +MathCosSlow(x); |
| 355 } | 359 } |
| 356 | 360 |
| 357 // ECMA 262 - 15.8.2.18 | 361 // ECMA 262 - 15.8.2.18 |
| 358 function MathTan(x) { | 362 function MathTan(x) { |
| 359 x = x * 1; // Convert to number. | 363 x = x * 1; // Convert to number. |
| 360 if ((%_DoubleHi(x) & 0x7fffffff) <= 0x3fe921fb) { | 364 if ((%_DoubleHi(x) & 0x7fffffff) <= 0x3fe921fb) { |
| 361 // |x| < pi/4, approximately. No reduction needed. | 365 // |x| < pi/4, approximately. No reduction needed. |
| 362 return KernelTan(x, 0, 1); | 366 return KernelTan(x, 0, 1); |
| 363 } | 367 } |
| 364 REMPIO2(x); | 368 REMPIO2(x); |
| (...skipping 625 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 990 z_l = CP_L * p_h + p_l * CP + dp_l; | 994 z_l = CP_L * p_h + p_l * CP + dp_l; |
| 991 | 995 |
| 992 // log2(ax) = (ss + ...) * 2 / (3 * log(2)) = n + dp_h + z_h + z_l | 996 // log2(ax) = (ss + ...) * 2 / (3 * log(2)) = n + dp_h + z_h + z_l |
| 993 var t = n; | 997 var t = n; |
| 994 var t1 = %_ConstructDouble(%_DoubleHi(((z_h + z_l) + dp_h) + t), 0); | 998 var t1 = %_ConstructDouble(%_DoubleHi(((z_h + z_l) + dp_h) + t), 0); |
| 995 var t2 = z_l - (((t1 - t) - dp_h) - z_h); | 999 var t2 = z_l - (((t1 - t) - dp_h) - z_h); |
| 996 | 1000 |
| 997 // t1 + t2 = log2(ax), sum up because we do not care about extra precision. | 1001 // t1 + t2 = log2(ax), sum up because we do not care about extra precision. |
| 998 return t1 + t2; | 1002 return t1 + t2; |
| 999 } | 1003 } |
| OLD | NEW |