Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(505)

Side by Side Diff: src/harmony-math.js

Issue 394833002: Ship ES6 Math functions. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/flag-definitions.h ('k') | src/math.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 'use strict';
6
7 // ES6 draft 09-27-13, section 20.2.2.28.
8 function MathSign(x) {
9 x = TO_NUMBER_INLINE(x);
10 if (x > 0) return 1;
11 if (x < 0) return -1;
12 if (x === 0) return x;
13 return NAN;
14 }
15
16
17 // ES6 draft 09-27-13, section 20.2.2.34.
18 function MathTrunc(x) {
19 x = TO_NUMBER_INLINE(x);
20 if (x > 0) return MathFloor(x);
21 if (x < 0) return MathCeil(x);
22 if (x === 0) return x;
23 return NAN;
24 }
25
26
27 // ES6 draft 09-27-13, section 20.2.2.30.
28 function MathSinh(x) {
29 if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
30 // Idempotent for NaN, +/-0 and +/-Infinity.
31 if (x === 0 || !NUMBER_IS_FINITE(x)) return x;
32 return (MathExp(x) - MathExp(-x)) / 2;
33 }
34
35
36 // ES6 draft 09-27-13, section 20.2.2.12.
37 function MathCosh(x) {
38 if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
39 if (!NUMBER_IS_FINITE(x)) return MathAbs(x);
40 return (MathExp(x) + MathExp(-x)) / 2;
41 }
42
43
44 // ES6 draft 09-27-13, section 20.2.2.33.
45 function MathTanh(x) {
46 if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
47 // Idempotent for +/-0.
48 if (x === 0) return x;
49 // Returns +/-1 for +/-Infinity.
50 if (!NUMBER_IS_FINITE(x)) return MathSign(x);
51 var exp1 = MathExp(x);
52 var exp2 = MathExp(-x);
53 return (exp1 - exp2) / (exp1 + exp2);
54 }
55
56
57 // ES6 draft 09-27-13, section 20.2.2.5.
58 function MathAsinh(x) {
59 if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
60 // Idempotent for NaN, +/-0 and +/-Infinity.
61 if (x === 0 || !NUMBER_IS_FINITE(x)) return x;
62 if (x > 0) return MathLog(x + MathSqrt(x * x + 1));
63 // This is to prevent numerical errors caused by large negative x.
64 return -MathLog(-x + MathSqrt(x * x + 1));
65 }
66
67
68 // ES6 draft 09-27-13, section 20.2.2.3.
69 function MathAcosh(x) {
70 if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
71 if (x < 1) return NAN;
72 // Idempotent for NaN and +Infinity.
73 if (!NUMBER_IS_FINITE(x)) return x;
74 return MathLog(x + MathSqrt(x + 1) * MathSqrt(x - 1));
75 }
76
77
78 // ES6 draft 09-27-13, section 20.2.2.7.
79 function MathAtanh(x) {
80 if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
81 // Idempotent for +/-0.
82 if (x === 0) return x;
83 // Returns NaN for NaN and +/- Infinity.
84 if (!NUMBER_IS_FINITE(x)) return NAN;
85 return 0.5 * MathLog((1 + x) / (1 - x));
86 }
87
88
89 // ES6 draft 09-27-13, section 20.2.2.21.
90 function MathLog10(x) {
91 return MathLog(x) * 0.434294481903251828; // log10(x) = log(x)/log(10).
92 }
93
94
95 // ES6 draft 09-27-13, section 20.2.2.22.
96 function MathLog2(x) {
97 return MathLog(x) * 1.442695040888963407; // log2(x) = log(x)/log(2).
98 }
99
100
101 // ES6 draft 09-27-13, section 20.2.2.17.
102 function MathHypot(x, y) { // Function length is 2.
103 // We may want to introduce fast paths for two arguments and when
104 // normalization to avoid overflow is not necessary. For now, we
105 // simply assume the general case.
106 var length = %_ArgumentsLength();
107 var args = new InternalArray(length);
108 var max = 0;
109 for (var i = 0; i < length; i++) {
110 var n = %_Arguments(i);
111 if (!IS_NUMBER(n)) n = NonNumberToNumber(n);
112 if (n === INFINITY || n === -INFINITY) return INFINITY;
113 n = MathAbs(n);
114 if (n > max) max = n;
115 args[i] = n;
116 }
117
118 // Kahan summation to avoid rounding errors.
119 // Normalize the numbers to the largest one to avoid overflow.
120 if (max === 0) max = 1;
121 var sum = 0;
122 var compensation = 0;
123 for (var i = 0; i < length; i++) {
124 var n = args[i] / max;
125 var summand = n * n - compensation;
126 var preliminary = sum + summand;
127 compensation = (preliminary - sum) - summand;
128 sum = preliminary;
129 }
130 return MathSqrt(sum) * max;
131 }
132
133
134 // ES6 draft 09-27-13, section 20.2.2.16.
135 function MathFroundJS(x) {
136 return %MathFround(TO_NUMBER_INLINE(x));
137 }
138
139
140 function MathClz32(x) {
141 x = ToUint32(TO_NUMBER_INLINE(x));
142 if (x == 0) return 32;
143 var result = 0;
144 // Binary search.
145 if ((x & 0xFFFF0000) === 0) { x <<= 16; result += 16; };
146 if ((x & 0xFF000000) === 0) { x <<= 8; result += 8; };
147 if ((x & 0xF0000000) === 0) { x <<= 4; result += 4; };
148 if ((x & 0xC0000000) === 0) { x <<= 2; result += 2; };
149 if ((x & 0x80000000) === 0) { x <<= 1; result += 1; };
150 return result;
151 }
152
153
154 // ES6 draft 09-27-13, section 20.2.2.9.
155 // Cube root approximation, refer to: http://metamerist.com/cbrt/cbrt.htm
156 // Using initial approximation adapted from Kahan's cbrt and 4 iterations
157 // of Newton's method.
158 function MathCbrt(x) {
159 if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
160 if (x == 0 || !NUMBER_IS_FINITE(x)) return x;
161 return x >= 0 ? CubeRoot(x) : -CubeRoot(-x);
162 }
163
164 macro NEWTON_ITERATION_CBRT(x, approx)
165 (1.0 / 3.0) * (x / (approx * approx) + 2 * approx);
166 endmacro
167
168 function CubeRoot(x) {
169 var approx_hi = MathFloor(%_DoubleHi(x) / 3) + 0x2A9F7893;
170 var approx = %_ConstructDouble(approx_hi, 0);
171 approx = NEWTON_ITERATION_CBRT(x, approx);
172 approx = NEWTON_ITERATION_CBRT(x, approx);
173 approx = NEWTON_ITERATION_CBRT(x, approx);
174 return NEWTON_ITERATION_CBRT(x, approx);
175 }
176
177
178
179 // ES6 draft 09-27-13, section 20.2.2.14.
180 // Use Taylor series to approximate.
181 // exp(x) - 1 at 0 == -1 + exp(0) + exp'(0)*x/1! + exp''(0)*x^2/2! + ...
182 // == x/1! + x^2/2! + x^3/3! + ...
183 // The closer x is to 0, the fewer terms are required.
184 function MathExpm1(x) {
185 if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
186 var xabs = MathAbs(x);
187 if (xabs < 2E-7) {
188 return x * (1 + x * (1/2));
189 } else if (xabs < 6E-5) {
190 return x * (1 + x * (1/2 + x * (1/6)));
191 } else if (xabs < 2E-2) {
192 return x * (1 + x * (1/2 + x * (1/6 +
193 x * (1/24 + x * (1/120 + x * (1/720))))));
194 } else { // Use regular exp if not close enough to 0.
195 return MathExp(x) - 1;
196 }
197 }
198
199
200 // ES6 draft 09-27-13, section 20.2.2.20.
201 // Use Taylor series to approximate. With y = x + 1;
202 // log(y) at 1 == log(1) + log'(1)(y-1)/1! + log''(1)(y-1)^2/2! + ...
203 // == 0 + x - x^2/2 + x^3/3 ...
204 // The closer x is to 0, the fewer terms are required.
205 function MathLog1p(x) {
206 if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
207 var xabs = MathAbs(x);
208 if (xabs < 1E-7) {
209 return x * (1 - x * (1/2));
210 } else if (xabs < 3E-5) {
211 return x * (1 - x * (1/2 - x * (1/3)));
212 } else if (xabs < 7E-3) {
213 return x * (1 - x * (1/2 - x * (1/3 - x * (1/4 -
214 x * (1/5 - x * (1/6 - x * (1/7)))))));
215 } else { // Use regular log if not close enough to 0.
216 return MathLog(1 + x);
217 }
218 }
219
220
221 function ExtendMath() {
222 %CheckIsBootstrapping();
223
224 // Set up the non-enumerable functions on the Math object.
225 InstallFunctions($Math, DONT_ENUM, $Array(
226 "sign", MathSign,
227 "trunc", MathTrunc,
228 "sinh", MathSinh,
229 "cosh", MathCosh,
230 "tanh", MathTanh,
231 "asinh", MathAsinh,
232 "acosh", MathAcosh,
233 "atanh", MathAtanh,
234 "log10", MathLog10,
235 "log2", MathLog2,
236 "hypot", MathHypot,
237 "fround", MathFroundJS,
238 "clz32", MathClz32,
239 "cbrt", MathCbrt,
240 "log1p", MathLog1p,
241 "expm1", MathExpm1
242 ));
243 }
244
245
246 ExtendMath();
OLDNEW
« no previous file with comments | « src/flag-definitions.h ('k') | src/math.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698