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 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. 32var $floor = MathFloor; 33var $random = MathRandom; 34var $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'); 40var $Math = new MathConstructor(); 41$Math.__proto__ = $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 = NonNumberToNumber(x); 48 if (x === 0) return 0; // To handle -0. 49 return x > 0 ? x : -x; 50} 51 52// ECMA 262 - 15.8.2.2 53function MathAcos(x) { 54 if (!IS_NUMBER(x)) x = NonNumberToNumber(x); 55 return %Math_acos(x); 56} 57 58// ECMA 262 - 15.8.2.3 59function MathAsin(x) { 60 if (!IS_NUMBER(x)) x = NonNumberToNumber(x); 61 return %Math_asin(x); 62} 63 64// ECMA 262 - 15.8.2.4 65function MathAtan(x) { 66 if (!IS_NUMBER(x)) x = NonNumberToNumber(x); 67 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) { 74 if (!IS_NUMBER(y)) y = NonNumberToNumber(y); 75 if (!IS_NUMBER(x)) x = NonNumberToNumber(x); 76 return %Math_atan2(y, x); 77} 78 79// ECMA 262 - 15.8.2.6 80function MathCeil(x) { 81 if (!IS_NUMBER(x)) x = NonNumberToNumber(x); 82 return %Math_ceil(x); 83} 84 85// ECMA 262 - 15.8.2.7 86function MathCos(x) { 87 if (!IS_NUMBER(x)) x = NonNumberToNumber(x); 88 return %_MathCos(x); 89} 90 91// ECMA 262 - 15.8.2.8 92function MathExp(x) { 93 if (!IS_NUMBER(x)) x = NonNumberToNumber(x); 94 return %Math_exp(x); 95} 96 97// ECMA 262 - 15.8.2.9 98function MathFloor(x) { 99 if (!IS_NUMBER(x)) x = NonNumberToNumber(x); 100 // 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. 102 if (x < 0x80000000 && x > 0) { 103 // 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. 107 return TO_UINT32(x); 108 } else { 109 return %Math_floor(x); 110 } 111} 112 113// ECMA 262 - 15.8.2.10 114function MathLog(x) { 115 if (!IS_NUMBER(x)) x = NonNumberToNumber(x); 116 return %_MathLog(x); 117} 118 119// ECMA 262 - 15.8.2.11 120function MathMax(arg1, arg2) { // length == 2 121 var length = %_ArgumentsLength(); 122 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 } 135 if (length == 0) { 136 return -1/0; // Compiler constant-folds this to -Infinity. 137 } 138 var r = arg1; 139 if (!IS_NUMBER(r)) r = NonNumberToNumber(r); 140 if (NUMBER_IS_NAN(r)) return r; 141 for (var i = 1; i < length; i++) { 142 var n = %_Arguments(i); 143 if (!IS_NUMBER(n)) n = NonNumberToNumber(n); 144 if (NUMBER_IS_NAN(n)) return n; 145 // Make sure +0 is considered greater than -0. -0 is never a Smi, +0 can be 146 // a Smi or heap number. 147 if (n > r || (r == 0 && n == 0 && !%_IsSmi(r) && 1 / r < 0)) r = n; 148 } 149 return r; 150} 151 152// ECMA 262 - 15.8.2.12 153function MathMin(arg1, arg2) { // length == 2 154 var length = %_ArgumentsLength(); 155 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 } 168 if (length == 0) { 169 return 1/0; // Compiler constant-folds this to Infinity. 170 } 171 var r = arg1; 172 if (!IS_NUMBER(r)) r = NonNumberToNumber(r); 173 if (NUMBER_IS_NAN(r)) return r; 174 for (var i = 1; i < length; i++) { 175 var n = %_Arguments(i); 176 if (!IS_NUMBER(n)) n = NonNumberToNumber(n); 177 if (NUMBER_IS_NAN(n)) return n; 178 // Make sure -0 is considered less than +0. -0 is never a Smi, +0 can be a 179 // Smi or a heap number. 180 if (n < r || (r == 0 && n == 0 && !%_IsSmi(n) && 1 / n < 0)) r = n; 181 } 182 return r; 183} 184 185// ECMA 262 - 15.8.2.13 186function MathPow(x, y) { 187 if (!IS_NUMBER(x)) x = NonNumberToNumber(x); 188 if (!IS_NUMBER(y)) y = NonNumberToNumber(y); 189 return %_MathPow(x, y); 190} 191 192// ECMA 262 - 15.8.2.14 193function MathRandom() { 194 return %_RandomHeapNumber(); 195} 196 197// ECMA 262 - 15.8.2.15 198function MathRound(x) { 199 if (!IS_NUMBER(x)) x = NonNumberToNumber(x); 200 return %RoundNumber(x); 201} 202 203// ECMA 262 - 15.8.2.16 204function MathSin(x) { 205 if (!IS_NUMBER(x)) x = NonNumberToNumber(x); 206 return %_MathSin(x); 207} 208 209// ECMA 262 - 15.8.2.17 210function MathSqrt(x) { 211 if (!IS_NUMBER(x)) x = NonNumberToNumber(x); 212 return %_MathSqrt(x); 213} 214 215// ECMA 262 - 15.8.2.18 216function MathTan(x) { 217 if (!IS_NUMBER(x)) x = NonNumberToNumber(x); 218 return %_MathTan(x); 219} 220 221 222// ------------------------------------------------------------------- 223 224function SetUpMath() { 225 %CheckIsBootstrapping(); 226 // Set up math constants. 227 // 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", 250 0.4342944819032518, 251 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); 264 %ToFastProperties($Math); 265 266 // Set up non-enumerable functions of the Math object and 267 // set their names. 268 InstallFunctions($Math, DONT_ENUM, $Array( 269 "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 )); 288} 289 290SetUpMath(); 291