blob: f8ad6b1fe67ebc9e3cdf5e6ad9720414aefaa7c9 [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;
19var InternalArray = utils.InternalArray;
20var NaN = %GetRootNaN();
Ben Murdochda12d292016-06-02 14:46:10 +010021var nextRandomIndex = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022var randomNumbers = UNDEFINED;
23var toStringTagSymbol = utils.ImportNow("to_string_tag_symbol");
24
25//-------------------------------------------------------------------
26
27// ECMA 262 - 15.8.2.1
28function MathAbs(x) {
29 x = +x;
30 return (x > 0) ? x : 0 - x;
31}
32
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000033// ECMA 262 - 15.8.2.5
34// The naming of y and x matches the spec, as does the order in which
35// ToNumber (valueOf) is called.
36function MathAtan2JS(y, x) {
37 y = +y;
38 x = +x;
Ben Murdochda12d292016-06-02 14:46:10 +010039 return %MathAtan2(y, x);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000040}
41
42// ECMA 262 - 15.8.2.8
43function MathExp(x) {
44 return %MathExpRT(TO_NUMBER(x));
45}
46
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000047// ECMA 262 - 15.8.2.10
48function MathLog(x) {
49 return %_MathLogRT(TO_NUMBER(x));
50}
51
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000052// ECMA 262 - 15.8.2.13
53function MathPowJS(x, y) {
54 return %_MathPow(TO_NUMBER(x), TO_NUMBER(y));
55}
56
57// ECMA 262 - 15.8.2.14
58function MathRandom() {
Ben Murdochda12d292016-06-02 14:46:10 +010059 // While creating a startup snapshot, %GenerateRandomNumbers returns a
60 // normal array containing a single random number, and has to be called for
61 // every new random number.
62 // Otherwise, it returns a pre-populated typed array of random numbers. The
63 // first two elements are reserved for the PRNG state.
64 if (nextRandomIndex <= kRandomNumberStart) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000065 randomNumbers = %GenerateRandomNumbers(randomNumbers);
Ben Murdochda12d292016-06-02 14:46:10 +010066 nextRandomIndex = randomNumbers.length;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000067 }
Ben Murdochda12d292016-06-02 14:46:10 +010068 return randomNumbers[--nextRandomIndex];
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000069}
70
71function MathRandomRaw() {
Ben Murdochda12d292016-06-02 14:46:10 +010072 if (nextRandomIndex <= kRandomNumberStart) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000073 randomNumbers = %GenerateRandomNumbers(randomNumbers);
Ben Murdochda12d292016-06-02 14:46:10 +010074 nextRandomIndex = randomNumbers.length;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000075 }
Ben Murdochda12d292016-06-02 14:46:10 +010076 return %_DoubleLo(randomNumbers[--nextRandomIndex]) & 0x3FFFFFFF;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000077}
78
79// ES6 draft 09-27-13, section 20.2.2.28.
80function MathSign(x) {
81 x = +x;
82 if (x > 0) return 1;
83 if (x < 0) return -1;
84 // -0, 0 or NaN.
85 return x;
86}
87
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000088// ES6 draft 09-27-13, section 20.2.2.5.
89function MathAsinh(x) {
90 x = TO_NUMBER(x);
91 // Idempotent for NaN, +/-0 and +/-Infinity.
92 if (x === 0 || !NUMBER_IS_FINITE(x)) return x;
Ben Murdochda12d292016-06-02 14:46:10 +010093 if (x > 0) return MathLog(x + %math_sqrt(x * x + 1));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000094 // This is to prevent numerical errors caused by large negative x.
Ben Murdochda12d292016-06-02 14:46:10 +010095 return -MathLog(-x + %math_sqrt(x * x + 1));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000096}
97
98// ES6 draft 09-27-13, section 20.2.2.3.
99function MathAcosh(x) {
100 x = TO_NUMBER(x);
101 if (x < 1) return NaN;
102 // Idempotent for NaN and +Infinity.
103 if (!NUMBER_IS_FINITE(x)) return x;
Ben Murdochda12d292016-06-02 14:46:10 +0100104 return MathLog(x + %math_sqrt(x + 1) * %math_sqrt(x - 1));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000105}
106
107// ES6 draft 09-27-13, section 20.2.2.7.
108function MathAtanh(x) {
109 x = TO_NUMBER(x);
110 // Idempotent for +/-0.
111 if (x === 0) return x;
112 // Returns NaN for NaN and +/- Infinity.
113 if (!NUMBER_IS_FINITE(x)) return NaN;
114 return 0.5 * MathLog((1 + x) / (1 - x));
115}
116
117// ES6 draft 09-27-13, section 20.2.2.17.
118function MathHypot(x, y) { // Function length is 2.
119 // We may want to introduce fast paths for two arguments and when
120 // normalization to avoid overflow is not necessary. For now, we
121 // simply assume the general case.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100122 var length = arguments.length;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000123 var max = 0;
124 for (var i = 0; i < length; i++) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100125 var n = MathAbs(arguments[i]);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000126 if (n > max) max = n;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100127 arguments[i] = n;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000128 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100129 if (max === INFINITY) return INFINITY;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000130
131 // Kahan summation to avoid rounding errors.
132 // Normalize the numbers to the largest one to avoid overflow.
133 if (max === 0) max = 1;
134 var sum = 0;
135 var compensation = 0;
136 for (var i = 0; i < length; i++) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100137 var n = arguments[i] / max;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000138 var summand = n * n - compensation;
139 var preliminary = sum + summand;
140 compensation = (preliminary - sum) - summand;
141 sum = preliminary;
142 }
Ben Murdochda12d292016-06-02 14:46:10 +0100143 return %math_sqrt(sum) * max;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000144}
145
146// ES6 draft 09-27-13, section 20.2.2.9.
147// Cube root approximation, refer to: http://metamerist.com/cbrt/cbrt.htm
148// Using initial approximation adapted from Kahan's cbrt and 4 iterations
149// of Newton's method.
150function MathCbrt(x) {
151 x = TO_NUMBER(x);
152 if (x == 0 || !NUMBER_IS_FINITE(x)) return x;
153 return x >= 0 ? CubeRoot(x) : -CubeRoot(-x);
154}
155
156macro NEWTON_ITERATION_CBRT(x, approx)
157 (1.0 / 3.0) * (x / (approx * approx) + 2 * approx);
158endmacro
159
160function CubeRoot(x) {
Ben Murdochda12d292016-06-02 14:46:10 +0100161 var approx_hi = %math_floor(%_DoubleHi(x) / 3) + 0x2A9F7893;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000162 var approx = %_ConstructDouble(approx_hi | 0, 0);
163 approx = NEWTON_ITERATION_CBRT(x, approx);
164 approx = NEWTON_ITERATION_CBRT(x, approx);
165 approx = NEWTON_ITERATION_CBRT(x, approx);
166 return NEWTON_ITERATION_CBRT(x, approx);
167}
168
169// -------------------------------------------------------------------
170
Ben Murdochda12d292016-06-02 14:46:10 +0100171%InstallToContext([
172 "math_pow", MathPowJS,
173]);
174
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000175%AddNamedProperty(GlobalMath, toStringTagSymbol, "Math", READ_ONLY | DONT_ENUM);
176
177// Set up math constants.
178utils.InstallConstants(GlobalMath, [
179 // ECMA-262, section 15.8.1.1.
180 "E", 2.7182818284590452354,
181 // ECMA-262, section 15.8.1.2.
182 "LN10", 2.302585092994046,
183 // ECMA-262, section 15.8.1.3.
184 "LN2", 0.6931471805599453,
185 // ECMA-262, section 15.8.1.4.
186 "LOG2E", 1.4426950408889634,
187 "LOG10E", 0.4342944819032518,
188 "PI", 3.1415926535897932,
189 "SQRT1_2", 0.7071067811865476,
190 "SQRT2", 1.4142135623730951
191]);
192
193// Set up non-enumerable functions of the Math object and
194// set their names.
195utils.InstallFunctions(GlobalMath, DONT_ENUM, [
196 "random", MathRandom,
197 "abs", MathAbs,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000198 "exp", MathExp,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000199 "log", MathLog,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000200 "atan2", MathAtan2JS,
201 "pow", MathPowJS,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000202 "sign", MathSign,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000203 "asinh", MathAsinh,
204 "acosh", MathAcosh,
205 "atanh", MathAtanh,
206 "hypot", MathHypot,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000207 "cbrt", MathCbrt
208]);
209
210%SetForceInlineFlag(MathAbs);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000211%SetForceInlineFlag(MathAtan2JS);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000212%SetForceInlineFlag(MathRandom);
213%SetForceInlineFlag(MathSign);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000214
215// -------------------------------------------------------------------
216// Exports
217
218utils.Export(function(to) {
219 to.MathAbs = MathAbs;
220 to.MathExp = MathExp;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000221 to.IntRandom = MathRandomRaw;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000222});
223
224})