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