Commit fa1bf00e authored by yangguo@chromium.org's avatar yangguo@chromium.org

Port fdlibm implementation for Math.cosh.

R=rtoy@chromium.org
BUG=v8:3494
LOG=N

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

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@23548 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent a668cd6f
......@@ -186,13 +186,6 @@ function MathTrunc(x) {
return x;
}
// ES6 draft 09-27-13, section 20.2.2.12.
function MathCosh(x) {
if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
if (!NUMBER_IS_FINITE(x)) return MathAbs(x);
return (MathExp(x) + MathExp(-x)) / 2;
}
// ES6 draft 09-27-13, section 20.2.2.33.
function MathTanh(x) {
if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
......@@ -369,7 +362,7 @@ function SetUpMath() {
"sign", MathSign,
"trunc", MathTrunc,
"sinh", MathSinh, // implemented by third_party/fdlibm
"cosh", MathCosh,
"cosh", MathCosh, // implemented by third_party/fdlibm
"tanh", MathTanh,
"asinh", MathAsinh,
"acosh", MathAcosh,
......
......@@ -102,13 +102,13 @@ assertEquals("Infinity", String(Math.acosh(Infinity)));
// Some random samples.
assertEqualsDelta(74.203210577788, Math.sinh(5), 1E-12);
assertEqualsDelta(-74.203210577788, Math.sinh(-5), 1E-12);
assertEqualsDelta(74.20321057778875, Math.sinh(5), 1E-12);
assertEqualsDelta(-74.20321057778875, Math.sinh(-5), 1E-12);
assertEqualsDelta(1.1276259652063, Math.cosh(0.5), 1E-12);
assertEqualsDelta(74.209948524787, Math.cosh(5), 1E-12);
assertEqualsDelta(1.1276259652063, Math.cosh(-0.5), 1E-12);
assertEqualsDelta(74.209948524787, Math.cosh(-5), 1E-12);
assertEqualsDelta(1.1276259652063807, Math.cosh(0.5), 1E-12);
assertEqualsDelta(74.20994852478785, Math.cosh(5), 1E-12);
assertEqualsDelta1.1276259652063807, Math.cosh(-0.5), 1E-12);
assertEqualsDelta(74.20994852478785, Math.cosh(-5), 1E-12);
assertEqualsDelta(0.4621171572600, Math.tanh(0.5), 1E-12);
assertEqualsDelta(0.9999092042625, Math.tanh(5), 1E-12);
......@@ -166,3 +166,23 @@ assertEquals(Infinity, Math.sinh(710.475860073944));
assertEquals(-Infinity, Math.sinh(-710.475860073944));
assertEquals(Infinity, Math.sinh(1000));
assertEquals(-Infinity, Math.sinh(-1000));
// Implementation-specific tests for cosh.
// Case |x| < 2^-55
assertEquals(1, Math.cosh(Math.pow(2, -56)));
assertEquals(1, Math.cosh(-Math.pow(2, -56)));
// Case |x| < 1/2*log(2). cosh(Math.LN2/4) = (sqrt(2)+1)/2^(5/4)
assertEquals(1.0150517651282178, Math.cosh(Math.LN2/4));
assertEquals(1.0150517651282178, Math.cosh(-Math.LN2/4));
// Case 1/2*log(2) < |x| < 22. cosh(10*Math.LN2) = 1048577/2048
assertEquals(512.00048828125, Math.cosh(10*Math.LN2));
assertEquals(512.00048828125, Math.cosh(-10*Math.LN2));
// Case 22 <= |x| < log(maxdouble)
assertEquals(2.1474836479999983e9, Math.cosh(32*Math.LN2));
assertEquals(2.1474836479999983e9, Math.cosh(-32*Math.LN2));
// Case log(maxdouble) <= |x| <= overflowthreshold
assertEquals(1.7976931348621744e308, Math.cosh(710.4758600739439));
assertEquals(1.7976931348621744e308, Math.cosh(-710.4758600739439));
// Overflow.
assertEquals(Infinity, Math.cosh(710.475860073944));
assertEquals(Infinity, Math.cosh(-710.475860073944));
......@@ -79,7 +79,7 @@ const double MathConstants::constants[] = {
-7.93650757867487942473e-05, // 49
4.00821782732936239552e-06, // 50
-2.01099218183624371326e-07, // Q5 51
710.4758600739439 // 52 overflow threshold for sinh
710.4758600739439 // 52 overflow threshold sinh, cosh
};
......
......@@ -759,3 +759,56 @@ function MathSinh(x) {
// Return Infinity of the appropriate sign or NaN.
return x * INFINITY;
}
// ES6 draft 09-27-13, section 20.2.2.12.
// Math.cosh
// Method :
// mathematically cosh(x) if defined to be (exp(x)+exp(-x))/2
// 1. Replace x by |x| (cosh(x) = cosh(-x)).
// 2.
// [ exp(x) - 1 ]^2
// 0 <= x <= ln2/2 : cosh(x) := 1 + -------------------
// 2*exp(x)
//
// exp(x) + 1/exp(x)
// ln2/2 <= x <= 22 : cosh(x) := -------------------
// 2
// 22 <= x <= lnovft : cosh(x) := exp(x)/2
// lnovft <= x <= ln2ovft: cosh(x) := exp(x/2)/2 * exp(x/2)
// ln2ovft < x : cosh(x) := huge*huge (overflow)
//
// Special cases:
// cosh(x) is |x| if x is +INF, -INF, or NaN.
// only cosh(0)=1 is exact for finite x.
//
const KCOSH_OVERFLOW = kMath[52];
function MathCosh(x) {
x = x * 1; // Convert to number.
var ix = %_DoubleHi(x) & 0x7fffffff;
// |x| in [0,0.5*log2], return 1+expm1(|x|)^2/(2*exp(|x|))
if (ix < 0x3fd62e43) {
var t = MathExpm1(MathAbs(x));
var w = 1 + t;
// For |x| < 2^-55, cosh(x) = 1
if (ix < 0x3c800000) return w;
return 1 + (t * t) / (w + w);
}
// |x| in [0.5*log2, 22], return (exp(|x|)+1/exp(|x|)/2
if (ix < 0x40360000) {
var t = MathExp(MathAbs(x));
return 0.5 * t + 0.5 / t;
}
// |x| in [22, log(maxdouble)], return half*exp(|x|)
if (ix < 0x40862e42) return 0.5 * MathExp(MathAbs(x));
// |x| in [log(maxdouble), overflowthreshold]
if (MathAbs(x) <= KCOSH_OVERFLOW) {
var w = MathExp(0.5 * MathAbs(x));
var t = 0.5 * w;
return t * w;
}
if (NUMBER_IS_NAN(x)) return x;
// |x| > overflowthreshold.
return INFINITY;
}
......@@ -51,7 +51,7 @@ EXPECTED_FUNCTION_COUNT = 431
EXPECTED_FUZZABLE_COUNT = 332
EXPECTED_CCTEST_COUNT = 7
EXPECTED_UNKNOWN_COUNT = 17
EXPECTED_BUILTINS_COUNT = 807
EXPECTED_BUILTINS_COUNT = 806
# Don't call these at all.
......
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