OLD | NEW |
1 // The following is adapted from fdlibm (http://www.netlib.org/fdlibm), | 1 // The following is adapted from fdlibm (http://www.netlib.org/fdlibm), |
2 // | 2 // |
3 // ==================================================== | 3 // ==================================================== |
4 // Copyright (C) 1993-2004 by Sun Microsystems, Inc. All rights reserved. | 4 // Copyright (C) 1993-2004 by Sun Microsystems, Inc. All rights reserved. |
5 // | 5 // |
6 // Developed at SunSoft, a Sun Microsystems, Inc. business. | 6 // Developed at SunSoft, a Sun Microsystems, Inc. business. |
7 // Permission to use, copy, modify, and distribute this | 7 // Permission to use, copy, modify, and distribute this |
8 // software is freely granted, provided that this notice | 8 // software is freely granted, provided that this notice |
9 // is preserved. | 9 // is preserved. |
10 // ==================================================== | 10 // ==================================================== |
11 // | 11 // |
12 // The original source code covered by the above license above has been | 12 // The original source code covered by the above license above has been |
13 // modified significantly by Google Inc. | 13 // modified significantly by Google Inc. |
14 // Copyright 2014 the V8 project authors. All rights reserved. | 14 // Copyright 2014 the V8 project authors. All rights reserved. |
15 // | 15 // |
16 // The following is a straightforward translation of fdlibm routines | 16 // The following is a straightforward translation of fdlibm routines |
17 // by Raymond Toy (rtoy@google.com). | 17 // by Raymond Toy (rtoy@google.com). |
18 | 18 |
19 (function(global, utils) { | 19 (function(global, utils) { |
20 | 20 |
21 "use strict"; | 21 "use strict"; |
22 | 22 |
23 %CheckIsBootstrapping(); | 23 %CheckIsBootstrapping(); |
24 | 24 |
25 // ------------------------------------------------------------------- | 25 // ------------------------------------------------------------------- |
26 // Imports | 26 // Imports |
27 | 27 |
28 var GlobalMath = global.Math; | 28 var GlobalMath = global.Math; |
29 var MathAbs; | |
30 var MathExpm1; | |
31 | 29 |
32 utils.Import(function(from) { | 30 utils.Import(function(from) {}); |
33 MathAbs = from.MathAbs; | |
34 MathExpm1 = from.MathExpm1; | |
35 }); | |
36 | |
37 // 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 // | |
47 // 22 <= x <= lnovft : sinh(x) := exp(x)/2 | |
48 // 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 // | |
55 define KSINH_OVERFLOW = 710.4758600739439; | |
56 define TWO_M28 = 3.725290298461914e-9; // 2^-28, empty lower half | |
57 define LOG_MAXD = 709.7822265625; // 0x40862e42 00000000, empty lower half | |
58 | |
59 function 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|) | |
72 if (ax < LOG_MAXD) return h * %math_exp(ax); | |
73 // |x| in [log(maxdouble), overflowthreshold] | |
74 // overflowthreshold = 710.4758600739426 | |
75 if (ax <= KSINH_OVERFLOW) { | |
76 var w = %math_exp(0.5 * ax); | |
77 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 | |
88 // Method : | |
89 // mathematically cosh(x) if defined to be (exp(x)+exp(-x))/2 | |
90 // 1. Replace x by |x| (cosh(x) = cosh(-x)). | |
91 // 2. | |
92 // [ exp(x) - 1 ]^2 | |
93 // 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 | |
99 // 22 <= x <= lnovft : cosh(x) := exp(x)/2 | |
100 // 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 // | |
107 define KCOSH_OVERFLOW = 710.4758600739439; | |
108 | |
109 function 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) { | |
122 var t = %math_exp(MathAbs(x)); | |
123 return 0.5 * t + 0.5 / t; | |
124 } | |
125 // |x| in [22, log(maxdouble)], return half*exp(|x|) | |
126 if (ix < 0x40862e42) return 0.5 * %math_exp(MathAbs(x)); | |
127 // |x| in [log(maxdouble), overflowthreshold] | |
128 if (MathAbs(x) <= KCOSH_OVERFLOW) { | |
129 var w = %math_exp(0.5 * MathAbs(x)); | |
130 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 } | |
137 | |
138 // 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 | |
161 define TWO_M55 = 2.77555756156289135105e-17; // 2^-55, empty lower half | |
162 | |
163 function 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 | 31 |
195 //------------------------------------------------------------------- | 32 //------------------------------------------------------------------- |
196 | 33 |
197 utils.InstallFunctions(GlobalMath, DONT_ENUM, [ | 34 utils.InstallFunctions(GlobalMath, DONT_ENUM, []); |
198 "sinh", MathSinh, | |
199 "cosh", MathCosh, | |
200 "tanh", MathTanh | |
201 ]); | |
202 | 35 |
203 }) | 36 }) |
OLD | NEW |