From 4826aa7af2790bc5232db6f028175d451f8dc16c Mon Sep 17 00:00:00 2001 From: "yangguo@chromium.org" Date: Mon, 10 Mar 2014 08:21:18 +0000 Subject: [PATCH] Harmony: implement Math.cbrt in Javascript. R=jarin@chromium.org Review URL: https://codereview.chromium.org/183743018 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@19742 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/harmony-math.js | 21 ++++++++++++++++++++- src/runtime.cc | 30 ------------------------------ src/runtime.h | 1 - 3 files changed, 20 insertions(+), 32 deletions(-) diff --git a/src/harmony-math.js b/src/harmony-math.js index e7afa4d..298fa58 100644 --- a/src/harmony-math.js +++ b/src/harmony-math.js @@ -175,11 +175,30 @@ function MathClz32(x) { // ES6 draft 09-27-13, section 20.2.2.9. +// Cube root approximation, refer to: http://metamerist.com/cbrt/cbrt.htm +// Using initial approximation adapted from Kahan's cbrt and 4 iterations +// of Newton's method. function MathCbrt(x) { - return %Math_cbrt(TO_NUMBER_INLINE(x)); + if (!IS_NUMBER(x)) x = NonNumberToNumber(x); + if (x == 0 || !NUMBER_IS_FINITE(x)) return x; + return x >= 0 ? CubeRoot(x) : -CubeRoot(-x); +} + +macro NEWTON_ITERATION_CBRT(x, approx) + (1.0 / 3.0) * (x / (approx * approx) + 2 * approx); +endmacro + +function CubeRoot(x) { + var approx_hi = MathFloor(%_DoubleHi(x) / 3) + 0x2A9F7893; + var approx = %_ConstructDouble(approx_hi, 0); + approx = NEWTON_ITERATION_CBRT(x, approx); + approx = NEWTON_ITERATION_CBRT(x, approx); + approx = NEWTON_ITERATION_CBRT(x, approx); + return NEWTON_ITERATION_CBRT(x, approx); } + // ES6 draft 09-27-13, section 20.2.2.14. // Use Taylor series to approximate. // exp(x) - 1 at 0 == -1 + exp(0) + exp'(0)*x/1! + exp''(0)*x^2/2! + ... diff --git a/src/runtime.cc b/src/runtime.cc index 2d760a4..c49d245 100644 --- a/src/runtime.cc +++ b/src/runtime.cc @@ -7694,36 +7694,6 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_ConstructDouble) { } -// Cube root approximation, refer to: http://metamerist.com/cbrt/cbrt.htm -// Using initial approximation adapted from Kahan's cbrt and 4 iterations -// of Newton's method. -inline double CubeRootNewtonIteration(double approx, double x) { - return (1.0 / 3.0) * (x / (approx * approx) + 2 * approx); -} - - -inline double CubeRoot(double x) { - static const uint64_t magic = V8_2PART_UINT64_C(0x2A9F7893, 00000000); - uint64_t xhigh = double_to_uint64(x); - double approx = uint64_to_double(xhigh / 3 + magic); - - approx = CubeRootNewtonIteration(approx, x); - approx = CubeRootNewtonIteration(approx, x); - approx = CubeRootNewtonIteration(approx, x); - return CubeRootNewtonIteration(approx, x); -} - - -RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_cbrt) { - SealHandleScope shs(isolate); - ASSERT(args.length() == 1); - CONVERT_DOUBLE_ARG_CHECKED(x, 0); - if (x == 0 || std::isinf(x)) return args[0]; - double result = (x > 0) ? CubeRoot(x) : -CubeRoot(-x); - return isolate->heap()->AllocateHeapNumber(result); -} - - static const double kPiDividedBy4 = 0.78539816339744830962; diff --git a/src/runtime.h b/src/runtime.h index 480edaf..d770968 100644 --- a/src/runtime.h +++ b/src/runtime.h @@ -175,7 +175,6 @@ namespace internal { F(Math_asin, 1, 1) \ F(Math_atan, 1, 1) \ F(Math_log, 1, 1) \ - F(Math_cbrt, 1, 1) \ F(Math_sqrt, 1, 1) \ F(Math_exp, 1, 1) \ F(Math_floor, 1, 1) \ -- 2.7.4