blob: 8e735c4a68962acf7de8dc01dd4676c5f3d7e6a6 [file] [log] [blame]
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001// Copyright 2012 the V8 project authors. All rights reserved.
Steve Blocka7e24c12009-10-30 11:49:00 +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.
Ben Murdoch3ef787d2012-04-12 10:51:47 +010032var $floor = MathFloor;
33var $random = MathRandom;
34var $abs = MathAbs;
Steve Blocka7e24c12009-10-30 11:49:00 +000035
36// Instance class name can only be set on functions. That is the only
37// purpose for MathConstructor.
38function MathConstructor() {}
39%FunctionSetInstanceClassName(MathConstructor, 'Math');
Ben Murdoch3ef787d2012-04-12 10:51:47 +010040var $Math = new MathConstructor();
Ben Murdoch589d6972011-11-30 16:04:58 +000041$Math.__proto__ = $Object.prototype;
Steve Blocka7e24c12009-10-30 11:49:00 +000042%SetProperty(global, "Math", $Math, DONT_ENUM);
43
44// ECMA 262 - 15.8.2.1
45function MathAbs(x) {
46 if (%_IsSmi(x)) return x >= 0 ? x : -x;
Ben Murdoch086aeea2011-05-13 15:57:08 +010047 if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
Steve Block6ded16b2010-05-10 14:33:55 +010048 if (x === 0) return 0; // To handle -0.
49 return x > 0 ? x : -x;
Steve Blocka7e24c12009-10-30 11:49:00 +000050}
51
52// ECMA 262 - 15.8.2.2
53function MathAcos(x) {
Ben Murdoch086aeea2011-05-13 15:57:08 +010054 if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
Steve Blocka7e24c12009-10-30 11:49:00 +000055 return %Math_acos(x);
56}
57
58// ECMA 262 - 15.8.2.3
59function MathAsin(x) {
Ben Murdoch086aeea2011-05-13 15:57:08 +010060 if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
Steve Blocka7e24c12009-10-30 11:49:00 +000061 return %Math_asin(x);
62}
63
64// ECMA 262 - 15.8.2.4
65function MathAtan(x) {
Ben Murdoch086aeea2011-05-13 15:57:08 +010066 if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
Steve Blocka7e24c12009-10-30 11:49:00 +000067 return %Math_atan(x);
68}
69
70// ECMA 262 - 15.8.2.5
71// The naming of y and x matches the spec, as does the order in which
72// ToNumber (valueOf) is called.
73function MathAtan2(y, x) {
Ben Murdoch086aeea2011-05-13 15:57:08 +010074 if (!IS_NUMBER(y)) y = NonNumberToNumber(y);
75 if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
Steve Blocka7e24c12009-10-30 11:49:00 +000076 return %Math_atan2(y, x);
77}
78
79// ECMA 262 - 15.8.2.6
80function MathCeil(x) {
Ben Murdoch086aeea2011-05-13 15:57:08 +010081 if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
Steve Blocka7e24c12009-10-30 11:49:00 +000082 return %Math_ceil(x);
83}
84
85// ECMA 262 - 15.8.2.7
86function MathCos(x) {
Ben Murdoch086aeea2011-05-13 15:57:08 +010087 if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
Steve Block6ded16b2010-05-10 14:33:55 +010088 return %_MathCos(x);
Steve Blocka7e24c12009-10-30 11:49:00 +000089}
90
91// ECMA 262 - 15.8.2.8
92function MathExp(x) {
Ben Murdoch086aeea2011-05-13 15:57:08 +010093 if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
Steve Blocka7e24c12009-10-30 11:49:00 +000094 return %Math_exp(x);
95}
96
97// ECMA 262 - 15.8.2.9
98function MathFloor(x) {
Ben Murdoch086aeea2011-05-13 15:57:08 +010099 if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
Steve Blocka7e24c12009-10-30 11:49:00 +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.
Leon Clarkee46be812010-01-19 14:06:41 +0000102 if (x < 0x80000000 && x > 0) {
Steve Blocka7e24c12009-10-30 11:49:00 +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.
Leon Clarkee46be812010-01-19 14:06:41 +0000107 return TO_UINT32(x);
Steve Blocka7e24c12009-10-30 11:49:00 +0000108 } else {
109 return %Math_floor(x);
110 }
111}
112
113// ECMA 262 - 15.8.2.10
114function MathLog(x) {
Ben Murdoch086aeea2011-05-13 15:57:08 +0100115 if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100116 return %_MathLog(x);
Steve Blocka7e24c12009-10-30 11:49:00 +0000117}
118
119// ECMA 262 - 15.8.2.11
120function MathMax(arg1, arg2) { // length == 2
Steve Blocka7e24c12009-10-30 11:49:00 +0000121 var length = %_ArgumentsLength();
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100122 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 }
Steve Blockd0582a62009-12-15 09:54:21 +0000135 if (length == 0) {
136 return -1/0; // Compiler constant-folds this to -Infinity.
137 }
138 var r = arg1;
Ben Murdoch086aeea2011-05-13 15:57:08 +0100139 if (!IS_NUMBER(r)) r = NonNumberToNumber(r);
Steve Blockd0582a62009-12-15 09:54:21 +0000140 if (NUMBER_IS_NAN(r)) return r;
141 for (var i = 1; i < length; i++) {
142 var n = %_Arguments(i);
Ben Murdoch086aeea2011-05-13 15:57:08 +0100143 if (!IS_NUMBER(n)) n = NonNumberToNumber(n);
Steve Blocka7e24c12009-10-30 11:49:00 +0000144 if (NUMBER_IS_NAN(n)) return n;
Leon Clarkee46be812010-01-19 14:06:41 +0000145 // Make sure +0 is considered greater than -0. -0 is never a Smi, +0 can be
146 // a Smi or heap number.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100147 if (n > r || (r == 0 && n == 0 && !%_IsSmi(r) && 1 / r < 0)) r = n;
Steve Blocka7e24c12009-10-30 11:49:00 +0000148 }
149 return r;
150}
151
152// ECMA 262 - 15.8.2.12
153function MathMin(arg1, arg2) { // length == 2
Steve Blocka7e24c12009-10-30 11:49:00 +0000154 var length = %_ArgumentsLength();
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100155 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 }
Steve Blockd0582a62009-12-15 09:54:21 +0000168 if (length == 0) {
169 return 1/0; // Compiler constant-folds this to Infinity.
170 }
171 var r = arg1;
Ben Murdoch086aeea2011-05-13 15:57:08 +0100172 if (!IS_NUMBER(r)) r = NonNumberToNumber(r);
Steve Blockd0582a62009-12-15 09:54:21 +0000173 if (NUMBER_IS_NAN(r)) return r;
174 for (var i = 1; i < length; i++) {
175 var n = %_Arguments(i);
Ben Murdoch086aeea2011-05-13 15:57:08 +0100176 if (!IS_NUMBER(n)) n = NonNumberToNumber(n);
Steve Blocka7e24c12009-10-30 11:49:00 +0000177 if (NUMBER_IS_NAN(n)) return n;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100178 // Make sure -0 is considered less than +0. -0 is never a Smi, +0 can be a
Leon Clarkee46be812010-01-19 14:06:41 +0000179 // Smi or a heap number.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100180 if (n < r || (r == 0 && n == 0 && !%_IsSmi(n) && 1 / n < 0)) r = n;
Steve Blocka7e24c12009-10-30 11:49:00 +0000181 }
182 return r;
183}
184
185// ECMA 262 - 15.8.2.13
186function MathPow(x, y) {
Ben Murdoch086aeea2011-05-13 15:57:08 +0100187 if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
188 if (!IS_NUMBER(y)) y = NonNumberToNumber(y);
Steve Block6ded16b2010-05-10 14:33:55 +0100189 return %_MathPow(x, y);
Steve Blocka7e24c12009-10-30 11:49:00 +0000190}
191
192// ECMA 262 - 15.8.2.14
193function MathRandom() {
Steve Block6ded16b2010-05-10 14:33:55 +0100194 return %_RandomHeapNumber();
Steve Blocka7e24c12009-10-30 11:49:00 +0000195}
196
197// ECMA 262 - 15.8.2.15
198function MathRound(x) {
Ben Murdoch086aeea2011-05-13 15:57:08 +0100199 if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
Steve Block6ded16b2010-05-10 14:33:55 +0100200 return %RoundNumber(x);
Steve Blocka7e24c12009-10-30 11:49:00 +0000201}
202
203// ECMA 262 - 15.8.2.16
204function MathSin(x) {
Ben Murdoch086aeea2011-05-13 15:57:08 +0100205 if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
Steve Block6ded16b2010-05-10 14:33:55 +0100206 return %_MathSin(x);
Steve Blocka7e24c12009-10-30 11:49:00 +0000207}
208
209// ECMA 262 - 15.8.2.17
210function MathSqrt(x) {
Ben Murdoch086aeea2011-05-13 15:57:08 +0100211 if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
Steve Block6ded16b2010-05-10 14:33:55 +0100212 return %_MathSqrt(x);
Steve Blocka7e24c12009-10-30 11:49:00 +0000213}
214
215// ECMA 262 - 15.8.2.18
216function MathTan(x) {
Ben Murdoch086aeea2011-05-13 15:57:08 +0100217 if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100218 return %_MathTan(x);
Steve Blocka7e24c12009-10-30 11:49:00 +0000219}
220
221
222// -------------------------------------------------------------------
223
Ben Murdoch589d6972011-11-30 16:04:58 +0000224function SetUpMath() {
225 %CheckIsBootstrapping();
226 // Set up math constants.
Steve Blocka7e24c12009-10-30 11:49:00 +0000227 // ECMA-262, section 15.8.1.1.
228 %OptimizeObjectForAddingMultipleProperties($Math, 8);
229 %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",
Steve Block1e0659c2011-05-24 12:43:12 +0100250 0.4342944819032518,
Steve Blocka7e24c12009-10-30 11:49:00 +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);
Andrei Popescu402d9372010-02-26 13:31:12 +0000264 %ToFastProperties($Math);
Steve Blocka7e24c12009-10-30 11:49:00 +0000265
Ben Murdoch589d6972011-11-30 16:04:58 +0000266 // Set up non-enumerable functions of the Math object and
Steve Blocka7e24c12009-10-30 11:49:00 +0000267 // set their names.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100268 InstallFunctions($Math, DONT_ENUM, $Array(
Steve Blocka7e24c12009-10-30 11:49:00 +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 ));
Ben Murdoch589d6972011-11-30 16:04:58 +0000288}
Steve Blocka7e24c12009-10-30 11:49:00 +0000289
Ben Murdoch589d6972011-11-30 16:04:58 +0000290SetUpMath();