OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 "use strict"; | 5 "use strict"; |
6 | 6 |
7 // This file relies on the fact that the following declarations have been made | 7 // This file relies on the fact that the following declarations have been made |
8 // in runtime.js: | 8 // in runtime.js: |
9 // var $Object = global.Object; | 9 // var $Object = global.Object; |
10 | 10 |
(...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
247 var t2 = 1 - t1; | 247 var t2 = 1 - t1; |
248 var y1 = kSinTable[index]; | 248 var y1 = kSinTable[index]; |
249 var y2 = kSinTable[index + 1]; | 249 var y2 = kSinTable[index + 1]; |
250 var dy = y2 - y1; | 250 var dy = y2 - y1; |
251 return (t2 * y1 + t1 * y2 + | 251 return (t2 * y1 + t1 * y2 + |
252 t1 * t2 * ((kCosXIntervalTable[index] - dy) * t2 + | 252 t1 * t2 * ((kCosXIntervalTable[index] - dy) * t2 + |
253 (dy - kCosXIntervalTable[index + 1]) * t1)) | 253 (dy - kCosXIntervalTable[index + 1]) * t1)) |
254 * (1 - (phase & 2)) + 0; | 254 * (1 - (phase & 2)) + 0; |
255 } | 255 } |
256 | 256 |
| 257 |
| 258 // ES6 draft 09-27-13, section 20.2.2.28. |
| 259 function MathSign(x) { |
| 260 x = TO_NUMBER_INLINE(x); |
| 261 if (x > 0) return 1; |
| 262 if (x < 0) return -1; |
| 263 if (x === 0) return x; |
| 264 return NAN; |
| 265 } |
| 266 |
| 267 |
| 268 // ES6 draft 09-27-13, section 20.2.2.34. |
| 269 function MathTrunc(x) { |
| 270 x = TO_NUMBER_INLINE(x); |
| 271 if (x > 0) return MathFloor(x); |
| 272 if (x < 0) return MathCeil(x); |
| 273 if (x === 0) return x; |
| 274 return NAN; |
| 275 } |
| 276 |
| 277 |
| 278 // ES6 draft 09-27-13, section 20.2.2.30. |
| 279 function MathSinh(x) { |
| 280 if (!IS_NUMBER(x)) x = NonNumberToNumber(x); |
| 281 // Idempotent for NaN, +/-0 and +/-Infinity. |
| 282 if (x === 0 || !NUMBER_IS_FINITE(x)) return x; |
| 283 return (MathExp(x) - MathExp(-x)) / 2; |
| 284 } |
| 285 |
| 286 |
| 287 // ES6 draft 09-27-13, section 20.2.2.12. |
| 288 function MathCosh(x) { |
| 289 if (!IS_NUMBER(x)) x = NonNumberToNumber(x); |
| 290 if (!NUMBER_IS_FINITE(x)) return MathAbs(x); |
| 291 return (MathExp(x) + MathExp(-x)) / 2; |
| 292 } |
| 293 |
| 294 |
| 295 // ES6 draft 09-27-13, section 20.2.2.33. |
| 296 function MathTanh(x) { |
| 297 if (!IS_NUMBER(x)) x = NonNumberToNumber(x); |
| 298 // Idempotent for +/-0. |
| 299 if (x === 0) return x; |
| 300 // Returns +/-1 for +/-Infinity. |
| 301 if (!NUMBER_IS_FINITE(x)) return MathSign(x); |
| 302 var exp1 = MathExp(x); |
| 303 var exp2 = MathExp(-x); |
| 304 return (exp1 - exp2) / (exp1 + exp2); |
| 305 } |
| 306 |
| 307 |
| 308 // ES6 draft 09-27-13, section 20.2.2.5. |
| 309 function MathAsinh(x) { |
| 310 if (!IS_NUMBER(x)) x = NonNumberToNumber(x); |
| 311 // Idempotent for NaN, +/-0 and +/-Infinity. |
| 312 if (x === 0 || !NUMBER_IS_FINITE(x)) return x; |
| 313 if (x > 0) return MathLog(x + MathSqrt(x * x + 1)); |
| 314 // This is to prevent numerical errors caused by large negative x. |
| 315 return -MathLog(-x + MathSqrt(x * x + 1)); |
| 316 } |
| 317 |
| 318 |
| 319 // ES6 draft 09-27-13, section 20.2.2.3. |
| 320 function MathAcosh(x) { |
| 321 if (!IS_NUMBER(x)) x = NonNumberToNumber(x); |
| 322 if (x < 1) return NAN; |
| 323 // Idempotent for NaN and +Infinity. |
| 324 if (!NUMBER_IS_FINITE(x)) return x; |
| 325 return MathLog(x + MathSqrt(x + 1) * MathSqrt(x - 1)); |
| 326 } |
| 327 |
| 328 |
| 329 // ES6 draft 09-27-13, section 20.2.2.7. |
| 330 function MathAtanh(x) { |
| 331 if (!IS_NUMBER(x)) x = NonNumberToNumber(x); |
| 332 // Idempotent for +/-0. |
| 333 if (x === 0) return x; |
| 334 // Returns NaN for NaN and +/- Infinity. |
| 335 if (!NUMBER_IS_FINITE(x)) return NAN; |
| 336 return 0.5 * MathLog((1 + x) / (1 - x)); |
| 337 } |
| 338 |
| 339 |
| 340 // ES6 draft 09-27-13, section 20.2.2.21. |
| 341 function MathLog10(x) { |
| 342 return MathLog(x) * 0.434294481903251828; // log10(x) = log(x)/log(10). |
| 343 } |
| 344 |
| 345 |
| 346 // ES6 draft 09-27-13, section 20.2.2.22. |
| 347 function MathLog2(x) { |
| 348 return MathLog(x) * 1.442695040888963407; // log2(x) = log(x)/log(2). |
| 349 } |
| 350 |
| 351 |
| 352 // ES6 draft 09-27-13, section 20.2.2.17. |
| 353 function MathHypot(x, y) { // Function length is 2. |
| 354 // We may want to introduce fast paths for two arguments and when |
| 355 // normalization to avoid overflow is not necessary. For now, we |
| 356 // simply assume the general case. |
| 357 var length = %_ArgumentsLength(); |
| 358 var args = new InternalArray(length); |
| 359 var max = 0; |
| 360 for (var i = 0; i < length; i++) { |
| 361 var n = %_Arguments(i); |
| 362 if (!IS_NUMBER(n)) n = NonNumberToNumber(n); |
| 363 if (n === INFINITY || n === -INFINITY) return INFINITY; |
| 364 n = MathAbs(n); |
| 365 if (n > max) max = n; |
| 366 args[i] = n; |
| 367 } |
| 368 |
| 369 // Kahan summation to avoid rounding errors. |
| 370 // Normalize the numbers to the largest one to avoid overflow. |
| 371 if (max === 0) max = 1; |
| 372 var sum = 0; |
| 373 var compensation = 0; |
| 374 for (var i = 0; i < length; i++) { |
| 375 var n = args[i] / max; |
| 376 var summand = n * n - compensation; |
| 377 var preliminary = sum + summand; |
| 378 compensation = (preliminary - sum) - summand; |
| 379 sum = preliminary; |
| 380 } |
| 381 return MathSqrt(sum) * max; |
| 382 } |
| 383 |
| 384 |
| 385 // ES6 draft 09-27-13, section 20.2.2.16. |
| 386 function MathFroundJS(x) { |
| 387 return %MathFround(TO_NUMBER_INLINE(x)); |
| 388 } |
| 389 |
| 390 |
| 391 function MathClz32(x) { |
| 392 x = ToUint32(TO_NUMBER_INLINE(x)); |
| 393 if (x == 0) return 32; |
| 394 var result = 0; |
| 395 // Binary search. |
| 396 if ((x & 0xFFFF0000) === 0) { x <<= 16; result += 16; }; |
| 397 if ((x & 0xFF000000) === 0) { x <<= 8; result += 8; }; |
| 398 if ((x & 0xF0000000) === 0) { x <<= 4; result += 4; }; |
| 399 if ((x & 0xC0000000) === 0) { x <<= 2; result += 2; }; |
| 400 if ((x & 0x80000000) === 0) { x <<= 1; result += 1; }; |
| 401 return result; |
| 402 } |
| 403 |
| 404 |
| 405 // ES6 draft 09-27-13, section 20.2.2.9. |
| 406 // Cube root approximation, refer to: http://metamerist.com/cbrt/cbrt.htm |
| 407 // Using initial approximation adapted from Kahan's cbrt and 4 iterations |
| 408 // of Newton's method. |
| 409 function MathCbrt(x) { |
| 410 if (!IS_NUMBER(x)) x = NonNumberToNumber(x); |
| 411 if (x == 0 || !NUMBER_IS_FINITE(x)) return x; |
| 412 return x >= 0 ? CubeRoot(x) : -CubeRoot(-x); |
| 413 } |
| 414 |
| 415 macro NEWTON_ITERATION_CBRT(x, approx) |
| 416 (1.0 / 3.0) * (x / (approx * approx) + 2 * approx); |
| 417 endmacro |
| 418 |
| 419 function CubeRoot(x) { |
| 420 var approx_hi = MathFloor(%_DoubleHi(x) / 3) + 0x2A9F7893; |
| 421 var approx = %_ConstructDouble(approx_hi, 0); |
| 422 approx = NEWTON_ITERATION_CBRT(x, approx); |
| 423 approx = NEWTON_ITERATION_CBRT(x, approx); |
| 424 approx = NEWTON_ITERATION_CBRT(x, approx); |
| 425 return NEWTON_ITERATION_CBRT(x, approx); |
| 426 } |
| 427 |
| 428 |
| 429 |
| 430 // ES6 draft 09-27-13, section 20.2.2.14. |
| 431 // Use Taylor series to approximate. |
| 432 // exp(x) - 1 at 0 == -1 + exp(0) + exp'(0)*x/1! + exp''(0)*x^2/2! + ... |
| 433 // == x/1! + x^2/2! + x^3/3! + ... |
| 434 // The closer x is to 0, the fewer terms are required. |
| 435 function MathExpm1(x) { |
| 436 if (!IS_NUMBER(x)) x = NonNumberToNumber(x); |
| 437 var xabs = MathAbs(x); |
| 438 if (xabs < 2E-7) { |
| 439 return x * (1 + x * (1/2)); |
| 440 } else if (xabs < 6E-5) { |
| 441 return x * (1 + x * (1/2 + x * (1/6))); |
| 442 } else if (xabs < 2E-2) { |
| 443 return x * (1 + x * (1/2 + x * (1/6 + |
| 444 x * (1/24 + x * (1/120 + x * (1/720)))))); |
| 445 } else { // Use regular exp if not close enough to 0. |
| 446 return MathExp(x) - 1; |
| 447 } |
| 448 } |
| 449 |
| 450 |
| 451 // ES6 draft 09-27-13, section 20.2.2.20. |
| 452 // Use Taylor series to approximate. With y = x + 1; |
| 453 // log(y) at 1 == log(1) + log'(1)(y-1)/1! + log''(1)(y-1)^2/2! + ... |
| 454 // == 0 + x - x^2/2 + x^3/3 ... |
| 455 // The closer x is to 0, the fewer terms are required. |
| 456 function MathLog1p(x) { |
| 457 if (!IS_NUMBER(x)) x = NonNumberToNumber(x); |
| 458 var xabs = MathAbs(x); |
| 459 if (xabs < 1E-7) { |
| 460 return x * (1 - x * (1/2)); |
| 461 } else if (xabs < 3E-5) { |
| 462 return x * (1 - x * (1/2 - x * (1/3))); |
| 463 } else if (xabs < 7E-3) { |
| 464 return x * (1 - x * (1/2 - x * (1/3 - x * (1/4 - |
| 465 x * (1/5 - x * (1/6 - x * (1/7))))))); |
| 466 } else { // Use regular log if not close enough to 0. |
| 467 return MathLog(1 + x); |
| 468 } |
| 469 } |
| 470 |
257 // ------------------------------------------------------------------- | 471 // ------------------------------------------------------------------- |
258 | 472 |
259 function SetUpMath() { | 473 function SetUpMath() { |
260 %CheckIsBootstrapping(); | 474 %CheckIsBootstrapping(); |
261 | 475 |
262 %SetPrototype($Math, $Object.prototype); | 476 %SetPrototype($Math, $Object.prototype); |
263 %AddNamedProperty(global, "Math", $Math, DONT_ENUM); | 477 %AddNamedProperty(global, "Math", $Math, DONT_ENUM); |
264 %FunctionSetInstanceClassName(MathConstructor, 'Math'); | 478 %FunctionSetInstanceClassName(MathConstructor, 'Math'); |
265 | 479 |
266 // Set up math constants. | 480 // Set up math constants. |
(...skipping 26 matching lines...) Expand all Loading... |
293 "floor", MathFloor, | 507 "floor", MathFloor, |
294 "log", MathLog, | 508 "log", MathLog, |
295 "round", MathRound, | 509 "round", MathRound, |
296 "sin", MathSin, | 510 "sin", MathSin, |
297 "sqrt", MathSqrt, | 511 "sqrt", MathSqrt, |
298 "tan", MathTan, | 512 "tan", MathTan, |
299 "atan2", MathAtan2JS, | 513 "atan2", MathAtan2JS, |
300 "pow", MathPow, | 514 "pow", MathPow, |
301 "max", MathMax, | 515 "max", MathMax, |
302 "min", MathMin, | 516 "min", MathMin, |
303 "imul", MathImul | 517 "imul", MathImul, |
| 518 "sign", MathSign, |
| 519 "trunc", MathTrunc, |
| 520 "sinh", MathSinh, |
| 521 "cosh", MathCosh, |
| 522 "tanh", MathTanh, |
| 523 "asinh", MathAsinh, |
| 524 "acosh", MathAcosh, |
| 525 "atanh", MathAtanh, |
| 526 "log10", MathLog10, |
| 527 "log2", MathLog2, |
| 528 "hypot", MathHypot, |
| 529 "fround", MathFroundJS, |
| 530 "clz32", MathClz32, |
| 531 "cbrt", MathCbrt, |
| 532 "log1p", MathLog1p, |
| 533 "expm1", MathExpm1 |
304 )); | 534 )); |
305 | 535 |
306 %SetInlineBuiltinFlag(MathCeil); | 536 %SetInlineBuiltinFlag(MathCeil); |
307 %SetInlineBuiltinFlag(MathRandom); | 537 %SetInlineBuiltinFlag(MathRandom); |
308 %SetInlineBuiltinFlag(MathSin); | 538 %SetInlineBuiltinFlag(MathSin); |
309 %SetInlineBuiltinFlag(MathCos); | 539 %SetInlineBuiltinFlag(MathCos); |
310 %SetInlineBuiltinFlag(MathTan); | 540 %SetInlineBuiltinFlag(MathTan); |
311 %SetInlineBuiltinFlag(TrigonometricInterpolation); | 541 %SetInlineBuiltinFlag(TrigonometricInterpolation); |
312 } | 542 } |
313 | 543 |
314 SetUpMath(); | 544 SetUpMath(); |
OLD | NEW |