blob: 46863284f08b1b888400c2065a97b9cd6a2aaa75 [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 }
mstarzinger@chromium.org32280cf2012-12-06 17:32:37 +0000134 var r = -1/0; // Compiler constant-folds this to -Infinity.
135 for (var i = 0; i < length; i++) {
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000136 var n = %_Arguments(i);
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000137 if (!IS_NUMBER(n)) n = NonNumberToNumber(n);
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000138 // Make sure +0 is considered greater than -0. -0 is never a Smi, +0 can be
139 // a Smi or heap number.
mstarzinger@chromium.org32280cf2012-12-06 17:32:37 +0000140 if (NUMBER_IS_NAN(n) || n > r ||
141 (r == 0 && n == 0 && !%_IsSmi(r) && 1 / r < 0)) {
142 r = n;
143 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000144 }
145 return r;
146}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000147
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000148// ECMA 262 - 15.8.2.12
149function MathMin(arg1, arg2) { // length == 2
kasperl@chromium.org68ac0092009-07-09 06:00:35 +0000150 var length = %_ArgumentsLength();
rossberg@chromium.orgfab14982012-01-05 15:02:15 +0000151 if (length == 2) {
152 if (!IS_NUMBER(arg1)) arg1 = NonNumberToNumber(arg1);
153 if (!IS_NUMBER(arg2)) arg2 = NonNumberToNumber(arg2);
154 if (arg2 > arg1) return arg1;
155 if (arg1 > arg2) return arg2;
156 if (arg1 == arg2) {
157 // Make sure -0 is considered less than +0. -0 is never a Smi, +0 can be
158 // a Smi or a heap number.
159 return (arg1 == 0 && !%_IsSmi(arg1) && 1 / arg1 < 0) ? arg1 : arg2;
160 }
161 // All comparisons failed, one of the arguments must be NaN.
162 return 0/0; // Compiler constant-folds this to NaN.
163 }
mstarzinger@chromium.org32280cf2012-12-06 17:32:37 +0000164 var r = 1/0; // Compiler constant-folds this to Infinity.
165 for (var i = 0; i < length; i++) {
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000166 var n = %_Arguments(i);
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000167 if (!IS_NUMBER(n)) n = NonNumberToNumber(n);
rossberg@chromium.orgfab14982012-01-05 15:02:15 +0000168 // 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 +0000169 // Smi or a heap number.
mstarzinger@chromium.org32280cf2012-12-06 17:32:37 +0000170 if (NUMBER_IS_NAN(n) || n < r ||
171 (r == 0 && n == 0 && !%_IsSmi(n) && 1 / n < 0)) {
172 r = n;
173 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000174 }
175 return r;
176}
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000177
178// ECMA 262 - 15.8.2.13
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000179function MathPow(x, y) {
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000180 if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
181 if (!IS_NUMBER(y)) y = NonNumberToNumber(y);
vegorov@chromium.orgf8372902010-03-15 10:26:20 +0000182 return %_MathPow(x, y);
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000183}
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000184
185// ECMA 262 - 15.8.2.14
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000186function MathRandom() {
ager@chromium.org357bf652010-04-12 11:30:10 +0000187 return %_RandomHeapNumber();
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000188}
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000189
190// ECMA 262 - 15.8.2.15
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000191function MathRound(x) {
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000192 if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000193 return %RoundNumber(x);
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000194}
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000195
196// ECMA 262 - 15.8.2.16
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000197function MathSin(x) {
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000198 if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
vegorov@chromium.orgf8372902010-03-15 10:26:20 +0000199 return %_MathSin(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.17
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000203function MathSqrt(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 %_MathSqrt(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.18
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000209function MathTan(x) {
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000210 if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000211 return %_MathTan(x);
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000212}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000213
214
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000215// -------------------------------------------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000216
fschneider@chromium.org1805e212011-09-05 10:49:12 +0000217function SetUpMath() {
218 %CheckIsBootstrapping();
219 // Set up math constants.
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000220 // ECMA-262, section 15.8.1.1.
sgjesse@chromium.org911335c2009-08-19 12:59:44 +0000221 %OptimizeObjectForAddingMultipleProperties($Math, 8);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000222 %SetProperty($Math,
223 "E",
224 2.7182818284590452354,
225 DONT_ENUM | DONT_DELETE | READ_ONLY);
226 // ECMA-262, section 15.8.1.2.
227 %SetProperty($Math,
228 "LN10",
229 2.302585092994046,
230 DONT_ENUM | DONT_DELETE | READ_ONLY);
231 // ECMA-262, section 15.8.1.3.
232 %SetProperty($Math,
233 "LN2",
234 0.6931471805599453,
235 DONT_ENUM | DONT_DELETE | READ_ONLY);
236 // ECMA-262, section 15.8.1.4.
237 %SetProperty($Math,
238 "LOG2E",
239 1.4426950408889634,
240 DONT_ENUM | DONT_DELETE | READ_ONLY);
241 %SetProperty($Math,
242 "LOG10E",
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000243 0.4342944819032518,
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000244 DONT_ENUM | DONT_DELETE | READ_ONLY);
245 %SetProperty($Math,
246 "PI",
247 3.1415926535897932,
248 DONT_ENUM | DONT_DELETE | READ_ONLY);
249 %SetProperty($Math,
250 "SQRT1_2",
251 0.7071067811865476,
252 DONT_ENUM | DONT_DELETE | READ_ONLY);
253 %SetProperty($Math,
254 "SQRT2",
255 1.4142135623730951,
256 DONT_ENUM | DONT_DELETE | READ_ONLY);
ager@chromium.org5c838252010-02-19 08:53:10 +0000257 %ToFastProperties($Math);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000258
fschneider@chromium.org1805e212011-09-05 10:49:12 +0000259 // Set up non-enumerable functions of the Math object and
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000260 // set their names.
ricow@chromium.org27bf2882011-11-17 08:34:43 +0000261 InstallFunctions($Math, DONT_ENUM, $Array(
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000262 "random", MathRandom,
263 "abs", MathAbs,
264 "acos", MathAcos,
265 "asin", MathAsin,
266 "atan", MathAtan,
267 "ceil", MathCeil,
268 "cos", MathCos,
269 "exp", MathExp,
270 "floor", MathFloor,
271 "log", MathLog,
272 "round", MathRound,
273 "sin", MathSin,
274 "sqrt", MathSqrt,
275 "tan", MathTan,
276 "atan2", MathAtan2,
277 "pow", MathPow,
278 "max", MathMax,
279 "min", MathMin
280 ));
fschneider@chromium.org1805e212011-09-05 10:49:12 +0000281}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000282
fschneider@chromium.org1805e212011-09-05 10:49:12 +0000283SetUpMath();