Home | History | Annotate | Download | only in src
      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.
     32 var $floor = MathFloor;
     33 var $random = MathRandom;
     34 var $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 var $Math = new MathConstructor();
     41 $Math.__proto__ = $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 == 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
    153 function 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
    186 function 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
    193 function MathRandom() {
    194   return %_RandomHeapNumber();
    195 }
    196 
    197 // ECMA 262 - 15.8.2.15
    198 function MathRound(x) {
    199   if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
    200   return %RoundNumber(x);
    201 }
    202 
    203 // ECMA 262 - 15.8.2.16
    204 function MathSin(x) {
    205   if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
    206   return %_MathSin(x);
    207 }
    208 
    209 // ECMA 262 - 15.8.2.17
    210 function MathSqrt(x) {
    211   if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
    212   return %_MathSqrt(x);
    213 }
    214 
    215 // ECMA 262 - 15.8.2.18
    216 function MathTan(x) {
    217   if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
    218   return %_MathTan(x);
    219 }
    220 
    221 
    222 // -------------------------------------------------------------------
    223 
    224 function 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 
    290 SetUpMath();
    291