blob: aee56af4f9916d526695b91420ad7150fc95792e [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.
jkummerow@chromium.orgf7a58842012-02-21 10:08:21 +000032var $floor = MathFloor;
jkummerow@chromium.orgf7a58842012-02-21 10:08:21 +000033var $abs = MathAbs;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000034
35// Instance class name can only be set on functions. That is the only
36// purpose for MathConstructor.
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000037function MathConstructor() {}
38%FunctionSetInstanceClassName(MathConstructor, 'Math');
jkummerow@chromium.orgf7a58842012-02-21 10:08:21 +000039var $Math = new MathConstructor();
fschneider@chromium.org1805e212011-09-05 10:49:12 +000040$Math.__proto__ = $Object.prototype;
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000041%SetProperty(global, "Math", $Math, DONT_ENUM);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000042
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000043// ECMA 262 - 15.8.2.1
44function MathAbs(x) {
ager@chromium.orgeadaf222009-06-16 09:43:10 +000045 if (%_IsSmi(x)) return x >= 0 ? x : -x;
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +000046 if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
vegorov@chromium.orgf8372902010-03-15 10:26:20 +000047 if (x === 0) return 0; // To handle -0.
48 return x > 0 ? x : -x;
mads.s.ager@gmail.com769cc962008-08-06 10:02:49 +000049}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000050
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000051// ECMA 262 - 15.8.2.2
ager@chromium.orgeadaf222009-06-16 09:43:10 +000052function MathAcos(x) {
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +000053 if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
ager@chromium.orgeadaf222009-06-16 09:43:10 +000054 return %Math_acos(x);
55}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000056
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000057// ECMA 262 - 15.8.2.3
ager@chromium.orgeadaf222009-06-16 09:43:10 +000058function MathAsin(x) {
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +000059 if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
ager@chromium.orgeadaf222009-06-16 09:43:10 +000060 return %Math_asin(x);
61}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000062
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000063// ECMA 262 - 15.8.2.4
ager@chromium.orgeadaf222009-06-16 09:43:10 +000064function MathAtan(x) {
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +000065 if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
ager@chromium.orgeadaf222009-06-16 09:43:10 +000066 return %Math_atan(x);
67}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000068
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000069// ECMA 262 - 15.8.2.5
kasperl@chromium.org68ac0092009-07-09 06:00:35 +000070// The naming of y and x matches the spec, as does the order in which
71// ToNumber (valueOf) is called.
72function MathAtan2(y, x) {
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +000073 if (!IS_NUMBER(y)) y = NonNumberToNumber(y);
74 if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
kasperl@chromium.org68ac0092009-07-09 06:00:35 +000075 return %Math_atan2(y, x);
ager@chromium.orgeadaf222009-06-16 09:43:10 +000076}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000077
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000078// ECMA 262 - 15.8.2.6
ager@chromium.orgeadaf222009-06-16 09:43:10 +000079function MathCeil(x) {
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +000080 if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
ager@chromium.orgeadaf222009-06-16 09:43:10 +000081 return %Math_ceil(x);
82}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000083
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000084// ECMA 262 - 15.8.2.7
ager@chromium.orgeadaf222009-06-16 09:43:10 +000085function MathCos(x) {
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +000086 if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
vegorov@chromium.orgf8372902010-03-15 10:26:20 +000087 return %_MathCos(x);
ager@chromium.orgeadaf222009-06-16 09:43:10 +000088}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000089
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000090// ECMA 262 - 15.8.2.8
ager@chromium.orgeadaf222009-06-16 09:43:10 +000091function MathExp(x) {
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +000092 if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
ager@chromium.orgeadaf222009-06-16 09:43:10 +000093 return %Math_exp(x);
94}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000095
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000096// ECMA 262 - 15.8.2.9
ager@chromium.orgeadaf222009-06-16 09:43:10 +000097function MathFloor(x) {
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +000098 if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
kasperl@chromium.org86f77b72009-07-06 08:21:57 +000099 // It's more common to call this with a positive number that's out
100 // of range than negative numbers; check the upper bound first.
fschneider@chromium.org0c20e672010-01-14 15:28:53 +0000101 if (x < 0x80000000 && x > 0) {
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000102 // Numbers in the range [0, 2^31) can be floored by converting
103 // them to an unsigned 32-bit value using the shift operator.
104 // We avoid doing so for -0, because the result of Math.floor(-0)
105 // has to be -0, which wouldn't be the case with the shift.
fschneider@chromium.org0c20e672010-01-14 15:28:53 +0000106 return TO_UINT32(x);
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000107 } else {
108 return %Math_floor(x);
109 }
110}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000111
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000112// ECMA 262 - 15.8.2.10
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000113function MathLog(x) {
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000114 if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000115 return %_MathLog(x);
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000116}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000117
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000118// ECMA 262 - 15.8.2.11
119function MathMax(arg1, arg2) { // length == 2
kasperl@chromium.org68ac0092009-07-09 06:00:35 +0000120 var length = %_ArgumentsLength();
rossberg@chromium.orgfab14982012-01-05 15:02:15 +0000121 if (length == 2) {
122 if (!IS_NUMBER(arg1)) arg1 = NonNumberToNumber(arg1);
123 if (!IS_NUMBER(arg2)) arg2 = NonNumberToNumber(arg2);
124 if (arg2 > arg1) return arg2;
125 if (arg1 > arg2) return arg1;
126 if (arg1 == arg2) {
127 // Make sure -0 is considered less than +0. -0 is never a Smi, +0 can be
128 // a Smi or a heap number.
129 return (arg1 == 0 && !%_IsSmi(arg1) && 1 / arg1 < 0) ? arg2 : arg1;
130 }
131 // All comparisons failed, one of the arguments must be NaN.
132 return 0/0; // Compiler constant-folds this to NaN.
133 }
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000134 if (length == 0) {
135 return -1/0; // Compiler constant-folds this to -Infinity.
136 }
137 var r = arg1;
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000138 if (!IS_NUMBER(r)) r = NonNumberToNumber(r);
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000139 if (NUMBER_IS_NAN(r)) return r;
140 for (var i = 1; i < length; i++) {
141 var n = %_Arguments(i);
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000142 if (!IS_NUMBER(n)) n = NonNumberToNumber(n);
mads.s.ager@gmail.com769cc962008-08-06 10:02:49 +0000143 if (NUMBER_IS_NAN(n)) return n;
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000144 // Make sure +0 is considered greater than -0. -0 is never a Smi, +0 can be
145 // a Smi or heap number.
rossberg@chromium.orgfab14982012-01-05 15:02:15 +0000146 if (n > r || (r == 0 && n == 0 && !%_IsSmi(r) && 1 / r < 0)) r = n;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000147 }
148 return r;
149}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000150
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000151// ECMA 262 - 15.8.2.12
152function MathMin(arg1, arg2) { // length == 2
kasperl@chromium.org68ac0092009-07-09 06:00:35 +0000153 var length = %_ArgumentsLength();
rossberg@chromium.orgfab14982012-01-05 15:02:15 +0000154 if (length == 2) {
155 if (!IS_NUMBER(arg1)) arg1 = NonNumberToNumber(arg1);
156 if (!IS_NUMBER(arg2)) arg2 = NonNumberToNumber(arg2);
157 if (arg2 > arg1) return arg1;
158 if (arg1 > arg2) return arg2;
159 if (arg1 == arg2) {
160 // Make sure -0 is considered less than +0. -0 is never a Smi, +0 can be
161 // a Smi or a heap number.
162 return (arg1 == 0 && !%_IsSmi(arg1) && 1 / arg1 < 0) ? arg1 : arg2;
163 }
164 // All comparisons failed, one of the arguments must be NaN.
165 return 0/0; // Compiler constant-folds this to NaN.
166 }
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000167 if (length == 0) {
168 return 1/0; // Compiler constant-folds this to Infinity.
169 }
170 var r = arg1;
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000171 if (!IS_NUMBER(r)) r = NonNumberToNumber(r);
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000172 if (NUMBER_IS_NAN(r)) return r;
173 for (var i = 1; i < length; i++) {
174 var n = %_Arguments(i);
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000175 if (!IS_NUMBER(n)) n = NonNumberToNumber(n);
mads.s.ager@gmail.com769cc962008-08-06 10:02:49 +0000176 if (NUMBER_IS_NAN(n)) return n;
rossberg@chromium.orgfab14982012-01-05 15:02:15 +0000177 // 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 +0000178 // Smi or a heap number.
rossberg@chromium.orgfab14982012-01-05 15:02:15 +0000179 if (n < r || (r == 0 && n == 0 && !%_IsSmi(n) && 1 / n < 0)) r = n;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000180 }
181 return r;
182}
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000183
184// ECMA 262 - 15.8.2.13
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000185function MathPow(x, y) {
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000186 if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
187 if (!IS_NUMBER(y)) y = NonNumberToNumber(y);
vegorov@chromium.orgf8372902010-03-15 10:26:20 +0000188 return %_MathPow(x, y);
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000189}
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000190
191// ECMA 262 - 15.8.2.14
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000192function MathRandom() {
ager@chromium.org357bf652010-04-12 11:30:10 +0000193 return %_RandomHeapNumber();
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000194}
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000195
196// ECMA 262 - 15.8.2.15
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000197function MathRound(x) {
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000198 if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000199 return %RoundNumber(x);
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000200}
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000201
202// ECMA 262 - 15.8.2.16
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000203function MathSin(x) {
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000204 if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
vegorov@chromium.orgf8372902010-03-15 10:26:20 +0000205 return %_MathSin(x);
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000206}
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000207
208// ECMA 262 - 15.8.2.17
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000209function MathSqrt(x) {
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000210 if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
vegorov@chromium.orgf8372902010-03-15 10:26:20 +0000211 return %_MathSqrt(x);
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000212}
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000213
214// ECMA 262 - 15.8.2.18
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000215function MathTan(x) {
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000216 if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000217 return %_MathTan(x);
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000218}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000219
220
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000221// -------------------------------------------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000222
fschneider@chromium.org1805e212011-09-05 10:49:12 +0000223function SetUpMath() {
224 %CheckIsBootstrapping();
225 // Set up math constants.
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000226 // ECMA-262, section 15.8.1.1.
sgjesse@chromium.org911335c2009-08-19 12:59:44 +0000227 %OptimizeObjectForAddingMultipleProperties($Math, 8);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000228 %SetProperty($Math,
229 "E",
230 2.7182818284590452354,
231 DONT_ENUM | DONT_DELETE | READ_ONLY);
232 // ECMA-262, section 15.8.1.2.
233 %SetProperty($Math,
234 "LN10",
235 2.302585092994046,
236 DONT_ENUM | DONT_DELETE | READ_ONLY);
237 // ECMA-262, section 15.8.1.3.
238 %SetProperty($Math,
239 "LN2",
240 0.6931471805599453,
241 DONT_ENUM | DONT_DELETE | READ_ONLY);
242 // ECMA-262, section 15.8.1.4.
243 %SetProperty($Math,
244 "LOG2E",
245 1.4426950408889634,
246 DONT_ENUM | DONT_DELETE | READ_ONLY);
247 %SetProperty($Math,
248 "LOG10E",
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000249 0.4342944819032518,
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000250 DONT_ENUM | DONT_DELETE | READ_ONLY);
251 %SetProperty($Math,
252 "PI",
253 3.1415926535897932,
254 DONT_ENUM | DONT_DELETE | READ_ONLY);
255 %SetProperty($Math,
256 "SQRT1_2",
257 0.7071067811865476,
258 DONT_ENUM | DONT_DELETE | READ_ONLY);
259 %SetProperty($Math,
260 "SQRT2",
261 1.4142135623730951,
262 DONT_ENUM | DONT_DELETE | READ_ONLY);
ager@chromium.org5c838252010-02-19 08:53:10 +0000263 %ToFastProperties($Math);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000264
fschneider@chromium.org1805e212011-09-05 10:49:12 +0000265 // Set up non-enumerable functions of the Math object and
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000266 // set their names.
ricow@chromium.org27bf2882011-11-17 08:34:43 +0000267 InstallFunctions($Math, DONT_ENUM, $Array(
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000268 "random", MathRandom,
269 "abs", MathAbs,
270 "acos", MathAcos,
271 "asin", MathAsin,
272 "atan", MathAtan,
273 "ceil", MathCeil,
274 "cos", MathCos,
275 "exp", MathExp,
276 "floor", MathFloor,
277 "log", MathLog,
278 "round", MathRound,
279 "sin", MathSin,
280 "sqrt", MathSqrt,
281 "tan", MathTan,
282 "atan2", MathAtan2,
283 "pow", MathPow,
284 "max", MathMax,
285 "min", MathMin
286 ));
fschneider@chromium.org1805e212011-09-05 10:49:12 +0000287}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000288
fschneider@chromium.org1805e212011-09-05 10:49:12 +0000289SetUpMath();