Home | History | Annotate | Download | only in src
      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 = ToNumber(x);
     48   return %Math_abs(x);
     49 }
     50 
     51 // ECMA 262 - 15.8.2.2
     52 function MathAcos(x) {
     53   if (!IS_NUMBER(x)) x = ToNumber(x);
     54   return %Math_acos(x);
     55 }
     56 
     57 // ECMA 262 - 15.8.2.3
     58 function MathAsin(x) {
     59   if (!IS_NUMBER(x)) x = ToNumber(x);
     60   return %Math_asin(x);
     61 }
     62 
     63 // ECMA 262 - 15.8.2.4
     64 function 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.
     72 function 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
     79 function MathCeil(x) {
     80   if (!IS_NUMBER(x)) x = ToNumber(x);
     81   return %Math_ceil(x);
     82 }
     83 
     84 // ECMA 262 - 15.8.2.7
     85 function MathCos(x) {
     86   if (!IS_NUMBER(x)) x = ToNumber(x);
     87   return %_Math_cos(x);
     88 }
     89 
     90 // ECMA 262 - 15.8.2.8
     91 function MathExp(x) {
     92   if (!IS_NUMBER(x)) x = ToNumber(x);
     93   return %Math_exp(x);
     94 }
     95 
     96 // ECMA 262 - 15.8.2.9
     97 function 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
    113 function MathLog(x) {
    114   if (!IS_NUMBER(x)) x = ToNumber(x);
    115   return %Math_log(x);
    116 }
    117 
    118 // ECMA 262 - 15.8.2.11
    119 function 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
    139 function 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
    159 function 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
    166 function MathRandom() {
    167   return %_RandomPositiveSmi() / 0x40000000;
    168 }
    169 
    170 // ECMA 262 - 15.8.2.15
    171 function MathRound(x) {
    172   if (!IS_NUMBER(x)) x = ToNumber(x);
    173   return %Math_round(x);
    174 }
    175 
    176 // ECMA 262 - 15.8.2.16
    177 function MathSin(x) {
    178   if (!IS_NUMBER(x)) x = ToNumber(x);
    179   return %_Math_sin(x);
    180 }
    181 
    182 // ECMA 262 - 15.8.2.17
    183 function MathSqrt(x) {
    184   if (!IS_NUMBER(x)) x = ToNumber(x);
    185   return %Math_sqrt(x);
    186 }
    187 
    188 // ECMA 262 - 15.8.2.18
    189 function MathTan(x) {
    190   if (!IS_NUMBER(x)) x = ToNumber(x);
    191   return %Math_tan(x);
    192 }
    193 
    194 
    195 // -------------------------------------------------------------------
    196 
    197 function 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 
    263 SetupMath();
    264