| 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 "use strict"; | 5 "use strict"; |
| 6 | 6 |
| 7 // This file relies on the fact that the following declarations have been made | 7 // This file relies on the fact that the following declarations have been made |
| 8 // in runtime.js: | 8 // in runtime.js: |
| 9 // var $Object = global.Object; | 9 // var $Object = global.Object; |
| 10 | 10 |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 49 // ToNumber (valueOf) is called. | 49 // ToNumber (valueOf) is called. |
| 50 function MathAtan2JS(y, x) { | 50 function MathAtan2JS(y, x) { |
| 51 return %MathAtan2(TO_NUMBER_INLINE(y), TO_NUMBER_INLINE(x)); | 51 return %MathAtan2(TO_NUMBER_INLINE(y), TO_NUMBER_INLINE(x)); |
| 52 } | 52 } |
| 53 | 53 |
| 54 // ECMA 262 - 15.8.2.6 | 54 // ECMA 262 - 15.8.2.6 |
| 55 function MathCeil(x) { | 55 function MathCeil(x) { |
| 56 return -MathFloor(-x); | 56 return -MathFloor(-x); |
| 57 } | 57 } |
| 58 | 58 |
| 59 // ECMA 262 - 15.8.2.7 | |
| 60 function MathCos(x) { | |
| 61 x = MathAbs(x); // Convert to number and get rid of -0. | |
| 62 return TrigonometricInterpolation(x, 1); | |
| 63 } | |
| 64 | |
| 65 // ECMA 262 - 15.8.2.8 | 59 // ECMA 262 - 15.8.2.8 |
| 66 function MathExp(x) { | 60 function MathExp(x) { |
| 67 return %MathExpRT(TO_NUMBER_INLINE(x)); | 61 return %MathExpRT(TO_NUMBER_INLINE(x)); |
| 68 } | 62 } |
| 69 | 63 |
| 70 // ECMA 262 - 15.8.2.9 | 64 // ECMA 262 - 15.8.2.9 |
| 71 function MathFloor(x) { | 65 function MathFloor(x) { |
| 72 x = TO_NUMBER_INLINE(x); | 66 x = TO_NUMBER_INLINE(x); |
| 73 // It's more common to call this with a positive number that's out | 67 // It's more common to call this with a positive number that's out |
| 74 // of range than negative numbers; check the upper bound first. | 68 // of range than negative numbers; check the upper bound first. |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 157 var x = ((r0 << 16) + (r1 & 0xFFFF)) | 0; | 151 var x = ((r0 << 16) + (r1 & 0xFFFF)) | 0; |
| 158 // Division by 0x100000000 through multiplication by reciprocal. | 152 // Division by 0x100000000 through multiplication by reciprocal. |
| 159 return (x < 0 ? (x + 0x100000000) : x) * 2.3283064365386962890625e-10; | 153 return (x < 0 ? (x + 0x100000000) : x) * 2.3283064365386962890625e-10; |
| 160 } | 154 } |
| 161 | 155 |
| 162 // ECMA 262 - 15.8.2.15 | 156 // ECMA 262 - 15.8.2.15 |
| 163 function MathRound(x) { | 157 function MathRound(x) { |
| 164 return %RoundNumber(TO_NUMBER_INLINE(x)); | 158 return %RoundNumber(TO_NUMBER_INLINE(x)); |
| 165 } | 159 } |
| 166 | 160 |
| 167 // ECMA 262 - 15.8.2.16 | |
| 168 function MathSin(x) { | |
| 169 x = x * 1; // Convert to number and deal with -0. | |
| 170 if (%_IsMinusZero(x)) return x; | |
| 171 return TrigonometricInterpolation(x, 0); | |
| 172 } | |
| 173 | |
| 174 // ECMA 262 - 15.8.2.17 | 161 // ECMA 262 - 15.8.2.17 |
| 175 function MathSqrt(x) { | 162 function MathSqrt(x) { |
| 176 return %_MathSqrtRT(TO_NUMBER_INLINE(x)); | 163 return %_MathSqrtRT(TO_NUMBER_INLINE(x)); |
| 177 } | 164 } |
| 178 | 165 |
| 179 // ECMA 262 - 15.8.2.18 | |
| 180 function MathTan(x) { | |
| 181 return MathSin(x) / MathCos(x); | |
| 182 } | |
| 183 | |
| 184 // Non-standard extension. | 166 // Non-standard extension. |
| 185 function MathImul(x, y) { | 167 function MathImul(x, y) { |
| 186 return %NumberImul(TO_NUMBER_INLINE(x), TO_NUMBER_INLINE(y)); | 168 return %NumberImul(TO_NUMBER_INLINE(x), TO_NUMBER_INLINE(y)); |
| 187 } | 169 } |
| 188 | 170 |
| 189 | |
| 190 var kInversePiHalf = 0.636619772367581343; // 2 / pi | |
| 191 var kInversePiHalfS26 = 9.48637384723993156e-9; // 2 / pi / (2^26) | |
| 192 var kS26 = 1 << 26; | |
| 193 var kTwoStepThreshold = 1 << 27; | |
| 194 // pi / 2 rounded up | |
| 195 var kPiHalf = 1.570796326794896780; // 0x192d4454fb21f93f | |
| 196 // We use two parts for pi/2 to emulate a higher precision. | |
| 197 // pi_half_1 only has 26 significant bits for mantissa. | |
| 198 // Note that pi_half > pi_half_1 + pi_half_2 | |
| 199 var kPiHalf1 = 1.570796325802803040; // 0x00000054fb21f93f | |
| 200 var kPiHalf2 = 9.920935796805404252e-10; // 0x3326a611460b113e | |
| 201 | |
| 202 var kSamples; // Initialized to a number during genesis. | |
| 203 var kIndexConvert; // Initialized to kSamples / (pi/2) during genesis. | |
| 204 var kSinTable; // Initialized to a Float64Array during genesis. | |
| 205 var kCosXIntervalTable; // Initialized to a Float64Array during genesis. | |
| 206 | |
| 207 // This implements sine using the following algorithm. | |
| 208 // 1) Multiplication takes care of to-number conversion. | |
| 209 // 2) Reduce x to the first quadrant [0, pi/2]. | |
| 210 // Conveniently enough, in case of +/-Infinity, we get NaN. | |
| 211 // Note that we try to use only 26 instead of 52 significant bits for | |
| 212 // mantissa to avoid rounding errors when multiplying. For very large | |
| 213 // input we therefore have additional steps. | |
| 214 // 3) Replace x by (pi/2-x) if x was in the 2nd or 4th quadrant. | |
| 215 // 4) Do a table lookup for the closest samples to the left and right of x. | |
| 216 // 5) Find the derivatives at those sampling points by table lookup: | |
| 217 // dsin(x)/dx = cos(x) = sin(pi/2-x) for x in [0, pi/2]. | |
| 218 // 6) Use cubic spline interpolation to approximate sin(x). | |
| 219 // 7) Negate the result if x was in the 3rd or 4th quadrant. | |
| 220 // 8) Get rid of -0 by adding 0. | |
| 221 function TrigonometricInterpolation(x, phase) { | |
| 222 if (x < 0 || x > kPiHalf) { | |
| 223 var multiple; | |
| 224 while (x < -kTwoStepThreshold || x > kTwoStepThreshold) { | |
| 225 // Let's assume this loop does not terminate. | |
| 226 // All numbers x in each loop forms a set S. | |
| 227 // (1) abs(x) > 2^27 for all x in S. | |
| 228 // (2) abs(multiple) != 0 since (2^27 * inverse_pi_half_s26) > 1 | |
| 229 // (3) multiple is rounded down in 2^26 steps, so the rounding error is | |
| 230 // at most max(ulp, 2^26). | |
| 231 // (4) so for x > 2^27, we subtract at most (1+pi/4)x and at least | |
| 232 // (1-pi/4)x | |
| 233 // (5) The subtraction results in x' so that abs(x') <= abs(x)*pi/4. | |
| 234 // Note that this difference cannot be simply rounded off. | |
| 235 // Set S cannot exist since (5) violates (1). Loop must terminate. | |
| 236 multiple = MathFloor(x * kInversePiHalfS26) * kS26; | |
| 237 x = x - multiple * kPiHalf1 - multiple * kPiHalf2; | |
| 238 } | |
| 239 multiple = MathFloor(x * kInversePiHalf); | |
| 240 x = x - multiple * kPiHalf1 - multiple * kPiHalf2; | |
| 241 phase += multiple; | |
| 242 } | |
| 243 var double_index = x * kIndexConvert; | |
| 244 if (phase & 1) double_index = kSamples - double_index; | |
| 245 var index = double_index | 0; | |
| 246 var t1 = double_index - index; | |
| 247 var t2 = 1 - t1; | |
| 248 var y1 = kSinTable[index]; | |
| 249 var y2 = kSinTable[index + 1]; | |
| 250 var dy = y2 - y1; | |
| 251 return (t2 * y1 + t1 * y2 + | |
| 252 t1 * t2 * ((kCosXIntervalTable[index] - dy) * t2 + | |
| 253 (dy - kCosXIntervalTable[index + 1]) * t1)) | |
| 254 * (1 - (phase & 2)) + 0; | |
| 255 } | |
| 256 | |
| 257 | |
| 258 // ES6 draft 09-27-13, section 20.2.2.28. | 171 // ES6 draft 09-27-13, section 20.2.2.28. |
| 259 function MathSign(x) { | 172 function MathSign(x) { |
| 260 x = TO_NUMBER_INLINE(x); | 173 x = TO_NUMBER_INLINE(x); |
| 261 if (x > 0) return 1; | 174 if (x > 0) return 1; |
| 262 if (x < 0) return -1; | 175 if (x < 0) return -1; |
| 263 if (x === 0) return x; | 176 if (x === 0) return x; |
| 264 return NAN; | 177 return NAN; |
| 265 } | 178 } |
| 266 | 179 |
| 267 | |
| 268 // ES6 draft 09-27-13, section 20.2.2.34. | 180 // ES6 draft 09-27-13, section 20.2.2.34. |
| 269 function MathTrunc(x) { | 181 function MathTrunc(x) { |
| 270 x = TO_NUMBER_INLINE(x); | 182 x = TO_NUMBER_INLINE(x); |
| 271 if (x > 0) return MathFloor(x); | 183 if (x > 0) return MathFloor(x); |
| 272 if (x < 0) return MathCeil(x); | 184 if (x < 0) return MathCeil(x); |
| 273 if (x === 0) return x; | 185 if (x === 0) return x; |
| 274 return NAN; | 186 return NAN; |
| 275 } | 187 } |
| 276 | 188 |
| 277 | |
| 278 // ES6 draft 09-27-13, section 20.2.2.30. | 189 // ES6 draft 09-27-13, section 20.2.2.30. |
| 279 function MathSinh(x) { | 190 function MathSinh(x) { |
| 280 if (!IS_NUMBER(x)) x = NonNumberToNumber(x); | 191 if (!IS_NUMBER(x)) x = NonNumberToNumber(x); |
| 281 // Idempotent for NaN, +/-0 and +/-Infinity. | 192 // Idempotent for NaN, +/-0 and +/-Infinity. |
| 282 if (x === 0 || !NUMBER_IS_FINITE(x)) return x; | 193 if (x === 0 || !NUMBER_IS_FINITE(x)) return x; |
| 283 return (MathExp(x) - MathExp(-x)) / 2; | 194 return (MathExp(x) - MathExp(-x)) / 2; |
| 284 } | 195 } |
| 285 | 196 |
| 286 | |
| 287 // ES6 draft 09-27-13, section 20.2.2.12. | 197 // ES6 draft 09-27-13, section 20.2.2.12. |
| 288 function MathCosh(x) { | 198 function MathCosh(x) { |
| 289 if (!IS_NUMBER(x)) x = NonNumberToNumber(x); | 199 if (!IS_NUMBER(x)) x = NonNumberToNumber(x); |
| 290 if (!NUMBER_IS_FINITE(x)) return MathAbs(x); | 200 if (!NUMBER_IS_FINITE(x)) return MathAbs(x); |
| 291 return (MathExp(x) + MathExp(-x)) / 2; | 201 return (MathExp(x) + MathExp(-x)) / 2; |
| 292 } | 202 } |
| 293 | 203 |
| 294 | |
| 295 // ES6 draft 09-27-13, section 20.2.2.33. | 204 // ES6 draft 09-27-13, section 20.2.2.33. |
| 296 function MathTanh(x) { | 205 function MathTanh(x) { |
| 297 if (!IS_NUMBER(x)) x = NonNumberToNumber(x); | 206 if (!IS_NUMBER(x)) x = NonNumberToNumber(x); |
| 298 // Idempotent for +/-0. | 207 // Idempotent for +/-0. |
| 299 if (x === 0) return x; | 208 if (x === 0) return x; |
| 300 // Returns +/-1 for +/-Infinity. | 209 // Returns +/-1 for +/-Infinity. |
| 301 if (!NUMBER_IS_FINITE(x)) return MathSign(x); | 210 if (!NUMBER_IS_FINITE(x)) return MathSign(x); |
| 302 var exp1 = MathExp(x); | 211 var exp1 = MathExp(x); |
| 303 var exp2 = MathExp(-x); | 212 var exp2 = MathExp(-x); |
| 304 return (exp1 - exp2) / (exp1 + exp2); | 213 return (exp1 - exp2) / (exp1 + exp2); |
| 305 } | 214 } |
| 306 | 215 |
| 307 | |
| 308 // ES6 draft 09-27-13, section 20.2.2.5. | 216 // ES6 draft 09-27-13, section 20.2.2.5. |
| 309 function MathAsinh(x) { | 217 function MathAsinh(x) { |
| 310 if (!IS_NUMBER(x)) x = NonNumberToNumber(x); | 218 if (!IS_NUMBER(x)) x = NonNumberToNumber(x); |
| 311 // Idempotent for NaN, +/-0 and +/-Infinity. | 219 // Idempotent for NaN, +/-0 and +/-Infinity. |
| 312 if (x === 0 || !NUMBER_IS_FINITE(x)) return x; | 220 if (x === 0 || !NUMBER_IS_FINITE(x)) return x; |
| 313 if (x > 0) return MathLog(x + MathSqrt(x * x + 1)); | 221 if (x > 0) return MathLog(x + MathSqrt(x * x + 1)); |
| 314 // This is to prevent numerical errors caused by large negative x. | 222 // This is to prevent numerical errors caused by large negative x. |
| 315 return -MathLog(-x + MathSqrt(x * x + 1)); | 223 return -MathLog(-x + MathSqrt(x * x + 1)); |
| 316 } | 224 } |
| 317 | 225 |
| 318 | |
| 319 // ES6 draft 09-27-13, section 20.2.2.3. | 226 // ES6 draft 09-27-13, section 20.2.2.3. |
| 320 function MathAcosh(x) { | 227 function MathAcosh(x) { |
| 321 if (!IS_NUMBER(x)) x = NonNumberToNumber(x); | 228 if (!IS_NUMBER(x)) x = NonNumberToNumber(x); |
| 322 if (x < 1) return NAN; | 229 if (x < 1) return NAN; |
| 323 // Idempotent for NaN and +Infinity. | 230 // Idempotent for NaN and +Infinity. |
| 324 if (!NUMBER_IS_FINITE(x)) return x; | 231 if (!NUMBER_IS_FINITE(x)) return x; |
| 325 return MathLog(x + MathSqrt(x + 1) * MathSqrt(x - 1)); | 232 return MathLog(x + MathSqrt(x + 1) * MathSqrt(x - 1)); |
| 326 } | 233 } |
| 327 | 234 |
| 328 | |
| 329 // ES6 draft 09-27-13, section 20.2.2.7. | 235 // ES6 draft 09-27-13, section 20.2.2.7. |
| 330 function MathAtanh(x) { | 236 function MathAtanh(x) { |
| 331 if (!IS_NUMBER(x)) x = NonNumberToNumber(x); | 237 if (!IS_NUMBER(x)) x = NonNumberToNumber(x); |
| 332 // Idempotent for +/-0. | 238 // Idempotent for +/-0. |
| 333 if (x === 0) return x; | 239 if (x === 0) return x; |
| 334 // Returns NaN for NaN and +/- Infinity. | 240 // Returns NaN for NaN and +/- Infinity. |
| 335 if (!NUMBER_IS_FINITE(x)) return NAN; | 241 if (!NUMBER_IS_FINITE(x)) return NAN; |
| 336 return 0.5 * MathLog((1 + x) / (1 - x)); | 242 return 0.5 * MathLog((1 + x) / (1 - x)); |
| 337 } | 243 } |
| 338 | 244 |
| 339 | |
| 340 // ES6 draft 09-27-13, section 20.2.2.21. | 245 // ES6 draft 09-27-13, section 20.2.2.21. |
| 341 function MathLog10(x) { | 246 function MathLog10(x) { |
| 342 return MathLog(x) * 0.434294481903251828; // log10(x) = log(x)/log(10). | 247 return MathLog(x) * 0.434294481903251828; // log10(x) = log(x)/log(10). |
| 343 } | 248 } |
| 344 | 249 |
| 345 | 250 |
| 346 // ES6 draft 09-27-13, section 20.2.2.22. | 251 // ES6 draft 09-27-13, section 20.2.2.22. |
| 347 function MathLog2(x) { | 252 function MathLog2(x) { |
| 348 return MathLog(x) * 1.442695040888963407; // log2(x) = log(x)/log(2). | 253 return MathLog(x) * 1.442695040888963407; // log2(x) = log(x)/log(2). |
| 349 } | 254 } |
| 350 | 255 |
| 351 | |
| 352 // ES6 draft 09-27-13, section 20.2.2.17. | 256 // ES6 draft 09-27-13, section 20.2.2.17. |
| 353 function MathHypot(x, y) { // Function length is 2. | 257 function MathHypot(x, y) { // Function length is 2. |
| 354 // We may want to introduce fast paths for two arguments and when | 258 // We may want to introduce fast paths for two arguments and when |
| 355 // normalization to avoid overflow is not necessary. For now, we | 259 // normalization to avoid overflow is not necessary. For now, we |
| 356 // simply assume the general case. | 260 // simply assume the general case. |
| 357 var length = %_ArgumentsLength(); | 261 var length = %_ArgumentsLength(); |
| 358 var args = new InternalArray(length); | 262 var args = new InternalArray(length); |
| 359 var max = 0; | 263 var max = 0; |
| 360 for (var i = 0; i < length; i++) { | 264 for (var i = 0; i < length; i++) { |
| 361 var n = %_Arguments(i); | 265 var n = %_Arguments(i); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 374 for (var i = 0; i < length; i++) { | 278 for (var i = 0; i < length; i++) { |
| 375 var n = args[i] / max; | 279 var n = args[i] / max; |
| 376 var summand = n * n - compensation; | 280 var summand = n * n - compensation; |
| 377 var preliminary = sum + summand; | 281 var preliminary = sum + summand; |
| 378 compensation = (preliminary - sum) - summand; | 282 compensation = (preliminary - sum) - summand; |
| 379 sum = preliminary; | 283 sum = preliminary; |
| 380 } | 284 } |
| 381 return MathSqrt(sum) * max; | 285 return MathSqrt(sum) * max; |
| 382 } | 286 } |
| 383 | 287 |
| 384 | |
| 385 // ES6 draft 09-27-13, section 20.2.2.16. | 288 // ES6 draft 09-27-13, section 20.2.2.16. |
| 386 function MathFroundJS(x) { | 289 function MathFroundJS(x) { |
| 387 return %MathFround(TO_NUMBER_INLINE(x)); | 290 return %MathFround(TO_NUMBER_INLINE(x)); |
| 388 } | 291 } |
| 389 | 292 |
| 390 | 293 // ES6 draft 07-18-14, section 20.2.2.11 |
| 391 function MathClz32(x) { | 294 function MathClz32(x) { |
| 392 x = ToUint32(TO_NUMBER_INLINE(x)); | 295 x = ToUint32(TO_NUMBER_INLINE(x)); |
| 393 if (x == 0) return 32; | 296 if (x == 0) return 32; |
| 394 var result = 0; | 297 var result = 0; |
| 395 // Binary search. | 298 // Binary search. |
| 396 if ((x & 0xFFFF0000) === 0) { x <<= 16; result += 16; }; | 299 if ((x & 0xFFFF0000) === 0) { x <<= 16; result += 16; }; |
| 397 if ((x & 0xFF000000) === 0) { x <<= 8; result += 8; }; | 300 if ((x & 0xFF000000) === 0) { x <<= 8; result += 8; }; |
| 398 if ((x & 0xF0000000) === 0) { x <<= 4; result += 4; }; | 301 if ((x & 0xF0000000) === 0) { x <<= 4; result += 4; }; |
| 399 if ((x & 0xC0000000) === 0) { x <<= 2; result += 2; }; | 302 if ((x & 0xC0000000) === 0) { x <<= 2; result += 2; }; |
| 400 if ((x & 0x80000000) === 0) { x <<= 1; result += 1; }; | 303 if ((x & 0x80000000) === 0) { x <<= 1; result += 1; }; |
| 401 return result; | 304 return result; |
| 402 } | 305 } |
| 403 | 306 |
| 404 | |
| 405 // ES6 draft 09-27-13, section 20.2.2.9. | 307 // ES6 draft 09-27-13, section 20.2.2.9. |
| 406 // Cube root approximation, refer to: http://metamerist.com/cbrt/cbrt.htm | 308 // Cube root approximation, refer to: http://metamerist.com/cbrt/cbrt.htm |
| 407 // Using initial approximation adapted from Kahan's cbrt and 4 iterations | 309 // Using initial approximation adapted from Kahan's cbrt and 4 iterations |
| 408 // of Newton's method. | 310 // of Newton's method. |
| 409 function MathCbrt(x) { | 311 function MathCbrt(x) { |
| 410 if (!IS_NUMBER(x)) x = NonNumberToNumber(x); | 312 if (!IS_NUMBER(x)) x = NonNumberToNumber(x); |
| 411 if (x == 0 || !NUMBER_IS_FINITE(x)) return x; | 313 if (x == 0 || !NUMBER_IS_FINITE(x)) return x; |
| 412 return x >= 0 ? CubeRoot(x) : -CubeRoot(-x); | 314 return x >= 0 ? CubeRoot(x) : -CubeRoot(-x); |
| 413 } | 315 } |
| 414 | 316 |
| 415 macro NEWTON_ITERATION_CBRT(x, approx) | 317 macro NEWTON_ITERATION_CBRT(x, approx) |
| 416 (1.0 / 3.0) * (x / (approx * approx) + 2 * approx); | 318 (1.0 / 3.0) * (x / (approx * approx) + 2 * approx); |
| 417 endmacro | 319 endmacro |
| 418 | 320 |
| 419 function CubeRoot(x) { | 321 function CubeRoot(x) { |
| 420 var approx_hi = MathFloor(%_DoubleHi(x) / 3) + 0x2A9F7893; | 322 var approx_hi = MathFloor(%_DoubleHi(x) / 3) + 0x2A9F7893; |
| 421 var approx = %_ConstructDouble(approx_hi, 0); | 323 var approx = %_ConstructDouble(approx_hi, 0); |
| 422 approx = NEWTON_ITERATION_CBRT(x, approx); | 324 approx = NEWTON_ITERATION_CBRT(x, approx); |
| 423 approx = NEWTON_ITERATION_CBRT(x, approx); | 325 approx = NEWTON_ITERATION_CBRT(x, approx); |
| 424 approx = NEWTON_ITERATION_CBRT(x, approx); | 326 approx = NEWTON_ITERATION_CBRT(x, approx); |
| 425 return NEWTON_ITERATION_CBRT(x, approx); | 327 return NEWTON_ITERATION_CBRT(x, approx); |
| 426 } | 328 } |
| 427 | 329 |
| 428 | |
| 429 | |
| 430 // ES6 draft 09-27-13, section 20.2.2.14. | 330 // ES6 draft 09-27-13, section 20.2.2.14. |
| 431 // Use Taylor series to approximate. | 331 // Use Taylor series to approximate. |
| 432 // exp(x) - 1 at 0 == -1 + exp(0) + exp'(0)*x/1! + exp''(0)*x^2/2! + ... | 332 // exp(x) - 1 at 0 == -1 + exp(0) + exp'(0)*x/1! + exp''(0)*x^2/2! + ... |
| 433 // == x/1! + x^2/2! + x^3/3! + ... | 333 // == x/1! + x^2/2! + x^3/3! + ... |
| 434 // The closer x is to 0, the fewer terms are required. | 334 // The closer x is to 0, the fewer terms are required. |
| 435 function MathExpm1(x) { | 335 function MathExpm1(x) { |
| 436 if (!IS_NUMBER(x)) x = NonNumberToNumber(x); | 336 if (!IS_NUMBER(x)) x = NonNumberToNumber(x); |
| 437 var xabs = MathAbs(x); | 337 var xabs = MathAbs(x); |
| 438 if (xabs < 2E-7) { | 338 if (xabs < 2E-7) { |
| 439 return x * (1 + x * (1/2)); | 339 return x * (1 + x * (1/2)); |
| 440 } else if (xabs < 6E-5) { | 340 } else if (xabs < 6E-5) { |
| 441 return x * (1 + x * (1/2 + x * (1/6))); | 341 return x * (1 + x * (1/2 + x * (1/6))); |
| 442 } else if (xabs < 2E-2) { | 342 } else if (xabs < 2E-2) { |
| 443 return x * (1 + x * (1/2 + x * (1/6 + | 343 return x * (1 + x * (1/2 + x * (1/6 + |
| 444 x * (1/24 + x * (1/120 + x * (1/720)))))); | 344 x * (1/24 + x * (1/120 + x * (1/720)))))); |
| 445 } else { // Use regular exp if not close enough to 0. | 345 } else { // Use regular exp if not close enough to 0. |
| 446 return MathExp(x) - 1; | 346 return MathExp(x) - 1; |
| 447 } | 347 } |
| 448 } | 348 } |
| 449 | 349 |
| 450 | |
| 451 // ES6 draft 09-27-13, section 20.2.2.20. | 350 // ES6 draft 09-27-13, section 20.2.2.20. |
| 452 // Use Taylor series to approximate. With y = x + 1; | 351 // Use Taylor series to approximate. With y = x + 1; |
| 453 // log(y) at 1 == log(1) + log'(1)(y-1)/1! + log''(1)(y-1)^2/2! + ... | 352 // log(y) at 1 == log(1) + log'(1)(y-1)/1! + log''(1)(y-1)^2/2! + ... |
| 454 // == 0 + x - x^2/2 + x^3/3 ... | 353 // == 0 + x - x^2/2 + x^3/3 ... |
| 455 // The closer x is to 0, the fewer terms are required. | 354 // The closer x is to 0, the fewer terms are required. |
| 456 function MathLog1p(x) { | 355 function MathLog1p(x) { |
| 457 if (!IS_NUMBER(x)) x = NonNumberToNumber(x); | 356 if (!IS_NUMBER(x)) x = NonNumberToNumber(x); |
| 458 var xabs = MathAbs(x); | 357 var xabs = MathAbs(x); |
| 459 if (xabs < 1E-7) { | 358 if (xabs < 1E-7) { |
| 460 return x * (1 - x * (1/2)); | 359 return x * (1 - x * (1/2)); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 495 | 394 |
| 496 // Set up non-enumerable functions of the Math object and | 395 // Set up non-enumerable functions of the Math object and |
| 497 // set their names. | 396 // set their names. |
| 498 InstallFunctions($Math, DONT_ENUM, $Array( | 397 InstallFunctions($Math, DONT_ENUM, $Array( |
| 499 "random", MathRandom, | 398 "random", MathRandom, |
| 500 "abs", MathAbs, | 399 "abs", MathAbs, |
| 501 "acos", MathAcosJS, | 400 "acos", MathAcosJS, |
| 502 "asin", MathAsinJS, | 401 "asin", MathAsinJS, |
| 503 "atan", MathAtanJS, | 402 "atan", MathAtanJS, |
| 504 "ceil", MathCeil, | 403 "ceil", MathCeil, |
| 505 "cos", MathCos, | 404 "cos", MathCos, // implemented by third_party/fdlibm |
| 506 "exp", MathExp, | 405 "exp", MathExp, |
| 507 "floor", MathFloor, | 406 "floor", MathFloor, |
| 508 "log", MathLog, | 407 "log", MathLog, |
| 509 "round", MathRound, | 408 "round", MathRound, |
| 510 "sin", MathSin, | 409 "sin", MathSin, // implemented by third_party/fdlibm |
| 511 "sqrt", MathSqrt, | 410 "sqrt", MathSqrt, |
| 512 "tan", MathTan, | 411 "tan", MathTan, // implemented by third_party/fdlibm |
| 513 "atan2", MathAtan2JS, | 412 "atan2", MathAtan2JS, |
| 514 "pow", MathPow, | 413 "pow", MathPow, |
| 515 "max", MathMax, | 414 "max", MathMax, |
| 516 "min", MathMin, | 415 "min", MathMin, |
| 517 "imul", MathImul, | 416 "imul", MathImul, |
| 518 "sign", MathSign, | 417 "sign", MathSign, |
| 519 "trunc", MathTrunc, | 418 "trunc", MathTrunc, |
| 520 "sinh", MathSinh, | 419 "sinh", MathSinh, |
| 521 "cosh", MathCosh, | 420 "cosh", MathCosh, |
| 522 "tanh", MathTanh, | 421 "tanh", MathTanh, |
| 523 "asinh", MathAsinh, | 422 "asinh", MathAsinh, |
| 524 "acosh", MathAcosh, | 423 "acosh", MathAcosh, |
| 525 "atanh", MathAtanh, | 424 "atanh", MathAtanh, |
| 526 "log10", MathLog10, | 425 "log10", MathLog10, |
| 527 "log2", MathLog2, | 426 "log2", MathLog2, |
| 528 "hypot", MathHypot, | 427 "hypot", MathHypot, |
| 529 "fround", MathFroundJS, | 428 "fround", MathFroundJS, |
| 530 "clz32", MathClz32, | 429 "clz32", MathClz32, |
| 531 "cbrt", MathCbrt, | 430 "cbrt", MathCbrt, |
| 532 "log1p", MathLog1p, | 431 "log1p", MathLog1p, |
| 533 "expm1", MathExpm1 | 432 "expm1", MathExpm1 |
| 534 )); | 433 )); |
| 535 | 434 |
| 536 %SetInlineBuiltinFlag(MathCeil); | 435 %SetInlineBuiltinFlag(MathCeil); |
| 537 %SetInlineBuiltinFlag(MathRandom); | 436 %SetInlineBuiltinFlag(MathRandom); |
| 538 %SetInlineBuiltinFlag(MathSin); | 437 %SetInlineBuiltinFlag(MathSin); |
| 539 %SetInlineBuiltinFlag(MathCos); | 438 %SetInlineBuiltinFlag(MathCos); |
| 540 %SetInlineBuiltinFlag(MathTan); | |
| 541 %SetInlineBuiltinFlag(TrigonometricInterpolation); | |
| 542 } | 439 } |
| 543 | 440 |
| 544 SetUpMath(); | 441 SetUpMath(); |
| OLD | NEW |