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 3 // found in the LICENSE file. 4 5 (function(global, utils) { 6 "use strict"; 7 8 %CheckIsBootstrapping(); 9 10 // ------------------------------------------------------------------- 11 // Imports 12 13 // The first two slots are reserved to persist PRNG state. 14 define kRandomNumberStart = 2; 15 16 var GlobalFloat64Array = global.Float64Array; 17 var GlobalMath = global.Math; 18 var GlobalObject = global.Object; 19 var NaN = %GetRootNaN(); 20 var nextRandomIndex = 0; 21 var randomNumbers = UNDEFINED; 22 var toStringTagSymbol = utils.ImportNow("to_string_tag_symbol"); 23 24 //------------------------------------------------------------------- 25 26 // ECMA 262 - 15.8.2.1 27 function MathAbs(x) { 28 x = +x; 29 return (x > 0) ? x : 0 - x; 30 } 31 32 // ECMA 262 - 15.8.2.13 33 function MathPowJS(x, y) { 34 return %_MathPow(TO_NUMBER(x), TO_NUMBER(y)); 35 } 36 37 // ECMA 262 - 15.8.2.14 38 function MathRandom() { 39 // While creating a startup snapshot, %GenerateRandomNumbers returns a 40 // normal array containing a single random number, and has to be called for 41 // every new random number. 42 // Otherwise, it returns a pre-populated typed array of random numbers. The 43 // first two elements are reserved for the PRNG state. 44 if (nextRandomIndex <= kRandomNumberStart) { 45 randomNumbers = %GenerateRandomNumbers(randomNumbers); 46 if (%_IsTypedArray(randomNumbers)) { 47 nextRandomIndex = %_TypedArrayGetLength(randomNumbers); 48 } else { 49 nextRandomIndex = randomNumbers.length; 50 } 51 } 52 return randomNumbers[--nextRandomIndex]; 53 } 54 55 function MathRandomRaw() { 56 if (nextRandomIndex <= kRandomNumberStart) { 57 randomNumbers = %GenerateRandomNumbers(randomNumbers); 58 nextRandomIndex = %_TypedArrayGetLength(randomNumbers); 59 } 60 return %_DoubleLo(randomNumbers[--nextRandomIndex]) & 0x3FFFFFFF; 61 } 62 63 // ES6 draft 09-27-13, section 20.2.2.28. 64 function MathSign(x) { 65 x = +x; 66 if (x > 0) return 1; 67 if (x < 0) return -1; 68 // -0, 0 or NaN. 69 return x; 70 } 71 72 // ES6 draft 09-27-13, section 20.2.2.5. 73 function MathAsinh(x) { 74 x = TO_NUMBER(x); 75 // Idempotent for NaN, +/-0 and +/-Infinity. 76 if (x === 0 || !NUMBER_IS_FINITE(x)) return x; 77 if (x > 0) return %math_log(x + %math_sqrt(x * x + 1)); 78 // This is to prevent numerical errors caused by large negative x. 79 return -%math_log(-x + %math_sqrt(x * x + 1)); 80 } 81 82 // ES6 draft 09-27-13, section 20.2.2.3. 83 function MathAcosh(x) { 84 x = TO_NUMBER(x); 85 if (x < 1) return NaN; 86 // Idempotent for NaN and +Infinity. 87 if (!NUMBER_IS_FINITE(x)) return x; 88 return %math_log(x + %math_sqrt(x + 1) * %math_sqrt(x - 1)); 89 } 90 91 // ES6 draft 09-27-13, section 20.2.2.17. 92 function MathHypot(x, y) { // Function length is 2. 93 // We may want to introduce fast paths for two arguments and when 94 // normalization to avoid overflow is not necessary. For now, we 95 // simply assume the general case. 96 var length = arguments.length; 97 var max = 0; 98 for (var i = 0; i < length; i++) { 99 var n = MathAbs(arguments[i]); 100 if (n > max) max = n; 101 arguments[i] = n; 102 } 103 if (max === INFINITY) return INFINITY; 104 105 // Kahan summation to avoid rounding errors. 106 // Normalize the numbers to the largest one to avoid overflow. 107 if (max === 0) max = 1; 108 var sum = 0; 109 var compensation = 0; 110 for (var i = 0; i < length; i++) { 111 var n = arguments[i] / max; 112 var summand = n * n - compensation; 113 var preliminary = sum + summand; 114 compensation = (preliminary - sum) - summand; 115 sum = preliminary; 116 } 117 return %math_sqrt(sum) * max; 118 } 119 120 // ------------------------------------------------------------------- 121 122 %InstallToContext([ 123 "math_pow", MathPowJS, 124 ]); 125 126 %AddNamedProperty(GlobalMath, toStringTagSymbol, "Math", READ_ONLY | DONT_ENUM); 127 128 // Set up math constants. 129 utils.InstallConstants(GlobalMath, [ 130 "PI", 3.1415926535897932, 131 "SQRT1_2", 0.7071067811865476, 132 "SQRT2", 1.4142135623730951 133 ]); 134 135 // Set up non-enumerable functions of the Math object and 136 // set their names. 137 utils.InstallFunctions(GlobalMath, DONT_ENUM, [ 138 "random", MathRandom, 139 "abs", MathAbs, 140 "pow", MathPowJS, 141 "sign", MathSign, 142 "asinh", MathAsinh, 143 "acosh", MathAcosh, 144 "hypot", MathHypot, 145 ]); 146 147 %SetForceInlineFlag(MathRandom); 148 %SetForceInlineFlag(MathSign); 149 150 // ------------------------------------------------------------------- 151 // Exports 152 153 utils.Export(function(to) { 154 to.MathAbs = MathAbs; 155 to.IntRandom = MathRandomRaw; 156 }); 157 158 }) 159