1// Copyright 2006-2008 the V8 project authors. All rights reserved.
2// 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.
32const $floor = MathFloor;
33const $random = MathRandom;
34const $abs = MathAbs;
35
36// Instance class name can only be set on functions. That is the only
37// purpose for MathConstructor.
38function MathConstructor() {}
39%FunctionSetInstanceClassName(MathConstructor, 'Math');
40const $Math = new MathConstructor();
41$Math.__proto__ = global.Object.prototype;
42%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;
47  if (!IS_NUMBER(x)) x = ToNumber(x);
48  return %Math_abs(x);
49}
50
51// ECMA 262 - 15.8.2.2
52function MathAcos(x) {
53  if (!IS_NUMBER(x)) x = ToNumber(x);
54  return %Math_acos(x);
55}
56
57// ECMA 262 - 15.8.2.3
58function MathAsin(x) {
59  if (!IS_NUMBER(x)) x = ToNumber(x);
60  return %Math_asin(x);
61}
62
63// ECMA 262 - 15.8.2.4
64function MathAtan(x) {
65  if (!IS_NUMBER(x)) x = ToNumber(x);
66  return %Math_atan(x);
67}
68
69// ECMA 262 - 15.8.2.5
70// The naming of y and x matches the spec, as does the order in which
71// ToNumber (valueOf) is called.
72function MathAtan2(y, x) {
73  if (!IS_NUMBER(y)) y = ToNumber(y);
74  if (!IS_NUMBER(x)) x = ToNumber(x);
75  return %Math_atan2(y, x);
76}
77
78// ECMA 262 - 15.8.2.6
79function MathCeil(x) {
80  if (!IS_NUMBER(x)) x = ToNumber(x);
81  return %Math_ceil(x);
82}
83
84// ECMA 262 - 15.8.2.7
85function MathCos(x) {
86  if (!IS_NUMBER(x)) x = ToNumber(x);
87  return %_Math_cos(x);
88}
89
90// ECMA 262 - 15.8.2.8
91function MathExp(x) {
92  if (!IS_NUMBER(x)) x = ToNumber(x);
93  return %Math_exp(x);
94}
95
96// ECMA 262 - 15.8.2.9
97function MathFloor(x) {
98  if (!IS_NUMBER(x)) x = ToNumber(x);
99  // 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.
101  if (x < 0x80000000 && x > 0) {
102    // 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.
106    return TO_UINT32(x);
107  } else {
108    return %Math_floor(x);
109  }
110}
111
112// ECMA 262 - 15.8.2.10
113function MathLog(x) {
114  if (!IS_NUMBER(x)) x = ToNumber(x);
115  return %Math_log(x);
116}
117
118// ECMA 262 - 15.8.2.11
119function MathMax(arg1, arg2) {  // length == 2
120  var length = %_ArgumentsLength();
121  if (length == 0) {
122    return -1/0;  // Compiler constant-folds this to -Infinity.
123  }
124  var r = arg1;
125  if (!IS_NUMBER(r)) r = ToNumber(r);
126  if (NUMBER_IS_NAN(r)) return r;
127  for (var i = 1; i < length; i++) {
128    var n = %_Arguments(i);
129    if (!IS_NUMBER(n)) n = ToNumber(n);
130    if (NUMBER_IS_NAN(n)) return n;
131    // Make sure +0 is considered greater than -0.  -0 is never a Smi, +0 can be
132    // a Smi or heap number.
133    if (n > r || (r === 0 && n === 0 && !%_IsSmi(r) && 1 / r < 0)) r = n;
134  }
135  return r;
136}
137
138// ECMA 262 - 15.8.2.12
139function MathMin(arg1, arg2) {  // length == 2
140  var length = %_ArgumentsLength();
141  if (length == 0) {
142    return 1/0;  // Compiler constant-folds this to Infinity.
143  }
144  var r = arg1;
145  if (!IS_NUMBER(r)) r = ToNumber(r);
146  if (NUMBER_IS_NAN(r)) return r;
147  for (var i = 1; i < length; i++) {
148    var n = %_Arguments(i);
149    if (!IS_NUMBER(n)) n = ToNumber(n);
150    if (NUMBER_IS_NAN(n)) return n;
151    // Make sure -0 is considered less than +0.  -0 is never a Smi, +0 can b a
152    // Smi or a heap number.
153    if (n < r || (r === 0 && n === 0 && !%_IsSmi(n) && 1 / n < 0)) r = n;
154  }
155  return r;
156}
157
158// ECMA 262 - 15.8.2.13
159function MathPow(x, y) {
160  if (!IS_NUMBER(x)) x = ToNumber(x);
161  if (!IS_NUMBER(y)) y = ToNumber(y);
162  return %Math_pow(x, y);
163}
164
165// ECMA 262 - 15.8.2.14
166function MathRandom() {
167  return %_RandomPositiveSmi() / 0x40000000;
168}
169
170// ECMA 262 - 15.8.2.15
171function MathRound(x) {
172  if (!IS_NUMBER(x)) x = ToNumber(x);
173  return %Math_round(x);
174}
175
176// ECMA 262 - 15.8.2.16
177function MathSin(x) {
178  if (!IS_NUMBER(x)) x = ToNumber(x);
179  return %_Math_sin(x);
180}
181
182// ECMA 262 - 15.8.2.17
183function MathSqrt(x) {
184  if (!IS_NUMBER(x)) x = ToNumber(x);
185  return %Math_sqrt(x);
186}
187
188// ECMA 262 - 15.8.2.18
189function MathTan(x) {
190  if (!IS_NUMBER(x)) x = ToNumber(x);
191  return %Math_tan(x);
192}
193
194
195// -------------------------------------------------------------------
196
197function SetupMath() {
198  // Setup math constants.
199  // ECMA-262, section 15.8.1.1.
200  %OptimizeObjectForAddingMultipleProperties($Math, 8);
201  %SetProperty($Math,
202               "E",
203               2.7182818284590452354,
204               DONT_ENUM |  DONT_DELETE | READ_ONLY);
205  // ECMA-262, section 15.8.1.2.
206  %SetProperty($Math,
207               "LN10",
208               2.302585092994046,
209               DONT_ENUM |  DONT_DELETE | READ_ONLY);
210  // ECMA-262, section 15.8.1.3.
211  %SetProperty($Math,
212               "LN2",
213               0.6931471805599453,
214               DONT_ENUM |  DONT_DELETE | READ_ONLY);
215  // ECMA-262, section 15.8.1.4.
216  %SetProperty($Math,
217               "LOG2E",
218               1.4426950408889634,
219               DONT_ENUM |  DONT_DELETE | READ_ONLY);
220  %SetProperty($Math,
221               "LOG10E",
222               0.43429448190325176,
223               DONT_ENUM |  DONT_DELETE | READ_ONLY);
224  %SetProperty($Math,
225               "PI",
226               3.1415926535897932,
227               DONT_ENUM |  DONT_DELETE | READ_ONLY);
228  %SetProperty($Math,
229               "SQRT1_2",
230               0.7071067811865476,
231               DONT_ENUM |  DONT_DELETE | READ_ONLY);
232  %SetProperty($Math,
233               "SQRT2",
234               1.4142135623730951,
235               DONT_ENUM |  DONT_DELETE | READ_ONLY);
236  %ToFastProperties($Math);
237
238  // Setup non-enumerable functions of the Math object and
239  // set their names.
240  InstallFunctionsOnHiddenPrototype($Math, DONT_ENUM, $Array(
241    "random", MathRandom,
242    "abs", MathAbs,
243    "acos", MathAcos,
244    "asin", MathAsin,
245    "atan", MathAtan,
246    "ceil", MathCeil,
247    "cos", MathCos,
248    "exp", MathExp,
249    "floor", MathFloor,
250    "log", MathLog,
251    "round", MathRound,
252    "sin", MathSin,
253    "sqrt", MathSqrt,
254    "tan", MathTan,
255    "atan2", MathAtan2,
256    "pow", MathPow,
257    "max", MathMax,
258    "min", MathMin
259  ));
260};
261
262
263SetupMath();
264