Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Side by Side Diff: src/math.js

Issue 394833002: Ship ES6 Math functions. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/harmony-math.js ('k') | src/objects.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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();
OLDNEW
« no previous file with comments | « src/harmony-math.js ('k') | src/objects.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698