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 |