Commit 47c9e1c9 authored by yangguo's avatar yangguo Committed by Commit bot

Implement Math.tanh using fdlibm port.

Contributed by Raymond Toy: http://rtoy.github.io/fdlibm-js/

R=jkummerow@chromium.org
BUG=v8:3495
LOG=N

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

Cr-Commit-Position: refs/heads/master@{#31335}
parent b7990793
......@@ -182,18 +182,6 @@ function MathTrunc(x) {
return x;
}
// ES6 draft 09-27-13, section 20.2.2.33.
function MathTanh(x) {
x = TO_NUMBER(x);
// Idempotent for +/-0.
if (x === 0) return x;
// Returns +/-1 for +/-Infinity.
if (!NUMBER_IS_FINITE(x)) return MathSign(x);
var exp1 = MathExp(x);
var exp2 = MathExp(-x);
return (exp1 - exp2) / (exp1 + exp2);
}
// ES6 draft 09-27-13, section 20.2.2.5.
function MathAsinh(x) {
x = TO_NUMBER(x);
......@@ -329,7 +317,6 @@ utils.InstallFunctions(GlobalMath, DONT_ENUM, [
"imul", MathImul,
"sign", MathSign,
"trunc", MathTrunc,
"tanh", MathTanh,
"asinh", MathAsinh,
"acosh", MathAcosh,
"atanh", MathAtanh,
......
......@@ -843,6 +843,63 @@ function MathCosh(x) {
return INFINITY;
}
// ES6 draft 09-27-13, section 20.2.2.33.
// Math.tanh(x)
// Method :
// x -x
// e - e
// 0. tanh(x) is defined to be -----------
// x -x
// e + e
// 1. reduce x to non-negative by tanh(-x) = -tanh(x).
// 2. 0 <= x <= 2**-55 : tanh(x) := x*(one+x)
// -t
// 2**-55 < x <= 1 : tanh(x) := -----; t = expm1(-2x)
// t + 2
// 2
// 1 <= x <= 22.0 : tanh(x) := 1- ----- ; t = expm1(2x)
// t + 2
// 22.0 < x <= INF : tanh(x) := 1.
//
// Special cases:
// tanh(NaN) is NaN;
// only tanh(0) = 0 is exact for finite argument.
//
define TWO_M55 = 2.77555756156289135105e-17; // 2^-55, empty lower half
function MathTanh(x) {
x = x * 1; // Convert to number.
// x is Infinity or NaN
if (!NUMBER_IS_FINITE(x)) {
if (x > 0) return 1;
if (x < 0) return -1;
return x;
}
var ax = MathAbs(x);
var z;
// |x| < 22
if (ax < 22) {
if (ax < TWO_M55) {
// |x| < 2^-55, tanh(small) = small.
return x;
}
if (ax >= 1) {
// |x| >= 1
var t = MathExpm1(2 * ax);
z = 1 - 2 / (t + 2);
} else {
var t = MathExpm1(-2 * ax);
z = -t / (t + 2);
}
} else {
// |x| > 22, return +/- 1
z = 1;
}
return (x >= 0) ? z : -z;
}
// ES6 draft 09-27-13, section 20.2.2.21.
// Return the base 10 logarithm of x
//
......@@ -1029,6 +1086,7 @@ utils.InstallFunctions(GlobalMath, DONT_ENUM, [
"tan", MathTan,
"sinh", MathSinh,
"cosh", MathCosh,
"tanh", MathTanh,
"log10", MathLog10,
"log2", MathLog2,
"log1p", MathLog1p,
......
......@@ -186,3 +186,21 @@ assertEquals(1.7976931348621744e308, Math.cosh(-710.4758600739439));
// Overflow.
assertEquals(Infinity, Math.cosh(710.475860073944));
assertEquals(Infinity, Math.cosh(-710.475860073944));
// Implementation-specific tests for tanh.
// Case |x| < 2^-55
var two_56 = Math.pow(2, -56);
assertEquals(two_56, Math.tanh(two_56));
assertEquals(-two_56, Math.tanh(-two_56));
// Case |x| < 1
assertEquals(0.6, Math.tanh(Math.LN2));
assertEquals(-0.6, Math.tanh(-Math.LN2));
// Case 1 < |x| < 22
assertEquals(15/17, Math.tanh(2 * Math.LN2));
assertEquals(-15/17, Math.tanh(-2 * Math.LN2));
// Case |x| > 22
assertEquals(1, Math.tanh(100));
assertEquals(-1, Math.tanh(-100));
// Test against overflow
assertEquals(1, Math.tanh(1e300));
assertEquals(-1, Math.tanh(-1e300));
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