blob: 74d3aa6562f593f3e9283259410348db20a2d862 [file] [log] [blame]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001// 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
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013// 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;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019var NaN = %GetRootNaN();
Ben Murdochda12d292016-06-02 14:46:10 +010020var nextRandomIndex = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021var 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
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000032// 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() {
Ben Murdochda12d292016-06-02 14:46:10 +010039 // 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) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000045 randomNumbers = %GenerateRandomNumbers(randomNumbers);
Ben Murdoch61f157c2016-09-16 13:49:30 +010046 if (%_IsTypedArray(randomNumbers)) {
47 nextRandomIndex = %_TypedArrayGetLength(randomNumbers);
48 } else {
49 nextRandomIndex = randomNumbers.length;
50 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000051 }
Ben Murdochda12d292016-06-02 14:46:10 +010052 return randomNumbers[--nextRandomIndex];
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000053}
54
55function MathRandomRaw() {
Ben Murdochda12d292016-06-02 14:46:10 +010056 if (nextRandomIndex <= kRandomNumberStart) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000057 randomNumbers = %GenerateRandomNumbers(randomNumbers);
Ben Murdoch61f157c2016-09-16 13:49:30 +010058 nextRandomIndex = %_TypedArrayGetLength(randomNumbers);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000059 }
Ben Murdochda12d292016-06-02 14:46:10 +010060 return %_DoubleLo(randomNumbers[--nextRandomIndex]) & 0x3FFFFFFF;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000061}
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
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000072// 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;
Ben Murdoch61f157c2016-09-16 13:49:30 +010077 if (x > 0) return %math_log(x + %math_sqrt(x * x + 1));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000078 // This is to prevent numerical errors caused by large negative x.
Ben Murdoch61f157c2016-09-16 13:49:30 +010079 return -%math_log(-x + %math_sqrt(x * x + 1));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000080}
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;
Ben Murdoch61f157c2016-09-16 13:49:30 +010088 return %math_log(x + %math_sqrt(x + 1) * %math_sqrt(x - 1));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000089}
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.
Ben Murdoch097c5b22016-05-18 11:27:45 +010096 var length = arguments.length;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000097 var max = 0;
98 for (var i = 0; i < length; i++) {
Ben Murdoch097c5b22016-05-18 11:27:45 +010099 var n = MathAbs(arguments[i]);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000100 if (n > max) max = n;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100101 arguments[i] = n;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000102 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100103 if (max === INFINITY) return INFINITY;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000104
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++) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100111 var n = arguments[i] / max;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000112 var summand = n * n - compensation;
113 var preliminary = sum + summand;
114 compensation = (preliminary - sum) - summand;
115 sum = preliminary;
116 }
Ben Murdochda12d292016-06-02 14:46:10 +0100117 return %math_sqrt(sum) * max;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000118}
119
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000120// -------------------------------------------------------------------
121
Ben Murdochda12d292016-06-02 14:46:10 +0100122%InstallToContext([
123 "math_pow", MathPowJS,
124]);
125
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000126%AddNamedProperty(GlobalMath, toStringTagSymbol, "Math", READ_ONLY | DONT_ENUM);
127
128// Set up math constants.
129utils.InstallConstants(GlobalMath, [
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000130 "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,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000140 "pow", MathPowJS,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000141 "sign", MathSign,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000142 "asinh", MathAsinh,
143 "acosh", MathAcosh,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000144 "hypot", MathHypot,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000145]);
146
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000147%SetForceInlineFlag(MathRandom);
148%SetForceInlineFlag(MathSign);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000149
150// -------------------------------------------------------------------
151// Exports
152
153utils.Export(function(to) {
154 to.MathAbs = MathAbs;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000155 to.IntRandom = MathRandomRaw;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000156});
157
158})