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. 14define kRandomNumberStart = 2; 15 16var GlobalFloat64Array = global.Float64Array; 17var GlobalMath = global.Math; 18var GlobalObject = global.Object; 19var NaN = %GetRootNaN(); 20var nextRandomIndex = 0; 21var randomNumbers = UNDEFINED; 22var toStringTagSymbol = utils.ImportNow("to_string_tag_symbol"); 23 24//------------------------------------------------------------------- 25 26// ECMA 262 - 15.8.2.1 27function MathAbs(x) { 28 x = +x; 29 return (x > 0) ? x : 0 - x; 30} 31 32// ECMA 262 - 15.8.2.13 33function MathPowJS(x, y) { 34 return %_MathPow(TO_NUMBER(x), TO_NUMBER(y)); 35} 36 37// ECMA 262 - 15.8.2.14 38function 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 55function 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. 64function 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. 73function 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. 83function 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. 92function 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. 129utils.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. 137utils.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 153utils.Export(function(to) { 154 to.MathAbs = MathAbs; 155 to.IntRandom = MathRandomRaw; 156}); 157 158}) 159