| Index: src/base/ieee754.cc
|
| diff --git a/src/base/ieee754.cc b/src/base/ieee754.cc
|
| index dd86353bbfbebfa48ab213827586669d96d5167f..9a9090de2b3c3d6628a88dc570049694ce26d8a2 100644
|
| --- a/src/base/ieee754.cc
|
| +++ b/src/base/ieee754.cc
|
| @@ -2308,6 +2308,182 @@ double tan(double x) {
|
| }
|
| }
|
|
|
| +/*
|
| + * 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.
|
| + */
|
| +double cosh(double x) {
|
| + static const double KCOSH_OVERFLOW = 710.4758600739439;
|
| + static const double one = 1.0, half = 0.5;
|
| + static volatile double huge = 1.0e+300;
|
| +
|
| + int32_t ix;
|
| +
|
| + /* High word of |x|. */
|
| + GET_HIGH_WORD(ix, x);
|
| + ix &= 0x7fffffff;
|
| +
|
| + // |x| in [0,0.5*log2], return 1+expm1(|x|)^2/(2*exp(|x|))
|
| + if (ix < 0x3fd62e43) {
|
| + double t = expm1(fabs(x));
|
| + double w = one + t;
|
| + // For |x| < 2^-55, cosh(x) = 1
|
| + if (ix < 0x3c800000) return w;
|
| + return one + (t * t) / (w + w);
|
| + }
|
| +
|
| + // |x| in [0.5*log2, 22], return (exp(|x|)+1/exp(|x|)/2
|
| + if (ix < 0x40360000) {
|
| + double t = exp(fabs(x));
|
| + return half * t + half / t;
|
| + }
|
| +
|
| + // |x| in [22, log(maxdouble)], return half*exp(|x|)
|
| + if (ix < 0x40862e42) return half * exp(fabs(x));
|
| +
|
| + // |x| in [log(maxdouble), overflowthreshold]
|
| + if (fabs(x) <= KCOSH_OVERFLOW) {
|
| + double w = exp(half * fabs(x));
|
| + double t = half * w;
|
| + return t * w;
|
| + }
|
| +
|
| + /* x is INF or NaN */
|
| + if (ix >= 0x7ff00000) return x * x;
|
| +
|
| + // |x| > overflowthreshold.
|
| + return huge * huge;
|
| +}
|
| +
|
| +/*
|
| + * ES6 draft 09-27-13, section 20.2.2.30.
|
| + * Math.sinh
|
| + * Method :
|
| + * mathematically sinh(x) if defined to be (exp(x)-exp(-x))/2
|
| + * 1. Replace x by |x| (sinh(-x) = -sinh(x)).
|
| + * 2.
|
| + * E + E/(E+1)
|
| + * 0 <= x <= 22 : sinh(x) := --------------, E=expm1(x)
|
| + * 2
|
| + *
|
| + * 22 <= x <= lnovft : sinh(x) := exp(x)/2
|
| + * lnovft <= x <= ln2ovft: sinh(x) := exp(x/2)/2 * exp(x/2)
|
| + * ln2ovft < x : sinh(x) := x*shuge (overflow)
|
| + *
|
| + * Special cases:
|
| + * sinh(x) is |x| if x is +Infinity, -Infinity, or NaN.
|
| + * only sinh(0)=0 is exact for finite x.
|
| + */
|
| +double sinh(double x) {
|
| + static const double KSINH_OVERFLOW = 710.4758600739439,
|
| + TWO_M28 =
|
| + 3.725290298461914e-9, // 2^-28, empty lower half
|
| + LOG_MAXD = 709.7822265625; // 0x40862e42 00000000, empty lower half
|
| + static const double shuge = 1.0e307;
|
| +
|
| + double h = (x < 0) ? -0.5 : 0.5;
|
| + // |x| in [0, 22]. return sign(x)*0.5*(E+E/(E+1))
|
| + double ax = fabs(x);
|
| + if (ax < 22) {
|
| + // For |x| < 2^-28, sinh(x) = x
|
| + if (ax < TWO_M28) return x;
|
| + double t = expm1(ax);
|
| + if (ax < 1) {
|
| + return h * (2 * t - t * t / (t + 1));
|
| + }
|
| + return h * (t + t / (t + 1));
|
| + }
|
| + // |x| in [22, log(maxdouble)], return 0.5 * exp(|x|)
|
| + if (ax < LOG_MAXD) return h * exp(ax);
|
| + // |x| in [log(maxdouble), overflowthreshold]
|
| + // overflowthreshold = 710.4758600739426
|
| + if (ax <= KSINH_OVERFLOW) {
|
| + double w = exp(0.5 * ax);
|
| + double t = h * w;
|
| + return t * w;
|
| + }
|
| + // |x| > overflowthreshold or is NaN.
|
| + // Return Infinity of the appropriate sign or NaN.
|
| + return x * shuge;
|
| +}
|
| +
|
| +/* Tanh(x)
|
| + * Return the Hyperbolic Tangent of 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**-28 : tanh(x) := x with inexact if x != 0
|
| + * -t
|
| + * 2**-28 <= x < 1 : tanh(x) := -----; t = expm1(-2x)
|
| + * t + 2
|
| + * 2
|
| + * 1 <= x < 22 : tanh(x) := 1 - -----; t = expm1(2x)
|
| + * t + 2
|
| + * 22 <= x <= INF : tanh(x) := 1.
|
| + *
|
| + * Special cases:
|
| + * tanh(NaN) is NaN;
|
| + * only tanh(0)=0 is exact for finite argument.
|
| + */
|
| +double tanh(double x) {
|
| + static const volatile double tiny = 1.0e-300;
|
| + static const double one = 1.0, two = 2.0, huge = 1.0e300;
|
| + double t, z;
|
| + int32_t jx, ix;
|
| +
|
| + GET_HIGH_WORD(jx, x);
|
| + ix = jx & 0x7fffffff;
|
| +
|
| + /* x is INF or NaN */
|
| + if (ix >= 0x7ff00000) {
|
| + if (jx >= 0)
|
| + return one / x + one; /* tanh(+-inf)=+-1 */
|
| + else
|
| + return one / x - one; /* tanh(NaN) = NaN */
|
| + }
|
| +
|
| + /* |x| < 22 */
|
| + if (ix < 0x40360000) { /* |x|<22 */
|
| + if (ix < 0x3e300000) { /* |x|<2**-28 */
|
| + if (huge + x > one) return x; /* tanh(tiny) = tiny with inexact */
|
| + }
|
| + if (ix >= 0x3ff00000) { /* |x|>=1 */
|
| + t = expm1(two * fabs(x));
|
| + z = one - two / (t + two);
|
| + } else {
|
| + t = expm1(-two * fabs(x));
|
| + z = -t / (t + two);
|
| + }
|
| + /* |x| >= 22, return +-1 */
|
| + } else {
|
| + z = one - tiny; /* raise inexact flag */
|
| + }
|
| + return (jx >= 0) ? z : -z;
|
| +}
|
| +
|
| } // namespace ieee754
|
| } // namespace base
|
| } // namespace v8
|
|
|