| 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 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 127 } | 127 } |
| 128 } else { | 128 } else { |
| 129 // Need to do full Payne-Hanek reduction here. | 129 // Need to do full Payne-Hanek reduction here. |
| 130 n = %RemPiO2(X, rempio2result); | 130 n = %RemPiO2(X, rempio2result); |
| 131 y0 = rempio2result[0]; | 131 y0 = rempio2result[0]; |
| 132 y1 = rempio2result[1]; | 132 y1 = rempio2result[1]; |
| 133 } | 133 } |
| 134 endmacro | 134 endmacro |
| 135 | 135 |
| 136 | 136 |
| 137 // __kernel_sin(X, Y, IY) | |
| 138 // kernel sin function on [-pi/4, pi/4], pi/4 ~ 0.7854 | |
| 139 // Input X is assumed to be bounded by ~pi/4 in magnitude. | |
| 140 // Input Y is the tail of X so that x = X + Y. | |
| 141 // | |
| 142 // Algorithm | |
| 143 // 1. Since ieee_sin(-x) = -ieee_sin(x), we need only to consider positive x. | |
| 144 // 2. ieee_sin(x) is approximated by a polynomial of degree 13 on | |
| 145 // [0,pi/4] | |
| 146 // 3 13 | |
| 147 // sin(x) ~ x + S1*x + ... + S6*x | |
| 148 // where | |
| 149 // | |
| 150 // |ieee_sin(x) 2 4 6 8 10 12 | -58 | |
| 151 // |----- - (1+S1*x +S2*x +S3*x +S4*x +S5*x +S6*x )| <= 2 | |
| 152 // | x | | |
| 153 // | |
| 154 // 3. ieee_sin(X+Y) = ieee_sin(X) + sin'(X')*Y | |
| 155 // ~ ieee_sin(X) + (1-X*X/2)*Y | |
| 156 // For better accuracy, let | |
| 157 // 3 2 2 2 2 | |
| 158 // r = X *(S2+X *(S3+X *(S4+X *(S5+X *S6)))) | |
| 159 // then 3 2 | |
| 160 // sin(x) = X + (S1*X + (X *(r-Y/2)+Y)) | |
| 161 // | |
| 162 define S1 = -1.66666666666666324348e-01; | |
| 163 define S2 = 8.33333333332248946124e-03; | |
| 164 define S3 = -1.98412698298579493134e-04; | |
| 165 define S4 = 2.75573137070700676789e-06; | |
| 166 define S5 = -2.50507602534068634195e-08; | |
| 167 define S6 = 1.58969099521155010221e-10; | |
| 168 | |
| 169 macro RETURN_KERNELSIN(X, Y, SIGN) | |
| 170 var z = X * X; | |
| 171 var v = z * X; | |
| 172 var r = S2 + z * (S3 + z * (S4 + z * (S5 + z * S6))); | |
| 173 return (X - ((z * (0.5 * Y - v * r) - Y) - v * S1)) SIGN; | |
| 174 endmacro | |
| 175 | |
| 176 // __kernel_cos(X, Y) | |
| 177 // kernel cos function on [-pi/4, pi/4], pi/4 ~ 0.785398164 | |
| 178 // Input X is assumed to be bounded by ~pi/4 in magnitude. | |
| 179 // Input Y is the tail of X so that x = X + Y. | |
| 180 // | |
| 181 // Algorithm | |
| 182 // 1. Since ieee_cos(-x) = ieee_cos(x), we need only to consider positive x. | |
| 183 // 2. ieee_cos(x) is approximated by a polynomial of degree 14 on | |
| 184 // [0,pi/4] | |
| 185 // 4 14 | |
| 186 // cos(x) ~ 1 - x*x/2 + C1*x + ... + C6*x | |
| 187 // where the remez error is | |
| 188 // | |
| 189 // | 2 4 6 8 10 12 14 | -58 | |
| 190 // |ieee_cos(x)-(1-.5*x +C1*x +C2*x +C3*x +C4*x +C5*x +C6*x )| <= 2 | |
| 191 // | | | |
| 192 // | |
| 193 // 4 6 8 10 12 14 | |
| 194 // 3. let r = C1*x +C2*x +C3*x +C4*x +C5*x +C6*x , then | |
| 195 // ieee_cos(x) = 1 - x*x/2 + r | |
| 196 // since ieee_cos(X+Y) ~ ieee_cos(X) - ieee_sin(X)*Y | |
| 197 // ~ ieee_cos(X) - X*Y, | |
| 198 // a correction term is necessary in ieee_cos(x) and hence | |
| 199 // cos(X+Y) = 1 - (X*X/2 - (r - X*Y)) | |
| 200 // For better accuracy when x > 0.3, let qx = |x|/4 with | |
| 201 // the last 32 bits mask off, and if x > 0.78125, let qx = 0.28125. | |
| 202 // Then | |
| 203 // cos(X+Y) = (1-qx) - ((X*X/2-qx) - (r-X*Y)). | |
| 204 // Note that 1-qx and (X*X/2-qx) is EXACT here, and the | |
| 205 // magnitude of the latter is at least a quarter of X*X/2, | |
| 206 // thus, reducing the rounding error in the subtraction. | |
| 207 // | |
| 208 define C1 = 4.16666666666666019037e-02; | |
| 209 define C2 = -1.38888888888741095749e-03; | |
| 210 define C3 = 2.48015872894767294178e-05; | |
| 211 define C4 = -2.75573143513906633035e-07; | |
| 212 define C5 = 2.08757232129817482790e-09; | |
| 213 define C6 = -1.13596475577881948265e-11; | |
| 214 | |
| 215 macro RETURN_KERNELCOS(X, Y, SIGN) | |
| 216 var ix = %_DoubleHi(X) & 0x7fffffff; | |
| 217 var z = X * X; | |
| 218 var r = z * (C1 + z * (C2 + z * (C3 + z * (C4 + z * (C5 + z * C6))))); | |
| 219 if (ix < 0x3fd33333) { // |x| ~< 0.3 | |
| 220 return (1 - (0.5 * z - (z * r - X * Y))) SIGN; | |
| 221 } else { | |
| 222 var qx; | |
| 223 if (ix > 0x3fe90000) { // |x| > 0.78125 | |
| 224 qx = 0.28125; | |
| 225 } else { | |
| 226 qx = %_ConstructDouble(%_DoubleHi(0.25 * X), 0); | |
| 227 } | |
| 228 var hz = 0.5 * z - qx; | |
| 229 return (1 - qx - (hz - (z * r - X * Y))) SIGN; | |
| 230 } | |
| 231 endmacro | |
| 232 | |
| 233 | |
| 234 // kernel tan function on [-pi/4, pi/4], pi/4 ~ 0.7854 | 137 // kernel tan function on [-pi/4, pi/4], pi/4 ~ 0.7854 |
| 235 // Input x is assumed to be bounded by ~pi/4 in magnitude. | 138 // Input x is assumed to be bounded by ~pi/4 in magnitude. |
| 236 // Input y is the tail of x. | 139 // Input y is the tail of x. |
| 237 // Input k indicates whether ieee_tan (if k = 1) or -1/tan (if k = -1) | 140 // Input k indicates whether ieee_tan (if k = 1) or -1/tan (if k = -1) |
| 238 // is returned. | 141 // is returned. |
| 239 // | 142 // |
| 240 // Algorithm | 143 // Algorithm |
| 241 // 1. Since ieee_tan(-x) = -ieee_tan(x), we need only to consider positive x. | 144 // 1. Since ieee_tan(-x) = -ieee_tan(x), we need only to consider positive x. |
| 242 // 2. if x < 2^-28 (hx<0x3e300000 0), return x with inexact if x!=0. | 145 // 2. if x < 2^-28 (hx<0x3e300000 0), return x with inexact if x!=0. |
| 243 // 3. ieee_tan(x) is approximated by a odd polynomial of degree 27 on | 146 // 3. ieee_tan(x) is approximated by a odd polynomial of degree 27 on |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 338 } else { | 241 } else { |
| 339 z = %_ConstructDouble(%_DoubleHi(w), 0); | 242 z = %_ConstructDouble(%_DoubleHi(w), 0); |
| 340 v = r - (z - x); | 243 v = r - (z - x); |
| 341 var a = -1 / w; | 244 var a = -1 / w; |
| 342 var t = %_ConstructDouble(%_DoubleHi(a), 0); | 245 var t = %_ConstructDouble(%_DoubleHi(a), 0); |
| 343 s = 1 + t * z; | 246 s = 1 + t * z; |
| 344 return t + a * (s + t * v); | 247 return t + a * (s + t * v); |
| 345 } | 248 } |
| 346 } | 249 } |
| 347 | 250 |
| 348 function MathSinSlow(x) { | |
| 349 REMPIO2(x); | |
| 350 var sign = 1 - (n & 2); | |
| 351 if (n & 1) { | |
| 352 RETURN_KERNELCOS(y0, y1, * sign); | |
| 353 } else { | |
| 354 RETURN_KERNELSIN(y0, y1, * sign); | |
| 355 } | |
| 356 } | |
| 357 | |
| 358 function MathCosSlow(x) { | |
| 359 REMPIO2(x); | |
| 360 if (n & 1) { | |
| 361 var sign = (n & 2) - 1; | |
| 362 RETURN_KERNELSIN(y0, y1, * sign); | |
| 363 } else { | |
| 364 var sign = 1 - (n & 2); | |
| 365 RETURN_KERNELCOS(y0, y1, * sign); | |
| 366 } | |
| 367 } | |
| 368 | |
| 369 // ECMA 262 - 15.8.2.16 | |
| 370 function MathSin(x) { | |
| 371 x = +x; // Convert to number. | |
| 372 if ((%_DoubleHi(x) & 0x7fffffff) <= 0x3fe921fb) { | |
| 373 // |x| < pi/4, approximately. No reduction needed. | |
| 374 RETURN_KERNELSIN(x, 0, /* empty */); | |
| 375 } | |
| 376 return +MathSinSlow(x); | |
| 377 } | |
| 378 | |
| 379 // ECMA 262 - 15.8.2.7 | |
| 380 function MathCos(x) { | |
| 381 x = +x; // Convert to number. | |
| 382 if ((%_DoubleHi(x) & 0x7fffffff) <= 0x3fe921fb) { | |
| 383 // |x| < pi/4, approximately. No reduction needed. | |
| 384 RETURN_KERNELCOS(x, 0, /* empty */); | |
| 385 } | |
| 386 return +MathCosSlow(x); | |
| 387 } | |
| 388 | |
| 389 // ECMA 262 - 15.8.2.18 | 251 // ECMA 262 - 15.8.2.18 |
| 390 function MathTan(x) { | 252 function MathTan(x) { |
| 391 x = x * 1; // Convert to number. | 253 x = x * 1; // Convert to number. |
| 392 if ((%_DoubleHi(x) & 0x7fffffff) <= 0x3fe921fb) { | 254 if ((%_DoubleHi(x) & 0x7fffffff) <= 0x3fe921fb) { |
| 393 // |x| < pi/4, approximately. No reduction needed. | 255 // |x| < pi/4, approximately. No reduction needed. |
| 394 return KernelTan(x, 0, 1); | 256 return KernelTan(x, 0, 1); |
| 395 } | 257 } |
| 396 REMPIO2(x); | 258 REMPIO2(x); |
| 397 return KernelTan(y0, y1, (n & 1) ? -1 : 1); | 259 return KernelTan(y0, y1, (n & 1) ? -1 : 1); |
| 398 } | 260 } |
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 557 } else { | 419 } else { |
| 558 // |x| > 22, return +/- 1 | 420 // |x| > 22, return +/- 1 |
| 559 z = 1; | 421 z = 1; |
| 560 } | 422 } |
| 561 return (x >= 0) ? z : -z; | 423 return (x >= 0) ? z : -z; |
| 562 } | 424 } |
| 563 | 425 |
| 564 //------------------------------------------------------------------- | 426 //------------------------------------------------------------------- |
| 565 | 427 |
| 566 utils.InstallFunctions(GlobalMath, DONT_ENUM, [ | 428 utils.InstallFunctions(GlobalMath, DONT_ENUM, [ |
| 567 "cos", MathCos, | |
| 568 "sin", MathSin, | |
| 569 "tan", MathTan, | 429 "tan", MathTan, |
| 570 "sinh", MathSinh, | 430 "sinh", MathSinh, |
| 571 "cosh", MathCosh, | 431 "cosh", MathCosh, |
| 572 "tanh", MathTanh | 432 "tanh", MathTanh |
| 573 ]); | 433 ]); |
| 574 | 434 |
| 575 %SetForceInlineFlag(MathSin); | |
| 576 %SetForceInlineFlag(MathCos); | |
| 577 | |
| 578 }) | 435 }) |
| OLD | NEW |