blob: f4426f4a000b701bc1cf370a03e85f660b2b76bf [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
28
29// Keep reference to original values of some global properties. This
30// has the added benefit that the code in this file is isolated from
31// changes to these properties.
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000032const $floor = MathFloor;
33const $random = MathRandom;
34const $abs = MathAbs;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000035
36// Instance class name can only be set on functions. That is the only
37// purpose for MathConstructor.
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000038function MathConstructor() {}
39%FunctionSetInstanceClassName(MathConstructor, 'Math');
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000040const $Math = new MathConstructor();
fschneider@chromium.org1805e212011-09-05 10:49:12 +000041$Math.__proto__ = $Object.prototype;
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000042%SetProperty(global, "Math", $Math, DONT_ENUM);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000043
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000044// ECMA 262 - 15.8.2.1
45function MathAbs(x) {
ager@chromium.orgeadaf222009-06-16 09:43:10 +000046 if (%_IsSmi(x)) return x >= 0 ? x : -x;
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +000047 if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
vegorov@chromium.orgf8372902010-03-15 10:26:20 +000048 if (x === 0) return 0; // To handle -0.
49 return x > 0 ? x : -x;
mads.s.ager@gmail.com769cc962008-08-06 10:02:49 +000050}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000051
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000052// ECMA 262 - 15.8.2.2
ager@chromium.orgeadaf222009-06-16 09:43:10 +000053function MathAcos(x) {
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +000054 if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
ager@chromium.orgeadaf222009-06-16 09:43:10 +000055 return %Math_acos(x);
56}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000057
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000058// ECMA 262 - 15.8.2.3
ager@chromium.orgeadaf222009-06-16 09:43:10 +000059function MathAsin(x) {
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +000060 if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
ager@chromium.orgeadaf222009-06-16 09:43:10 +000061 return %Math_asin(x);
62}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000063
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000064// ECMA 262 - 15.8.2.4
ager@chromium.orgeadaf222009-06-16 09:43:10 +000065function MathAtan(x) {
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +000066 if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
ager@chromium.orgeadaf222009-06-16 09:43:10 +000067 return %Math_atan(x);
68}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000069
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000070// ECMA 262 - 15.8.2.5
kasperl@chromium.org68ac0092009-07-09 06:00:35 +000071// The naming of y and x matches the spec, as does the order in which
72// ToNumber (valueOf) is called.
73function MathAtan2(y, x) {
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +000074 if (!IS_NUMBER(y)) y = NonNumberToNumber(y);
75 if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
kasperl@chromium.org68ac0092009-07-09 06:00:35 +000076 return %Math_atan2(y, x);
ager@chromium.orgeadaf222009-06-16 09:43:10 +000077}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000078
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000079// ECMA 262 - 15.8.2.6
ager@chromium.orgeadaf222009-06-16 09:43:10 +000080function MathCeil(x) {
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +000081 if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
ager@chromium.orgeadaf222009-06-16 09:43:10 +000082 return %Math_ceil(x);
83}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000084
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000085// ECMA 262 - 15.8.2.7
ager@chromium.orgeadaf222009-06-16 09:43:10 +000086function MathCos(x) {
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +000087 if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
vegorov@chromium.orgf8372902010-03-15 10:26:20 +000088 return %_MathCos(x);
ager@chromium.orgeadaf222009-06-16 09:43:10 +000089}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000090
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000091// ECMA 262 - 15.8.2.8
ager@chromium.orgeadaf222009-06-16 09:43:10 +000092function MathExp(x) {
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +000093 if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
ager@chromium.orgeadaf222009-06-16 09:43:10 +000094 return %Math_exp(x);
95}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000096
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000097// ECMA 262 - 15.8.2.9
ager@chromium.orgeadaf222009-06-16 09:43:10 +000098function MathFloor(x) {
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +000099 if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
kasperl@chromium.org86f77b72009-07-06 08:21:57 +0000100 // It's more common to call this with a positive number that's out
101 // of range than negative numbers; check the upper bound first.
fschneider@chromium.org0c20e672010-01-14 15:28:53 +0000102 if (x < 0x80000000 && x > 0) {
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000103 // Numbers in the range [0, 2^31) can be floored by converting
104 // them to an unsigned 32-bit value using the shift operator.
105 // We avoid doing so for -0, because the result of Math.floor(-0)
106 // has to be -0, which wouldn't be the case with the shift.
fschneider@chromium.org0c20e672010-01-14 15:28:53 +0000107 return TO_UINT32(x);
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000108 } else {
109 return %Math_floor(x);
110 }
111}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000112
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000113// ECMA 262 - 15.8.2.10
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000114function MathLog(x) {
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000115 if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000116 return %_MathLog(x);
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000117}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000118
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000119// ECMA 262 - 15.8.2.11
120function MathMax(arg1, arg2) { // length == 2
kasperl@chromium.org68ac0092009-07-09 06:00:35 +0000121 var length = %_ArgumentsLength();
rossberg@chromium.orgfab14982012-01-05 15:02:15 +0000122 if (length == 2) {
123 if (!IS_NUMBER(arg1)) arg1 = NonNumberToNumber(arg1);
124 if (!IS_NUMBER(arg2)) arg2 = NonNumberToNumber(arg2);
125 if (arg2 > arg1) return arg2;
126 if (arg1 > arg2) return arg1;
127 if (arg1 == arg2) {
128 // Make sure -0 is considered less than +0. -0 is never a Smi, +0 can be
129 // a Smi or a heap number.
130 return (arg1 == 0 && !%_IsSmi(arg1) && 1 / arg1 < 0) ? arg2 : arg1;
131 }
132 // All comparisons failed, one of the arguments must be NaN.
133 return 0/0; // Compiler constant-folds this to NaN.
134 }
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000135 if (length == 0) {
136 return -1/0; // Compiler constant-folds this to -Infinity.
137 }
138 var r = arg1;
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000139 if (!IS_NUMBER(r)) r = NonNumberToNumber(r);
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000140 if (NUMBER_IS_NAN(r)) return r;
141 for (var i = 1; i < length; i++) {
142 var n = %_Arguments(i);
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000143 if (!IS_NUMBER(n)) n = NonNumberToNumber(n);
mads.s.ager@gmail.com769cc962008-08-06 10:02:49 +0000144 if (NUMBER_IS_NAN(n)) return n;
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000145 // Make sure +0 is considered greater than -0. -0 is never a Smi, +0 can be
146 // a Smi or heap number.
rossberg@chromium.orgfab14982012-01-05 15:02:15 +0000147 if (n > r || (r == 0 && n == 0 && !%_IsSmi(r) && 1 / r < 0)) r = n;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000148 }
149 return r;
150}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000151
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000152// ECMA 262 - 15.8.2.12
153function MathMin(arg1, arg2) { // length == 2
kasperl@chromium.org68ac0092009-07-09 06:00:35 +0000154 var length = %_ArgumentsLength();
rossberg@chromium.orgfab14982012-01-05 15:02:15 +0000155 if (length == 2) {
156 if (!IS_NUMBER(arg1)) arg1 = NonNumberToNumber(arg1);
157 if (!IS_NUMBER(arg2)) arg2 = NonNumberToNumber(arg2);
158 if (arg2 > arg1) return arg1;
159 if (arg1 > arg2) return arg2;
160 if (arg1 == arg2) {
161 // Make sure -0 is considered less than +0. -0 is never a Smi, +0 can be
162 // a Smi or a heap number.
163 return (arg1 == 0 && !%_IsSmi(arg1) && 1 / arg1 < 0) ? arg1 : arg2;
164 }
165 // All comparisons failed, one of the arguments must be NaN.
166 return 0/0; // Compiler constant-folds this to NaN.
167 }
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000168 if (length == 0) {
169 return 1/0; // Compiler constant-folds this to Infinity.
170 }
171 var r = arg1;
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000172 if (!IS_NUMBER(r)) r = NonNumberToNumber(r);
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000173 if (NUMBER_IS_NAN(r)) return r;
174 for (var i = 1; i < length; i++) {
175 var n = %_Arguments(i);
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000176 if (!IS_NUMBER(n)) n = NonNumberToNumber(n);
mads.s.ager@gmail.com769cc962008-08-06 10:02:49 +0000177 if (NUMBER_IS_NAN(n)) return n;
rossberg@chromium.orgfab14982012-01-05 15:02:15 +0000178 // 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 +0000179 // Smi or a heap number.
rossberg@chromium.orgfab14982012-01-05 15:02:15 +0000180 if (n < r || (r == 0 && n == 0 && !%_IsSmi(n) && 1 / n < 0)) r = n;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000181 }
182 return r;
183}
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000184
185// ECMA 262 - 15.8.2.13
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000186function MathPow(x, y) {
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000187 if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
188 if (!IS_NUMBER(y)) y = NonNumberToNumber(y);
vegorov@chromium.orgf8372902010-03-15 10:26:20 +0000189 return %_MathPow(x, y);
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000190}
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000191
192// ECMA 262 - 15.8.2.14
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000193function MathRandom() {
ager@chromium.org357bf652010-04-12 11:30:10 +0000194 return %_RandomHeapNumber();
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000195}
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000196
197// ECMA 262 - 15.8.2.15
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000198function MathRound(x) {
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000199 if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000200 return %RoundNumber(x);
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000201}
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000202
203// ECMA 262 - 15.8.2.16
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000204function MathSin(x) {
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000205 if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
vegorov@chromium.orgf8372902010-03-15 10:26:20 +0000206 return %_MathSin(x);
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000207}
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000208
209// ECMA 262 - 15.8.2.17
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000210function MathSqrt(x) {
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000211 if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
vegorov@chromium.orgf8372902010-03-15 10:26:20 +0000212 return %_MathSqrt(x);
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000213}
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000214
215// ECMA 262 - 15.8.2.18
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000216function MathTan(x) {
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000217 if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000218 return %_MathTan(x);
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000219}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000220
221
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000222// -------------------------------------------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000223
fschneider@chromium.org1805e212011-09-05 10:49:12 +0000224function SetUpMath() {
225 %CheckIsBootstrapping();
226 // Set up math constants.
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000227 // ECMA-262, section 15.8.1.1.
sgjesse@chromium.org911335c2009-08-19 12:59:44 +0000228 %OptimizeObjectForAddingMultipleProperties($Math, 8);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000229 %SetProperty($Math,
230 "E",
231 2.7182818284590452354,
232 DONT_ENUM | DONT_DELETE | READ_ONLY);
233 // ECMA-262, section 15.8.1.2.
234 %SetProperty($Math,
235 "LN10",
236 2.302585092994046,
237 DONT_ENUM | DONT_DELETE | READ_ONLY);
238 // ECMA-262, section 15.8.1.3.
239 %SetProperty($Math,
240 "LN2",
241 0.6931471805599453,
242 DONT_ENUM | DONT_DELETE | READ_ONLY);
243 // ECMA-262, section 15.8.1.4.
244 %SetProperty($Math,
245 "LOG2E",
246 1.4426950408889634,
247 DONT_ENUM | DONT_DELETE | READ_ONLY);
248 %SetProperty($Math,
249 "LOG10E",
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000250 0.4342944819032518,
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000251 DONT_ENUM | DONT_DELETE | READ_ONLY);
252 %SetProperty($Math,
253 "PI",
254 3.1415926535897932,
255 DONT_ENUM | DONT_DELETE | READ_ONLY);
256 %SetProperty($Math,
257 "SQRT1_2",
258 0.7071067811865476,
259 DONT_ENUM | DONT_DELETE | READ_ONLY);
260 %SetProperty($Math,
261 "SQRT2",
262 1.4142135623730951,
263 DONT_ENUM | DONT_DELETE | READ_ONLY);
ager@chromium.org5c838252010-02-19 08:53:10 +0000264 %ToFastProperties($Math);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000265
fschneider@chromium.org1805e212011-09-05 10:49:12 +0000266 // Set up non-enumerable functions of the Math object and
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000267 // set their names.
ricow@chromium.org27bf2882011-11-17 08:34:43 +0000268 InstallFunctions($Math, DONT_ENUM, $Array(
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000269 "random", MathRandom,
270 "abs", MathAbs,
271 "acos", MathAcos,
272 "asin", MathAsin,
273 "atan", MathAtan,
274 "ceil", MathCeil,
275 "cos", MathCos,
276 "exp", MathExp,
277 "floor", MathFloor,
278 "log", MathLog,
279 "round", MathRound,
280 "sin", MathSin,
281 "sqrt", MathSqrt,
282 "tan", MathTan,
283 "atan2", MathAtan2,
284 "pow", MathPow,
285 "max", MathMax,
286 "min", MathMin
287 ));
fschneider@chromium.org1805e212011-09-05 10:49:12 +0000288}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000289
fschneider@chromium.org1805e212011-09-05 10:49:12 +0000290SetUpMath();