blob: 26ef126f6850ac5ef0a980decd0fe48c60956f1d [file] [log] [blame]
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001// The following is adapted from fdlibm (http://www.netlib.org/fdlibm),
2//
3// ====================================================
4// Copyright (C) 1993-2004 by Sun Microsystems, Inc. All rights reserved.
5//
6// Developed at SunSoft, a Sun Microsystems, Inc. business.
7// Permission to use, copy, modify, and distribute this
8// software is freely granted, provided that this notice
9// is preserved.
10// ====================================================
11//
12// The original source code covered by the above license above has been
13// modified significantly by Google Inc.
14// Copyright 2014 the V8 project authors. All rights reserved.
15//
16// The following is a straightforward translation of fdlibm routines
17// by Raymond Toy (rtoy@google.com).
18
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019(function(global, utils) {
20
Emily Bernierd0a1eb72015-03-24 16:35:39 -040021"use strict";
22
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023%CheckIsBootstrapping();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000024
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000025// -------------------------------------------------------------------
26// Imports
27
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000028var GlobalMath = global.Math;
29var MathAbs;
Ben Murdoch61f157c2016-09-16 13:49:30 +010030var MathExpm1;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000031
32utils.Import(function(from) {
33 MathAbs = from.MathAbs;
Ben Murdoch61f157c2016-09-16 13:49:30 +010034 MathExpm1 = from.MathExpm1;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000035});
36
Ben Murdochb8a8cc12014-11-26 15:28:44 +000037// ES6 draft 09-27-13, section 20.2.2.30.
38// Math.sinh
39// Method :
40// mathematically sinh(x) if defined to be (exp(x)-exp(-x))/2
41// 1. Replace x by |x| (sinh(-x) = -sinh(x)).
42// 2.
43// E + E/(E+1)
44// 0 <= x <= 22 : sinh(x) := --------------, E=expm1(x)
45// 2
46//
Emily Bernierd0a1eb72015-03-24 16:35:39 -040047// 22 <= x <= lnovft : sinh(x) := exp(x)/2
Ben Murdochb8a8cc12014-11-26 15:28:44 +000048// lnovft <= x <= ln2ovft: sinh(x) := exp(x/2)/2 * exp(x/2)
49// ln2ovft < x : sinh(x) := x*shuge (overflow)
50//
51// Special cases:
52// sinh(x) is |x| if x is +Infinity, -Infinity, or NaN.
53// only sinh(0)=0 is exact for finite x.
54//
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000055define KSINH_OVERFLOW = 710.4758600739439;
56define TWO_M28 = 3.725290298461914e-9; // 2^-28, empty lower half
57define LOG_MAXD = 709.7822265625; // 0x40862e42 00000000, empty lower half
Ben Murdochb8a8cc12014-11-26 15:28:44 +000058
59function MathSinh(x) {
60 x = x * 1; // Convert to number.
61 var h = (x < 0) ? -0.5 : 0.5;
62 // |x| in [0, 22]. return sign(x)*0.5*(E+E/(E+1))
63 var ax = MathAbs(x);
64 if (ax < 22) {
65 // For |x| < 2^-28, sinh(x) = x
66 if (ax < TWO_M28) return x;
67 var t = MathExpm1(ax);
68 if (ax < 1) return h * (2 * t - t * t / (t + 1));
69 return h * (t + t / (t + 1));
70 }
71 // |x| in [22, log(maxdouble)], return 0.5 * exp(|x|)
Ben Murdoch61f157c2016-09-16 13:49:30 +010072 if (ax < LOG_MAXD) return h * %math_exp(ax);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000073 // |x| in [log(maxdouble), overflowthreshold]
74 // overflowthreshold = 710.4758600739426
75 if (ax <= KSINH_OVERFLOW) {
Ben Murdoch61f157c2016-09-16 13:49:30 +010076 var w = %math_exp(0.5 * ax);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000077 var t = h * w;
78 return t * w;
79 }
80 // |x| > overflowthreshold or is NaN.
81 // Return Infinity of the appropriate sign or NaN.
82 return x * INFINITY;
83}
84
85
86// ES6 draft 09-27-13, section 20.2.2.12.
87// Math.cosh
Emily Bernierd0a1eb72015-03-24 16:35:39 -040088// Method :
Ben Murdochb8a8cc12014-11-26 15:28:44 +000089// mathematically cosh(x) if defined to be (exp(x)+exp(-x))/2
Emily Bernierd0a1eb72015-03-24 16:35:39 -040090// 1. Replace x by |x| (cosh(x) = cosh(-x)).
Ben Murdochb8a8cc12014-11-26 15:28:44 +000091// 2.
Emily Bernierd0a1eb72015-03-24 16:35:39 -040092// [ exp(x) - 1 ]^2
Ben Murdochb8a8cc12014-11-26 15:28:44 +000093// 0 <= x <= ln2/2 : cosh(x) := 1 + -------------------
94// 2*exp(x)
95//
96// exp(x) + 1/exp(x)
97// ln2/2 <= x <= 22 : cosh(x) := -------------------
98// 2
Emily Bernierd0a1eb72015-03-24 16:35:39 -040099// 22 <= x <= lnovft : cosh(x) := exp(x)/2
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000100// lnovft <= x <= ln2ovft: cosh(x) := exp(x/2)/2 * exp(x/2)
101// ln2ovft < x : cosh(x) := huge*huge (overflow)
102//
103// Special cases:
104// cosh(x) is |x| if x is +INF, -INF, or NaN.
105// only cosh(0)=1 is exact for finite x.
106//
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000107define KCOSH_OVERFLOW = 710.4758600739439;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000108
109function MathCosh(x) {
110 x = x * 1; // Convert to number.
111 var ix = %_DoubleHi(x) & 0x7fffffff;
112 // |x| in [0,0.5*log2], return 1+expm1(|x|)^2/(2*exp(|x|))
113 if (ix < 0x3fd62e43) {
114 var t = MathExpm1(MathAbs(x));
115 var w = 1 + t;
116 // For |x| < 2^-55, cosh(x) = 1
117 if (ix < 0x3c800000) return w;
118 return 1 + (t * t) / (w + w);
119 }
120 // |x| in [0.5*log2, 22], return (exp(|x|)+1/exp(|x|)/2
121 if (ix < 0x40360000) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100122 var t = %math_exp(MathAbs(x));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000123 return 0.5 * t + 0.5 / t;
124 }
125 // |x| in [22, log(maxdouble)], return half*exp(|x|)
Ben Murdoch61f157c2016-09-16 13:49:30 +0100126 if (ix < 0x40862e42) return 0.5 * %math_exp(MathAbs(x));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000127 // |x| in [log(maxdouble), overflowthreshold]
128 if (MathAbs(x) <= KCOSH_OVERFLOW) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100129 var w = %math_exp(0.5 * MathAbs(x));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000130 var t = 0.5 * w;
131 return t * w;
132 }
133 if (NUMBER_IS_NAN(x)) return x;
134 // |x| > overflowthreshold.
135 return INFINITY;
136}
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400137
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000138// ES6 draft 09-27-13, section 20.2.2.33.
139// Math.tanh(x)
140// Method :
141// x -x
142// e - e
143// 0. tanh(x) is defined to be -----------
144// x -x
145// e + e
146// 1. reduce x to non-negative by tanh(-x) = -tanh(x).
147// 2. 0 <= x <= 2**-55 : tanh(x) := x*(one+x)
148// -t
149// 2**-55 < x <= 1 : tanh(x) := -----; t = expm1(-2x)
150// t + 2
151// 2
152// 1 <= x <= 22.0 : tanh(x) := 1- ----- ; t = expm1(2x)
153// t + 2
154// 22.0 < x <= INF : tanh(x) := 1.
155//
156// Special cases:
157// tanh(NaN) is NaN;
158// only tanh(0) = 0 is exact for finite argument.
159//
160
161define TWO_M55 = 2.77555756156289135105e-17; // 2^-55, empty lower half
162
163function MathTanh(x) {
164 x = x * 1; // Convert to number.
165 // x is Infinity or NaN
166 if (!NUMBER_IS_FINITE(x)) {
167 if (x > 0) return 1;
168 if (x < 0) return -1;
169 return x;
170 }
171
172 var ax = MathAbs(x);
173 var z;
174 // |x| < 22
175 if (ax < 22) {
176 if (ax < TWO_M55) {
177 // |x| < 2^-55, tanh(small) = small.
178 return x;
179 }
180 if (ax >= 1) {
181 // |x| >= 1
182 var t = MathExpm1(2 * ax);
183 z = 1 - 2 / (t + 2);
184 } else {
185 var t = MathExpm1(-2 * ax);
186 z = -t / (t + 2);
187 }
188 } else {
189 // |x| > 22, return +/- 1
190 z = 1;
191 }
192 return (x >= 0) ? z : -z;
193}
194
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000195//-------------------------------------------------------------------
196
197utils.InstallFunctions(GlobalMath, DONT_ENUM, [
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000198 "sinh", MathSinh,
199 "cosh", MathCosh,
Ben Murdoch61f157c2016-09-16 13:49:30 +0100200 "tanh", MathTanh
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000201]);
202
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000203})