blob: 9ba1934b851a7224c1ea310fd03597e5ec185707 [file] [log] [blame]
rossberg@chromium.orgfab14982012-01-05 15:02:15 +00001// Copyright 2012 the V8 project authors. All rights reserved.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +000028// This file relies on the fact that the following declarations have been made
29// in runtime.js:
30// var $Object = global.Object;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000031
32// Keep reference to original values of some global properties. This
33// has the added benefit that the code in this file is isolated from
34// changes to these properties.
jkummerow@chromium.orgf7a58842012-02-21 10:08:21 +000035var $floor = MathFloor;
jkummerow@chromium.orgf7a58842012-02-21 10:08:21 +000036var $abs = MathAbs;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000037
38// Instance class name can only be set on functions. That is the only
39// purpose for MathConstructor.
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000040function MathConstructor() {}
jkummerow@chromium.orgf7a58842012-02-21 10:08:21 +000041var $Math = new MathConstructor();
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +000042
43// -------------------------------------------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000044
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000045// ECMA 262 - 15.8.2.1
46function MathAbs(x) {
ager@chromium.orgeadaf222009-06-16 09:43:10 +000047 if (%_IsSmi(x)) return x >= 0 ? x : -x;
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +000048 if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
vegorov@chromium.orgf8372902010-03-15 10:26:20 +000049 if (x === 0) return 0; // To handle -0.
50 return x > 0 ? x : -x;
mads.s.ager@gmail.com769cc962008-08-06 10:02:49 +000051}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000052
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000053// ECMA 262 - 15.8.2.2
ager@chromium.orgeadaf222009-06-16 09:43:10 +000054function MathAcos(x) {
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +000055 if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
ager@chromium.orgeadaf222009-06-16 09:43:10 +000056 return %Math_acos(x);
57}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000058
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000059// ECMA 262 - 15.8.2.3
ager@chromium.orgeadaf222009-06-16 09:43:10 +000060function MathAsin(x) {
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +000061 if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
ager@chromium.orgeadaf222009-06-16 09:43:10 +000062 return %Math_asin(x);
63}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000064
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000065// ECMA 262 - 15.8.2.4
ager@chromium.orgeadaf222009-06-16 09:43:10 +000066function MathAtan(x) {
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +000067 if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
ager@chromium.orgeadaf222009-06-16 09:43:10 +000068 return %Math_atan(x);
69}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000070
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000071// ECMA 262 - 15.8.2.5
kasperl@chromium.org68ac0092009-07-09 06:00:35 +000072// The naming of y and x matches the spec, as does the order in which
73// ToNumber (valueOf) is called.
74function MathAtan2(y, x) {
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +000075 if (!IS_NUMBER(y)) y = NonNumberToNumber(y);
76 if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
kasperl@chromium.org68ac0092009-07-09 06:00:35 +000077 return %Math_atan2(y, x);
ager@chromium.orgeadaf222009-06-16 09:43:10 +000078}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000079
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000080// ECMA 262 - 15.8.2.6
ager@chromium.orgeadaf222009-06-16 09:43:10 +000081function MathCeil(x) {
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +000082 if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
ager@chromium.orgeadaf222009-06-16 09:43:10 +000083 return %Math_ceil(x);
84}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000085
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000086// ECMA 262 - 15.8.2.7
ager@chromium.orgeadaf222009-06-16 09:43:10 +000087function MathCos(x) {
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +000088 if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
vegorov@chromium.orgf8372902010-03-15 10:26:20 +000089 return %_MathCos(x);
ager@chromium.orgeadaf222009-06-16 09:43:10 +000090}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000091
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000092// ECMA 262 - 15.8.2.8
ager@chromium.orgeadaf222009-06-16 09:43:10 +000093function MathExp(x) {
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +000094 if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
ager@chromium.orgeadaf222009-06-16 09:43:10 +000095 return %Math_exp(x);
96}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000097
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000098// ECMA 262 - 15.8.2.9
ager@chromium.orgeadaf222009-06-16 09:43:10 +000099function MathFloor(x) {
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000100 if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
kasperl@chromium.org86f77b72009-07-06 08:21:57 +0000101 // It's more common to call this with a positive number that's out
102 // of range than negative numbers; check the upper bound first.
fschneider@chromium.org0c20e672010-01-14 15:28:53 +0000103 if (x < 0x80000000 && x > 0) {
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000104 // Numbers in the range [0, 2^31) can be floored by converting
105 // them to an unsigned 32-bit value using the shift operator.
106 // We avoid doing so for -0, because the result of Math.floor(-0)
107 // has to be -0, which wouldn't be the case with the shift.
fschneider@chromium.org0c20e672010-01-14 15:28:53 +0000108 return TO_UINT32(x);
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000109 } else {
110 return %Math_floor(x);
111 }
112}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000113
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000114// ECMA 262 - 15.8.2.10
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000115function MathLog(x) {
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000116 if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000117 return %_MathLog(x);
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000118}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000119
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000120// ECMA 262 - 15.8.2.11
121function MathMax(arg1, arg2) { // length == 2
kasperl@chromium.org68ac0092009-07-09 06:00:35 +0000122 var length = %_ArgumentsLength();
rossberg@chromium.orgfab14982012-01-05 15:02:15 +0000123 if (length == 2) {
124 if (!IS_NUMBER(arg1)) arg1 = NonNumberToNumber(arg1);
125 if (!IS_NUMBER(arg2)) arg2 = NonNumberToNumber(arg2);
126 if (arg2 > arg1) return arg2;
127 if (arg1 > arg2) return arg1;
128 if (arg1 == arg2) {
129 // Make sure -0 is considered less than +0. -0 is never a Smi, +0 can be
130 // a Smi or a heap number.
131 return (arg1 == 0 && !%_IsSmi(arg1) && 1 / arg1 < 0) ? arg2 : arg1;
132 }
133 // All comparisons failed, one of the arguments must be NaN.
134 return 0/0; // Compiler constant-folds this to NaN.
135 }
mstarzinger@chromium.org32280cf2012-12-06 17:32:37 +0000136 var r = -1/0; // Compiler constant-folds this to -Infinity.
137 for (var i = 0; i < length; i++) {
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000138 var n = %_Arguments(i);
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000139 if (!IS_NUMBER(n)) n = NonNumberToNumber(n);
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000140 // Make sure +0 is considered greater than -0. -0 is never a Smi, +0 can be
141 // a Smi or heap number.
mstarzinger@chromium.org32280cf2012-12-06 17:32:37 +0000142 if (NUMBER_IS_NAN(n) || n > r ||
143 (r == 0 && n == 0 && !%_IsSmi(r) && 1 / r < 0)) {
144 r = n;
145 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000146 }
147 return r;
148}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000149
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000150// ECMA 262 - 15.8.2.12
151function MathMin(arg1, arg2) { // length == 2
kasperl@chromium.org68ac0092009-07-09 06:00:35 +0000152 var length = %_ArgumentsLength();
rossberg@chromium.orgfab14982012-01-05 15:02:15 +0000153 if (length == 2) {
154 if (!IS_NUMBER(arg1)) arg1 = NonNumberToNumber(arg1);
155 if (!IS_NUMBER(arg2)) arg2 = NonNumberToNumber(arg2);
156 if (arg2 > arg1) return arg1;
157 if (arg1 > arg2) return arg2;
158 if (arg1 == arg2) {
159 // Make sure -0 is considered less than +0. -0 is never a Smi, +0 can be
160 // a Smi or a heap number.
161 return (arg1 == 0 && !%_IsSmi(arg1) && 1 / arg1 < 0) ? arg1 : arg2;
162 }
163 // All comparisons failed, one of the arguments must be NaN.
164 return 0/0; // Compiler constant-folds this to NaN.
165 }
mstarzinger@chromium.org32280cf2012-12-06 17:32:37 +0000166 var r = 1/0; // Compiler constant-folds this to Infinity.
167 for (var i = 0; i < length; i++) {
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000168 var n = %_Arguments(i);
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000169 if (!IS_NUMBER(n)) n = NonNumberToNumber(n);
rossberg@chromium.orgfab14982012-01-05 15:02:15 +0000170 // Make sure -0 is considered less than +0. -0 is never a Smi, +0 can be a
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000171 // Smi or a heap number.
mstarzinger@chromium.org32280cf2012-12-06 17:32:37 +0000172 if (NUMBER_IS_NAN(n) || n < r ||
173 (r == 0 && n == 0 && !%_IsSmi(n) && 1 / n < 0)) {
174 r = n;
175 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000176 }
177 return r;
178}
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000179
180// ECMA 262 - 15.8.2.13
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000181function MathPow(x, y) {
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000182 if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
183 if (!IS_NUMBER(y)) y = NonNumberToNumber(y);
vegorov@chromium.orgf8372902010-03-15 10:26:20 +0000184 return %_MathPow(x, y);
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000185}
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000186
187// ECMA 262 - 15.8.2.14
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000188function MathRandom() {
ager@chromium.org357bf652010-04-12 11:30:10 +0000189 return %_RandomHeapNumber();
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000190}
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000191
192// ECMA 262 - 15.8.2.15
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000193function MathRound(x) {
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000194 if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000195 return %RoundNumber(x);
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000196}
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000197
198// ECMA 262 - 15.8.2.16
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000199function MathSin(x) {
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000200 if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
vegorov@chromium.orgf8372902010-03-15 10:26:20 +0000201 return %_MathSin(x);
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000202}
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000203
204// ECMA 262 - 15.8.2.17
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000205function MathSqrt(x) {
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000206 if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
vegorov@chromium.orgf8372902010-03-15 10:26:20 +0000207 return %_MathSqrt(x);
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000208}
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000209
210// ECMA 262 - 15.8.2.18
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000211function MathTan(x) {
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000212 if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000213 return %_MathTan(x);
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000214}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000215
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000216// Non-standard extension.
217function MathImul(x, y) {
218 if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
219 if (!IS_NUMBER(y)) y = NonNumberToNumber(y);
220 return %NumberImul(x, y);
221}
222
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000223
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000224// -------------------------------------------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000225
fschneider@chromium.org1805e212011-09-05 10:49:12 +0000226function SetUpMath() {
227 %CheckIsBootstrapping();
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000228
229 %SetPrototype($Math, $Object.prototype);
230 %SetProperty(global, "Math", $Math, DONT_ENUM);
231 %FunctionSetInstanceClassName(MathConstructor, 'Math');
232
fschneider@chromium.org1805e212011-09-05 10:49:12 +0000233 // Set up math constants.
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000234 // ECMA-262, section 15.8.1.1.
sgjesse@chromium.org911335c2009-08-19 12:59:44 +0000235 %OptimizeObjectForAddingMultipleProperties($Math, 8);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000236 %SetProperty($Math,
237 "E",
238 2.7182818284590452354,
239 DONT_ENUM | DONT_DELETE | READ_ONLY);
240 // ECMA-262, section 15.8.1.2.
241 %SetProperty($Math,
242 "LN10",
243 2.302585092994046,
244 DONT_ENUM | DONT_DELETE | READ_ONLY);
245 // ECMA-262, section 15.8.1.3.
246 %SetProperty($Math,
247 "LN2",
248 0.6931471805599453,
249 DONT_ENUM | DONT_DELETE | READ_ONLY);
250 // ECMA-262, section 15.8.1.4.
251 %SetProperty($Math,
252 "LOG2E",
253 1.4426950408889634,
254 DONT_ENUM | DONT_DELETE | READ_ONLY);
255 %SetProperty($Math,
256 "LOG10E",
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000257 0.4342944819032518,
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000258 DONT_ENUM | DONT_DELETE | READ_ONLY);
259 %SetProperty($Math,
260 "PI",
261 3.1415926535897932,
262 DONT_ENUM | DONT_DELETE | READ_ONLY);
263 %SetProperty($Math,
264 "SQRT1_2",
265 0.7071067811865476,
266 DONT_ENUM | DONT_DELETE | READ_ONLY);
267 %SetProperty($Math,
268 "SQRT2",
269 1.4142135623730951,
270 DONT_ENUM | DONT_DELETE | READ_ONLY);
ager@chromium.org5c838252010-02-19 08:53:10 +0000271 %ToFastProperties($Math);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000272
fschneider@chromium.org1805e212011-09-05 10:49:12 +0000273 // Set up non-enumerable functions of the Math object and
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000274 // set their names.
ricow@chromium.org27bf2882011-11-17 08:34:43 +0000275 InstallFunctions($Math, DONT_ENUM, $Array(
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000276 "random", MathRandom,
277 "abs", MathAbs,
278 "acos", MathAcos,
279 "asin", MathAsin,
280 "atan", MathAtan,
281 "ceil", MathCeil,
282 "cos", MathCos,
283 "exp", MathExp,
284 "floor", MathFloor,
285 "log", MathLog,
286 "round", MathRound,
287 "sin", MathSin,
288 "sqrt", MathSqrt,
289 "tan", MathTan,
290 "atan2", MathAtan2,
291 "pow", MathPow,
292 "max", MathMax,
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000293 "min", MathMin,
294 "imul", MathImul
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000295 ));
fschneider@chromium.org1805e212011-09-05 10:49:12 +0000296}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000297
fschneider@chromium.org1805e212011-09-05 10:49:12 +0000298SetUpMath();