1// Copyright 2012 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// This file relies on the fact that the following declarations have been made 29// in runtime.js: 30// var $Object = global.Object; 31 32// Keep reference to original values of some global properties. This 33// has the added benefit that the code in this file is isolated from 34// changes to these properties. 35var $floor = MathFloor; 36var $abs = MathAbs; 37 38// Instance class name can only be set on functions. That is the only 39// purpose for MathConstructor. 40function MathConstructor() {} 41var $Math = new MathConstructor(); 42 43// ------------------------------------------------------------------- 44 45// ECMA 262 - 15.8.2.1 46function MathAbs(x) { 47 if (%_IsSmi(x)) return x >= 0 ? x : -x; 48 if (!IS_NUMBER(x)) x = NonNumberToNumber(x); 49 if (x === 0) return 0; // To handle -0. 50 return x > 0 ? x : -x; 51} 52 53// ECMA 262 - 15.8.2.2 54function MathAcos(x) { 55 if (!IS_NUMBER(x)) x = NonNumberToNumber(x); 56 return %Math_acos(x); 57} 58 59// ECMA 262 - 15.8.2.3 60function MathAsin(x) { 61 if (!IS_NUMBER(x)) x = NonNumberToNumber(x); 62 return %Math_asin(x); 63} 64 65// ECMA 262 - 15.8.2.4 66function MathAtan(x) { 67 if (!IS_NUMBER(x)) x = NonNumberToNumber(x); 68 return %Math_atan(x); 69} 70 71// ECMA 262 - 15.8.2.5 72// The naming of y and x matches the spec, as does the order in which 73// ToNumber (valueOf) is called. 74function MathAtan2(y, x) { 75 if (!IS_NUMBER(y)) y = NonNumberToNumber(y); 76 if (!IS_NUMBER(x)) x = NonNumberToNumber(x); 77 return %Math_atan2(y, x); 78} 79 80// ECMA 262 - 15.8.2.6 81function MathCeil(x) { 82 if (!IS_NUMBER(x)) x = NonNumberToNumber(x); 83 return %Math_ceil(x); 84} 85 86// ECMA 262 - 15.8.2.7 87function MathCos(x) { 88 if (!IS_NUMBER(x)) x = NonNumberToNumber(x); 89 return %_MathCos(x); 90} 91 92// ECMA 262 - 15.8.2.8 93function MathExp(x) { 94 if (!IS_NUMBER(x)) x = NonNumberToNumber(x); 95 return %Math_exp(x); 96} 97 98// ECMA 262 - 15.8.2.9 99function MathFloor(x) { 100 if (!IS_NUMBER(x)) x = NonNumberToNumber(x); 101 // It's more common to call this with a positive number that's out 102 // of range than negative numbers; check the upper bound first. 103 if (x < 0x80000000 && x > 0) { 104 // Numbers in the range [0, 2^31) can be floored by converting 105 // them to an unsigned 32-bit value using the shift operator. 106 // We avoid doing so for -0, because the result of Math.floor(-0) 107 // has to be -0, which wouldn't be the case with the shift. 108 return TO_UINT32(x); 109 } else { 110 return %Math_floor(x); 111 } 112} 113 114// ECMA 262 - 15.8.2.10 115function MathLog(x) { 116 if (!IS_NUMBER(x)) x = NonNumberToNumber(x); 117 return %_MathLog(x); 118} 119 120// ECMA 262 - 15.8.2.11 121function MathMax(arg1, arg2) { // length == 2 122 var length = %_ArgumentsLength(); 123 if (length == 2) { 124 if (!IS_NUMBER(arg1)) arg1 = NonNumberToNumber(arg1); 125 if (!IS_NUMBER(arg2)) arg2 = NonNumberToNumber(arg2); 126 if (arg2 > arg1) return arg2; 127 if (arg1 > arg2) return arg1; 128 if (arg1 == arg2) { 129 // Make sure -0 is considered less than +0. -0 is never a Smi, +0 can be 130 // a Smi or a heap number. 131 return (arg1 == 0 && !%_IsSmi(arg1) && 1 / arg1 < 0) ? arg2 : arg1; 132 } 133 // All comparisons failed, one of the arguments must be NaN. 134 return 0/0; // Compiler constant-folds this to NaN. 135 } 136 var r = -1/0; // Compiler constant-folds this to -Infinity. 137 for (var i = 0; i < length; i++) { 138 var n = %_Arguments(i); 139 if (!IS_NUMBER(n)) n = NonNumberToNumber(n); 140 // Make sure +0 is considered greater than -0. -0 is never a Smi, +0 can be 141 // a Smi or heap number. 142 if (NUMBER_IS_NAN(n) || n > r || 143 (r == 0 && n == 0 && !%_IsSmi(r) && 1 / r < 0)) { 144 r = n; 145 } 146 } 147 return r; 148} 149 150// ECMA 262 - 15.8.2.12 151function MathMin(arg1, arg2) { // length == 2 152 var length = %_ArgumentsLength(); 153 if (length == 2) { 154 if (!IS_NUMBER(arg1)) arg1 = NonNumberToNumber(arg1); 155 if (!IS_NUMBER(arg2)) arg2 = NonNumberToNumber(arg2); 156 if (arg2 > arg1) return arg1; 157 if (arg1 > arg2) return arg2; 158 if (arg1 == arg2) { 159 // Make sure -0 is considered less than +0. -0 is never a Smi, +0 can be 160 // a Smi or a heap number. 161 return (arg1 == 0 && !%_IsSmi(arg1) && 1 / arg1 < 0) ? arg1 : arg2; 162 } 163 // All comparisons failed, one of the arguments must be NaN. 164 return 0/0; // Compiler constant-folds this to NaN. 165 } 166 var r = 1/0; // Compiler constant-folds this to Infinity. 167 for (var i = 0; i < length; i++) { 168 var n = %_Arguments(i); 169 if (!IS_NUMBER(n)) n = NonNumberToNumber(n); 170 // Make sure -0 is considered less than +0. -0 is never a Smi, +0 can be a 171 // Smi or a heap number. 172 if (NUMBER_IS_NAN(n) || n < r || 173 (r == 0 && n == 0 && !%_IsSmi(n) && 1 / n < 0)) { 174 r = n; 175 } 176 } 177 return r; 178} 179 180// ECMA 262 - 15.8.2.13 181function MathPow(x, y) { 182 if (!IS_NUMBER(x)) x = NonNumberToNumber(x); 183 if (!IS_NUMBER(y)) y = NonNumberToNumber(y); 184 return %_MathPow(x, y); 185} 186 187// ECMA 262 - 15.8.2.14 188function MathRandom() { 189 return %_RandomHeapNumber(); 190} 191 192// ECMA 262 - 15.8.2.15 193function MathRound(x) { 194 if (!IS_NUMBER(x)) x = NonNumberToNumber(x); 195 return %RoundNumber(x); 196} 197 198// ECMA 262 - 15.8.2.16 199function MathSin(x) { 200 if (!IS_NUMBER(x)) x = NonNumberToNumber(x); 201 return %_MathSin(x); 202} 203 204// ECMA 262 - 15.8.2.17 205function MathSqrt(x) { 206 if (!IS_NUMBER(x)) x = NonNumberToNumber(x); 207 return %_MathSqrt(x); 208} 209 210// ECMA 262 - 15.8.2.18 211function MathTan(x) { 212 if (!IS_NUMBER(x)) x = NonNumberToNumber(x); 213 return %_MathTan(x); 214} 215 216// Non-standard extension. 217function MathImul(x, y) { 218 if (!IS_NUMBER(x)) x = NonNumberToNumber(x); 219 if (!IS_NUMBER(y)) y = NonNumberToNumber(y); 220 return %NumberImul(x, y); 221} 222 223 224// ------------------------------------------------------------------- 225 226function SetUpMath() { 227 %CheckIsBootstrapping(); 228 229 %SetPrototype($Math, $Object.prototype); 230 %SetProperty(global, "Math", $Math, DONT_ENUM); 231 %FunctionSetInstanceClassName(MathConstructor, 'Math'); 232 233 // Set up math constants. 234 // ECMA-262, section 15.8.1.1. 235 %OptimizeObjectForAddingMultipleProperties($Math, 8); 236 %SetProperty($Math, 237 "E", 238 2.7182818284590452354, 239 DONT_ENUM | DONT_DELETE | READ_ONLY); 240 // ECMA-262, section 15.8.1.2. 241 %SetProperty($Math, 242 "LN10", 243 2.302585092994046, 244 DONT_ENUM | DONT_DELETE | READ_ONLY); 245 // ECMA-262, section 15.8.1.3. 246 %SetProperty($Math, 247 "LN2", 248 0.6931471805599453, 249 DONT_ENUM | DONT_DELETE | READ_ONLY); 250 // ECMA-262, section 15.8.1.4. 251 %SetProperty($Math, 252 "LOG2E", 253 1.4426950408889634, 254 DONT_ENUM | DONT_DELETE | READ_ONLY); 255 %SetProperty($Math, 256 "LOG10E", 257 0.4342944819032518, 258 DONT_ENUM | DONT_DELETE | READ_ONLY); 259 %SetProperty($Math, 260 "PI", 261 3.1415926535897932, 262 DONT_ENUM | DONT_DELETE | READ_ONLY); 263 %SetProperty($Math, 264 "SQRT1_2", 265 0.7071067811865476, 266 DONT_ENUM | DONT_DELETE | READ_ONLY); 267 %SetProperty($Math, 268 "SQRT2", 269 1.4142135623730951, 270 DONT_ENUM | DONT_DELETE | READ_ONLY); 271 %ToFastProperties($Math); 272 273 // Set up non-enumerable functions of the Math object and 274 // set their names. 275 InstallFunctions($Math, DONT_ENUM, $Array( 276 "random", MathRandom, 277 "abs", MathAbs, 278 "acos", MathAcos, 279 "asin", MathAsin, 280 "atan", MathAtan, 281 "ceil", MathCeil, 282 "cos", MathCos, 283 "exp", MathExp, 284 "floor", MathFloor, 285 "log", MathLog, 286 "round", MathRound, 287 "sin", MathSin, 288 "sqrt", MathSqrt, 289 "tan", MathTan, 290 "atan2", MathAtan2, 291 "pow", MathPow, 292 "max", MathMax, 293 "min", MathMin, 294 "imul", MathImul 295 )); 296} 297 298SetUpMath(); 299