Commit 2454b8e7 authored by yangguo@chromium.org's avatar yangguo@chromium.org

Harmony: move implementation of Math.log1p and Math.expm1 to Javascript.

R=jarin@chromium.org

Review URL: https://codereview.chromium.org/179533003

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@19701 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent c6bfbace
...@@ -174,21 +174,51 @@ function MathClz32(x) { ...@@ -174,21 +174,51 @@ function MathClz32(x) {
} }
//ES6 draft 09-27-13, section 20.2.2.9. // ES6 draft 09-27-13, section 20.2.2.9.
function MathCbrt(x) { function MathCbrt(x) {
return %Math_cbrt(TO_NUMBER_INLINE(x)); return %Math_cbrt(TO_NUMBER_INLINE(x));
} }
//ES6 draft 09-27-13, section 20.2.2.14. // 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! + ...
// == x/1! + x^2/2! + x^3/3! + ...
// The closer x is to 0, the fewer terms are required.
function MathExpm1(x) { function MathExpm1(x) {
return %Math_expm1(TO_NUMBER_INLINE(x)); if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
var xabs = MathAbs(x);
if (xabs < 2E-7) {
return x * (1 + x * (1/2));
} else if (xabs < 6E-5) {
return x * (1 + x * (1/2 + x * (1/6)));
} else if (xabs < 2E-2) {
return x * (1 + x * (1/2 + x * (1/6 +
x * (1/24 + x * (1/120 + x * (1/720))))));
} else { // Use regular exp if not close enough to 0.
return MathExp(x) - 1;
}
} }
//ES6 draft 09-27-13, section 20.2.2.20. // ES6 draft 09-27-13, section 20.2.2.20.
// Use Taylor series to approximate. With y = x + 1;
// log(y) at 1 == log(1) + log'(1)(y-1)/1! + log''(1)(y-1)^2/2! + ...
// == 0 + x - x^2/2 + x^3/3 ...
// The closer x is to 0, the fewer terms are required.
function MathLog1p(x) { function MathLog1p(x) {
return %Math_log1p(TO_NUMBER_INLINE(x)); if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
var xabs = MathAbs(x);
if (xabs < 1E-7) {
return x * (1 - x * (1/2));
} else if (xabs < 3E-5) {
return x * (1 - x * (1/2 - x * (1/3)));
} else if (xabs < 7E-3) {
return x * (1 - x * (1/2 - x * (1/3 - x * (1/4 -
x * (1/5 - x * (1/6 - x * (1/7)))))));
} else { // Use regular log if not close enough to 0.
return MathLog(1 + x);
}
} }
......
...@@ -7694,67 +7694,6 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_cbrt) { ...@@ -7694,67 +7694,6 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_cbrt) {
} }
RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_log1p) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 1);
CONVERT_DOUBLE_ARG_CHECKED(x, 0);
double x_abs = std::fabs(x);
// Use Taylor series to approximate. With y = x + 1;
// log(y) at 1 == log(1) + log'(1)(y-1)/1! + log''(1)(y-1)^2/2! + ...
// == 0 + x - x^2/2 + x^3/3 ...
// The closer x is to 0, the fewer terms are required.
static const double threshold_2 = 1.0 / 0x00800000;
static const double threshold_3 = 1.0 / 0x00008000;
static const double threshold_7 = 1.0 / 0x00000080;
double result;
if (x_abs < threshold_2) {
result = x * (1.0/1.0 - x * 1.0/2.0);
} else if (x_abs < threshold_3) {
result = x * (1.0/1.0 - x * (1.0/2.0 - x * (1.0/3.0)));
} else if (x_abs < threshold_7) {
result = x * (1.0/1.0 - x * (1.0/2.0 - x * (
1.0/3.0 - x * (1.0/4.0 - x * (
1.0/5.0 - x * (1.0/6.0 - x * (
1.0/7.0)))))));
} else { // Use regular log if not close enough to 0.
result = std::log(1.0 + x);
}
return isolate->heap()->AllocateHeapNumber(result);
}
RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_expm1) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 1);
CONVERT_DOUBLE_ARG_CHECKED(x, 0);
double x_abs = std::fabs(x);
// Use Taylor series to approximate.
// exp(x) - 1 at 0 == -1 + exp(0) + exp'(0)*x/1! + exp''(0)*x^2/2! + ...
// == x/1! + x^2/2! + x^3/3! + ...
// The closer x is to 0, the fewer terms are required.
static const double threshold_2 = 1.0 / 0x00400000;
static const double threshold_3 = 1.0 / 0x00004000;
static const double threshold_6 = 1.0 / 0x00000040;
double result;
if (x_abs < threshold_2) {
result = x * (1.0/1.0 + x * (1.0/2.0));
} else if (x_abs < threshold_3) {
result = x * (1.0/1.0 + x * (1.0/2.0 + x * (1.0/6.0)));
} else if (x_abs < threshold_6) {
result = x * (1.0/1.0 + x * (1.0/2.0 + x * (
1.0/6.0 + x * (1.0/24.0 + x * (
1.0/120.0 + x * (1.0/720.0))))));
} else { // Use regular exp if not close enough to 0.
result = std::exp(x) - 1.0;
}
return isolate->heap()->AllocateHeapNumber(result);
}
static const double kPiDividedBy4 = 0.78539816339744830962; static const double kPiDividedBy4 = 0.78539816339744830962;
......
...@@ -179,8 +179,6 @@ namespace internal { ...@@ -179,8 +179,6 @@ namespace internal {
F(Math_atan, 1, 1) \ F(Math_atan, 1, 1) \
F(Math_log, 1, 1) \ F(Math_log, 1, 1) \
F(Math_cbrt, 1, 1) \ F(Math_cbrt, 1, 1) \
F(Math_log1p, 1, 1) \
F(Math_expm1, 1, 1) \
F(Math_sqrt, 1, 1) \ F(Math_sqrt, 1, 1) \
F(Math_exp, 1, 1) \ F(Math_exp, 1, 1) \
F(Math_floor, 1, 1) \ F(Math_floor, 1, 1) \
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment