OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 var rngstate; // Initialized to a Uint32Array during genesis. | 5 var rngstate; // Initialized to a Uint32Array during genesis. |
6 | 6 |
7 (function(global, utils) { | 7 (function(global, utils) { |
8 "use strict"; | 8 "use strict"; |
9 | 9 |
10 %CheckIsBootstrapping(); | 10 %CheckIsBootstrapping(); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
49 return %_MathAtan2(y, x); | 49 return %_MathAtan2(y, x); |
50 } | 50 } |
51 | 51 |
52 // ECMA 262 - 15.8.2.6 | 52 // ECMA 262 - 15.8.2.6 |
53 function MathCeil(x) { | 53 function MathCeil(x) { |
54 return -%_MathFloor(-x); | 54 return -%_MathFloor(-x); |
55 } | 55 } |
56 | 56 |
57 // ECMA 262 - 15.8.2.8 | 57 // ECMA 262 - 15.8.2.8 |
58 function MathExp(x) { | 58 function MathExp(x) { |
59 return %MathExpRT(TO_NUMBER_INLINE(x)); | 59 return %MathExpRT(TO_NUMBER(x)); |
60 } | 60 } |
61 | 61 |
62 // ECMA 262 - 15.8.2.9 | 62 // ECMA 262 - 15.8.2.9 |
63 function MathFloorJS(x) { | 63 function MathFloorJS(x) { |
64 return %_MathFloor(+x); | 64 return %_MathFloor(+x); |
65 } | 65 } |
66 | 66 |
67 // ECMA 262 - 15.8.2.10 | 67 // ECMA 262 - 15.8.2.10 |
68 function MathLog(x) { | 68 function MathLog(x) { |
69 return %_MathLogRT(TO_NUMBER_INLINE(x)); | 69 return %_MathLogRT(TO_NUMBER(x)); |
70 } | 70 } |
71 | 71 |
72 // ECMA 262 - 15.8.2.11 | 72 // ECMA 262 - 15.8.2.11 |
73 function MathMax(arg1, arg2) { // length == 2 | 73 function MathMax(arg1, arg2) { // length == 2 |
74 var length = %_ArgumentsLength(); | 74 var length = %_ArgumentsLength(); |
75 if (length == 2) { | 75 if (length == 2) { |
76 arg1 = TO_NUMBER_INLINE(arg1); | 76 arg1 = TO_NUMBER(arg1); |
77 arg2 = TO_NUMBER_INLINE(arg2); | 77 arg2 = TO_NUMBER(arg2); |
78 if (arg2 > arg1) return arg2; | 78 if (arg2 > arg1) return arg2; |
79 if (arg1 > arg2) return arg1; | 79 if (arg1 > arg2) return arg1; |
80 if (arg1 == arg2) { | 80 if (arg1 == arg2) { |
81 // Make sure -0 is considered less than +0. | 81 // Make sure -0 is considered less than +0. |
82 return (arg1 === 0 && %_IsMinusZero(arg1)) ? arg2 : arg1; | 82 return (arg1 === 0 && %_IsMinusZero(arg1)) ? arg2 : arg1; |
83 } | 83 } |
84 // All comparisons failed, one of the arguments must be NaN. | 84 // All comparisons failed, one of the arguments must be NaN. |
85 return NAN; | 85 return NAN; |
86 } | 86 } |
87 var r = -INFINITY; | 87 var r = -INFINITY; |
88 for (var i = 0; i < length; i++) { | 88 for (var i = 0; i < length; i++) { |
89 var n = %_Arguments(i); | 89 var n = %_Arguments(i); |
90 n = TO_NUMBER_INLINE(n); | 90 n = TO_NUMBER(n); |
91 // Make sure +0 is considered greater than -0. | 91 // Make sure +0 is considered greater than -0. |
92 if (NUMBER_IS_NAN(n) || n > r || (r === 0 && n === 0 && %_IsMinusZero(r))) { | 92 if (NUMBER_IS_NAN(n) || n > r || (r === 0 && n === 0 && %_IsMinusZero(r))) { |
93 r = n; | 93 r = n; |
94 } | 94 } |
95 } | 95 } |
96 return r; | 96 return r; |
97 } | 97 } |
98 | 98 |
99 // ECMA 262 - 15.8.2.12 | 99 // ECMA 262 - 15.8.2.12 |
100 function MathMin(arg1, arg2) { // length == 2 | 100 function MathMin(arg1, arg2) { // length == 2 |
101 var length = %_ArgumentsLength(); | 101 var length = %_ArgumentsLength(); |
102 if (length == 2) { | 102 if (length == 2) { |
103 arg1 = TO_NUMBER_INLINE(arg1); | 103 arg1 = TO_NUMBER(arg1); |
104 arg2 = TO_NUMBER_INLINE(arg2); | 104 arg2 = TO_NUMBER(arg2); |
105 if (arg2 > arg1) return arg1; | 105 if (arg2 > arg1) return arg1; |
106 if (arg1 > arg2) return arg2; | 106 if (arg1 > arg2) return arg2; |
107 if (arg1 == arg2) { | 107 if (arg1 == arg2) { |
108 // Make sure -0 is considered less than +0. | 108 // Make sure -0 is considered less than +0. |
109 return (arg1 === 0 && %_IsMinusZero(arg1)) ? arg1 : arg2; | 109 return (arg1 === 0 && %_IsMinusZero(arg1)) ? arg1 : arg2; |
110 } | 110 } |
111 // All comparisons failed, one of the arguments must be NaN. | 111 // All comparisons failed, one of the arguments must be NaN. |
112 return NAN; | 112 return NAN; |
113 } | 113 } |
114 var r = INFINITY; | 114 var r = INFINITY; |
115 for (var i = 0; i < length; i++) { | 115 for (var i = 0; i < length; i++) { |
116 var n = %_Arguments(i); | 116 var n = %_Arguments(i); |
117 n = TO_NUMBER_INLINE(n); | 117 n = TO_NUMBER(n); |
118 // Make sure -0 is considered less than +0. | 118 // Make sure -0 is considered less than +0. |
119 if (NUMBER_IS_NAN(n) || n < r || (r === 0 && n === 0 && %_IsMinusZero(n))) { | 119 if (NUMBER_IS_NAN(n) || n < r || (r === 0 && n === 0 && %_IsMinusZero(n))) { |
120 r = n; | 120 r = n; |
121 } | 121 } |
122 } | 122 } |
123 return r; | 123 return r; |
124 } | 124 } |
125 | 125 |
126 // ECMA 262 - 15.8.2.13 | 126 // ECMA 262 - 15.8.2.13 |
127 function MathPowJS(x, y) { | 127 function MathPowJS(x, y) { |
128 return %_MathPow(TO_NUMBER_INLINE(x), TO_NUMBER_INLINE(y)); | 128 return %_MathPow(TO_NUMBER(x), TO_NUMBER(y)); |
129 } | 129 } |
130 | 130 |
131 // ECMA 262 - 15.8.2.14 | 131 // ECMA 262 - 15.8.2.14 |
132 function MathRandom() { | 132 function MathRandom() { |
133 var r0 = (MathImul(18030, rngstate[0] & 0xFFFF) + (rngstate[0] >>> 16)) | 0; | 133 var r0 = (MathImul(18030, rngstate[0] & 0xFFFF) + (rngstate[0] >>> 16)) | 0; |
134 rngstate[0] = r0; | 134 rngstate[0] = r0; |
135 var r1 = (MathImul(36969, rngstate[1] & 0xFFFF) + (rngstate[1] >>> 16)) | 0; | 135 var r1 = (MathImul(36969, rngstate[1] & 0xFFFF) + (rngstate[1] >>> 16)) | 0; |
136 rngstate[1] = r1; | 136 rngstate[1] = r1; |
137 var x = ((r0 << 16) + (r1 & 0xFFFF)) | 0; | 137 var x = ((r0 << 16) + (r1 & 0xFFFF)) | 0; |
138 // Division by 0x100000000 through multiplication by reciprocal. | 138 // Division by 0x100000000 through multiplication by reciprocal. |
139 return (x < 0 ? (x + 0x100000000) : x) * 2.3283064365386962890625e-10; | 139 return (x < 0 ? (x + 0x100000000) : x) * 2.3283064365386962890625e-10; |
140 } | 140 } |
141 | 141 |
142 function MathRandomRaw() { | 142 function MathRandomRaw() { |
143 var r0 = (MathImul(18030, rngstate[0] & 0xFFFF) + (rngstate[0] >>> 16)) | 0; | 143 var r0 = (MathImul(18030, rngstate[0] & 0xFFFF) + (rngstate[0] >>> 16)) | 0; |
144 rngstate[0] = r0; | 144 rngstate[0] = r0; |
145 var r1 = (MathImul(36969, rngstate[1] & 0xFFFF) + (rngstate[1] >>> 16)) | 0; | 145 var r1 = (MathImul(36969, rngstate[1] & 0xFFFF) + (rngstate[1] >>> 16)) | 0; |
146 rngstate[1] = r1; | 146 rngstate[1] = r1; |
147 var x = ((r0 << 16) + (r1 & 0xFFFF)) | 0; | 147 var x = ((r0 << 16) + (r1 & 0xFFFF)) | 0; |
148 return x & 0x3fffffff; | 148 return x & 0x3fffffff; |
149 } | 149 } |
150 | 150 |
151 // ECMA 262 - 15.8.2.15 | 151 // ECMA 262 - 15.8.2.15 |
152 function MathRound(x) { | 152 function MathRound(x) { |
153 return %RoundNumber(TO_NUMBER_INLINE(x)); | 153 return %RoundNumber(TO_NUMBER(x)); |
154 } | 154 } |
155 | 155 |
156 // ECMA 262 - 15.8.2.17 | 156 // ECMA 262 - 15.8.2.17 |
157 function MathSqrtJS(x) { | 157 function MathSqrtJS(x) { |
158 return %_MathSqrt(+x); | 158 return %_MathSqrt(+x); |
159 } | 159 } |
160 | 160 |
161 // Non-standard extension. | 161 // Non-standard extension. |
162 function MathImul(x, y) { | 162 function MathImul(x, y) { |
163 return %NumberImul(TO_NUMBER_INLINE(x), TO_NUMBER_INLINE(y)); | 163 return %NumberImul(TO_NUMBER(x), TO_NUMBER(y)); |
164 } | 164 } |
165 | 165 |
166 // ES6 draft 09-27-13, section 20.2.2.28. | 166 // ES6 draft 09-27-13, section 20.2.2.28. |
167 function MathSign(x) { | 167 function MathSign(x) { |
168 x = +x; | 168 x = +x; |
169 if (x > 0) return 1; | 169 if (x > 0) return 1; |
170 if (x < 0) return -1; | 170 if (x < 0) return -1; |
171 // -0, 0 or NaN. | 171 // -0, 0 or NaN. |
172 return x; | 172 return x; |
173 } | 173 } |
174 | 174 |
175 // ES6 draft 09-27-13, section 20.2.2.34. | 175 // ES6 draft 09-27-13, section 20.2.2.34. |
176 function MathTrunc(x) { | 176 function MathTrunc(x) { |
177 x = +x; | 177 x = +x; |
178 if (x > 0) return %_MathFloor(x); | 178 if (x > 0) return %_MathFloor(x); |
179 if (x < 0) return -%_MathFloor(-x); | 179 if (x < 0) return -%_MathFloor(-x); |
180 // -0, 0 or NaN. | 180 // -0, 0 or NaN. |
181 return x; | 181 return x; |
182 } | 182 } |
183 | 183 |
184 // ES6 draft 09-27-13, section 20.2.2.33. | 184 // ES6 draft 09-27-13, section 20.2.2.33. |
185 function MathTanh(x) { | 185 function MathTanh(x) { |
186 x = TO_NUMBER_INLINE(x); | 186 x = TO_NUMBER(x); |
187 // Idempotent for +/-0. | 187 // Idempotent for +/-0. |
188 if (x === 0) return x; | 188 if (x === 0) return x; |
189 // Returns +/-1 for +/-Infinity. | 189 // Returns +/-1 for +/-Infinity. |
190 if (!NUMBER_IS_FINITE(x)) return MathSign(x); | 190 if (!NUMBER_IS_FINITE(x)) return MathSign(x); |
191 var exp1 = MathExp(x); | 191 var exp1 = MathExp(x); |
192 var exp2 = MathExp(-x); | 192 var exp2 = MathExp(-x); |
193 return (exp1 - exp2) / (exp1 + exp2); | 193 return (exp1 - exp2) / (exp1 + exp2); |
194 } | 194 } |
195 | 195 |
196 // ES6 draft 09-27-13, section 20.2.2.5. | 196 // ES6 draft 09-27-13, section 20.2.2.5. |
197 function MathAsinh(x) { | 197 function MathAsinh(x) { |
198 x = TO_NUMBER_INLINE(x); | 198 x = TO_NUMBER(x); |
199 // Idempotent for NaN, +/-0 and +/-Infinity. | 199 // Idempotent for NaN, +/-0 and +/-Infinity. |
200 if (x === 0 || !NUMBER_IS_FINITE(x)) return x; | 200 if (x === 0 || !NUMBER_IS_FINITE(x)) return x; |
201 if (x > 0) return MathLog(x + %_MathSqrt(x * x + 1)); | 201 if (x > 0) return MathLog(x + %_MathSqrt(x * x + 1)); |
202 // This is to prevent numerical errors caused by large negative x. | 202 // This is to prevent numerical errors caused by large negative x. |
203 return -MathLog(-x + %_MathSqrt(x * x + 1)); | 203 return -MathLog(-x + %_MathSqrt(x * x + 1)); |
204 } | 204 } |
205 | 205 |
206 // ES6 draft 09-27-13, section 20.2.2.3. | 206 // ES6 draft 09-27-13, section 20.2.2.3. |
207 function MathAcosh(x) { | 207 function MathAcosh(x) { |
208 x = TO_NUMBER_INLINE(x); | 208 x = TO_NUMBER(x); |
209 if (x < 1) return NAN; | 209 if (x < 1) return NAN; |
210 // Idempotent for NaN and +Infinity. | 210 // Idempotent for NaN and +Infinity. |
211 if (!NUMBER_IS_FINITE(x)) return x; | 211 if (!NUMBER_IS_FINITE(x)) return x; |
212 return MathLog(x + %_MathSqrt(x + 1) * %_MathSqrt(x - 1)); | 212 return MathLog(x + %_MathSqrt(x + 1) * %_MathSqrt(x - 1)); |
213 } | 213 } |
214 | 214 |
215 // ES6 draft 09-27-13, section 20.2.2.7. | 215 // ES6 draft 09-27-13, section 20.2.2.7. |
216 function MathAtanh(x) { | 216 function MathAtanh(x) { |
217 x = TO_NUMBER_INLINE(x); | 217 x = TO_NUMBER(x); |
218 // Idempotent for +/-0. | 218 // Idempotent for +/-0. |
219 if (x === 0) return x; | 219 if (x === 0) return x; |
220 // Returns NaN for NaN and +/- Infinity. | 220 // Returns NaN for NaN and +/- Infinity. |
221 if (!NUMBER_IS_FINITE(x)) return NAN; | 221 if (!NUMBER_IS_FINITE(x)) return NAN; |
222 return 0.5 * MathLog((1 + x) / (1 - x)); | 222 return 0.5 * MathLog((1 + x) / (1 - x)); |
223 } | 223 } |
224 | 224 |
225 // ES6 draft 09-27-13, section 20.2.2.17. | 225 // ES6 draft 09-27-13, section 20.2.2.17. |
226 function MathHypot(x, y) { // Function length is 2. | 226 function MathHypot(x, y) { // Function length is 2. |
227 // We may want to introduce fast paths for two arguments and when | 227 // We may want to introduce fast paths for two arguments and when |
228 // normalization to avoid overflow is not necessary. For now, we | 228 // normalization to avoid overflow is not necessary. For now, we |
229 // simply assume the general case. | 229 // simply assume the general case. |
230 var length = %_ArgumentsLength(); | 230 var length = %_ArgumentsLength(); |
231 var args = new InternalArray(length); | 231 var args = new InternalArray(length); |
232 var max = 0; | 232 var max = 0; |
233 for (var i = 0; i < length; i++) { | 233 for (var i = 0; i < length; i++) { |
234 var n = %_Arguments(i); | 234 var n = %_Arguments(i); |
235 n = TO_NUMBER_INLINE(n); | 235 n = TO_NUMBER(n); |
236 if (n === INFINITY || n === -INFINITY) return INFINITY; | 236 if (n === INFINITY || n === -INFINITY) return INFINITY; |
237 n = MathAbs(n); | 237 n = MathAbs(n); |
238 if (n > max) max = n; | 238 if (n > max) max = n; |
239 args[i] = n; | 239 args[i] = n; |
240 } | 240 } |
241 | 241 |
242 // Kahan summation to avoid rounding errors. | 242 // Kahan summation to avoid rounding errors. |
243 // Normalize the numbers to the largest one to avoid overflow. | 243 // Normalize the numbers to the largest one to avoid overflow. |
244 if (max === 0) max = 1; | 244 if (max === 0) max = 1; |
245 var sum = 0; | 245 var sum = 0; |
246 var compensation = 0; | 246 var compensation = 0; |
247 for (var i = 0; i < length; i++) { | 247 for (var i = 0; i < length; i++) { |
248 var n = args[i] / max; | 248 var n = args[i] / max; |
249 var summand = n * n - compensation; | 249 var summand = n * n - compensation; |
250 var preliminary = sum + summand; | 250 var preliminary = sum + summand; |
251 compensation = (preliminary - sum) - summand; | 251 compensation = (preliminary - sum) - summand; |
252 sum = preliminary; | 252 sum = preliminary; |
253 } | 253 } |
254 return %_MathSqrt(sum) * max; | 254 return %_MathSqrt(sum) * max; |
255 } | 255 } |
256 | 256 |
257 // ES6 draft 09-27-13, section 20.2.2.16. | 257 // ES6 draft 09-27-13, section 20.2.2.16. |
258 function MathFroundJS(x) { | 258 function MathFroundJS(x) { |
259 return %MathFround(TO_NUMBER_INLINE(x)); | 259 return %MathFround(TO_NUMBER(x)); |
260 } | 260 } |
261 | 261 |
262 // ES6 draft 07-18-14, section 20.2.2.11 | 262 // ES6 draft 07-18-14, section 20.2.2.11 |
263 function MathClz32JS(x) { | 263 function MathClz32JS(x) { |
264 return %_MathClz32(x >>> 0); | 264 return %_MathClz32(x >>> 0); |
265 } | 265 } |
266 | 266 |
267 // ES6 draft 09-27-13, section 20.2.2.9. | 267 // ES6 draft 09-27-13, section 20.2.2.9. |
268 // Cube root approximation, refer to: http://metamerist.com/cbrt/cbrt.htm | 268 // Cube root approximation, refer to: http://metamerist.com/cbrt/cbrt.htm |
269 // Using initial approximation adapted from Kahan's cbrt and 4 iterations | 269 // Using initial approximation adapted from Kahan's cbrt and 4 iterations |
270 // of Newton's method. | 270 // of Newton's method. |
271 function MathCbrt(x) { | 271 function MathCbrt(x) { |
272 x = TO_NUMBER_INLINE(x); | 272 x = TO_NUMBER(x); |
273 if (x == 0 || !NUMBER_IS_FINITE(x)) return x; | 273 if (x == 0 || !NUMBER_IS_FINITE(x)) return x; |
274 return x >= 0 ? CubeRoot(x) : -CubeRoot(-x); | 274 return x >= 0 ? CubeRoot(x) : -CubeRoot(-x); |
275 } | 275 } |
276 | 276 |
277 macro NEWTON_ITERATION_CBRT(x, approx) | 277 macro NEWTON_ITERATION_CBRT(x, approx) |
278 (1.0 / 3.0) * (x / (approx * approx) + 2 * approx); | 278 (1.0 / 3.0) * (x / (approx * approx) + 2 * approx); |
279 endmacro | 279 endmacro |
280 | 280 |
281 function CubeRoot(x) { | 281 function CubeRoot(x) { |
282 var approx_hi = MathFloorJS(%_DoubleHi(x) / 3) + 0x2A9F7893; | 282 var approx_hi = MathFloorJS(%_DoubleHi(x) / 3) + 0x2A9F7893; |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
357 utils.Export(function(to) { | 357 utils.Export(function(to) { |
358 to.MathAbs = MathAbs; | 358 to.MathAbs = MathAbs; |
359 to.MathExp = MathExp; | 359 to.MathExp = MathExp; |
360 to.MathFloor = MathFloorJS; | 360 to.MathFloor = MathFloorJS; |
361 to.IntRandom = MathRandomRaw; | 361 to.IntRandom = MathRandomRaw; |
362 to.MathMax = MathMax; | 362 to.MathMax = MathMax; |
363 to.MathMin = MathMin; | 363 to.MathMin = MathMin; |
364 }); | 364 }); |
365 | 365 |
366 }) | 366 }) |
OLD | NEW |