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