• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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