Home | History | Annotate | Download | only in runtime
      1 /*
      2  *  Copyright (C) 1999-2000 Harri Porten (porten (at) kde.org)
      3  *  Copyright (C) 2007, 2008 Apple Inc. All Rights Reserved.
      4  *
      5  *  This library is free software; you can redistribute it and/or
      6  *  modify it under the terms of the GNU Lesser General Public
      7  *  License as published by the Free Software Foundation; either
      8  *  version 2 of the License, or (at your option) any later version.
      9  *
     10  *  This library is distributed in the hope that it will be useful,
     11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
     12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     13  *  Lesser General Public License for more details.
     14  *
     15  *  You should have received a copy of the GNU Lesser General Public
     16  *  License along with this library; if not, write to the Free Software
     17  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
     18  *
     19  */
     20 
     21 #include "config.h"
     22 #include "MathObject.h"
     23 
     24 #include "ObjectPrototype.h"
     25 #include "Operations.h"
     26 #include <time.h>
     27 #include <wtf/Assertions.h>
     28 #include <wtf/MathExtras.h>
     29 #include <wtf/RandomNumber.h>
     30 #include <wtf/RandomNumberSeed.h>
     31 
     32 namespace JSC {
     33 
     34 ASSERT_CLASS_FITS_IN_CELL(MathObject);
     35 
     36 static JSValue JSC_HOST_CALL mathProtoFuncAbs(ExecState*, JSObject*, JSValue, const ArgList&);
     37 static JSValue JSC_HOST_CALL mathProtoFuncACos(ExecState*, JSObject*, JSValue, const ArgList&);
     38 static JSValue JSC_HOST_CALL mathProtoFuncASin(ExecState*, JSObject*, JSValue, const ArgList&);
     39 static JSValue JSC_HOST_CALL mathProtoFuncATan(ExecState*, JSObject*, JSValue, const ArgList&);
     40 static JSValue JSC_HOST_CALL mathProtoFuncATan2(ExecState*, JSObject*, JSValue, const ArgList&);
     41 static JSValue JSC_HOST_CALL mathProtoFuncCeil(ExecState*, JSObject*, JSValue, const ArgList&);
     42 static JSValue JSC_HOST_CALL mathProtoFuncCos(ExecState*, JSObject*, JSValue, const ArgList&);
     43 static JSValue JSC_HOST_CALL mathProtoFuncExp(ExecState*, JSObject*, JSValue, const ArgList&);
     44 static JSValue JSC_HOST_CALL mathProtoFuncFloor(ExecState*, JSObject*, JSValue, const ArgList&);
     45 static JSValue JSC_HOST_CALL mathProtoFuncLog(ExecState*, JSObject*, JSValue, const ArgList&);
     46 static JSValue JSC_HOST_CALL mathProtoFuncMax(ExecState*, JSObject*, JSValue, const ArgList&);
     47 static JSValue JSC_HOST_CALL mathProtoFuncMin(ExecState*, JSObject*, JSValue, const ArgList&);
     48 static JSValue JSC_HOST_CALL mathProtoFuncPow(ExecState*, JSObject*, JSValue, const ArgList&);
     49 static JSValue JSC_HOST_CALL mathProtoFuncRandom(ExecState*, JSObject*, JSValue, const ArgList&);
     50 static JSValue JSC_HOST_CALL mathProtoFuncRound(ExecState*, JSObject*, JSValue, const ArgList&);
     51 static JSValue JSC_HOST_CALL mathProtoFuncSin(ExecState*, JSObject*, JSValue, const ArgList&);
     52 static JSValue JSC_HOST_CALL mathProtoFuncSqrt(ExecState*, JSObject*, JSValue, const ArgList&);
     53 static JSValue JSC_HOST_CALL mathProtoFuncTan(ExecState*, JSObject*, JSValue, const ArgList&);
     54 
     55 }
     56 
     57 #include "MathObject.lut.h"
     58 
     59 namespace JSC {
     60 
     61 // ------------------------------ MathObject --------------------------------
     62 
     63 const ClassInfo MathObject::info = { "Math", 0, 0, ExecState::mathTable };
     64 
     65 /* Source for MathObject.lut.h
     66 @begin mathTable
     67   abs           mathProtoFuncAbs               DontEnum|Function 1
     68   acos          mathProtoFuncACos              DontEnum|Function 1
     69   asin          mathProtoFuncASin              DontEnum|Function 1
     70   atan          mathProtoFuncATan              DontEnum|Function 1
     71   atan2         mathProtoFuncATan2             DontEnum|Function 2
     72   ceil          mathProtoFuncCeil              DontEnum|Function 1
     73   cos           mathProtoFuncCos               DontEnum|Function 1
     74   exp           mathProtoFuncExp               DontEnum|Function 1
     75   floor         mathProtoFuncFloor             DontEnum|Function 1
     76   log           mathProtoFuncLog               DontEnum|Function 1
     77   max           mathProtoFuncMax               DontEnum|Function 2
     78   min           mathProtoFuncMin               DontEnum|Function 2
     79   pow           mathProtoFuncPow               DontEnum|Function 2
     80   random        mathProtoFuncRandom            DontEnum|Function 0
     81   round         mathProtoFuncRound             DontEnum|Function 1
     82   sin           mathProtoFuncSin               DontEnum|Function 1
     83   sqrt          mathProtoFuncSqrt              DontEnum|Function 1
     84   tan           mathProtoFuncTan               DontEnum|Function 1
     85 @end
     86 */
     87 
     88 MathObject::MathObject(ExecState* exec, NonNullPassRefPtr<Structure> structure)
     89     : JSObject(structure)
     90 {
     91     putDirectWithoutTransition(Identifier(exec, "E"), jsNumber(exec, exp(1.0)), DontDelete | DontEnum | ReadOnly);
     92     putDirectWithoutTransition(Identifier(exec, "LN2"), jsNumber(exec, log(2.0)), DontDelete | DontEnum | ReadOnly);
     93     putDirectWithoutTransition(Identifier(exec, "LN10"), jsNumber(exec, log(10.0)), DontDelete | DontEnum | ReadOnly);
     94     putDirectWithoutTransition(Identifier(exec, "LOG2E"), jsNumber(exec, 1.0 / log(2.0)), DontDelete | DontEnum | ReadOnly);
     95     putDirectWithoutTransition(Identifier(exec, "LOG10E"), jsNumber(exec, 1.0 / log(10.0)), DontDelete | DontEnum | ReadOnly);
     96     putDirectWithoutTransition(Identifier(exec, "PI"), jsNumber(exec, piDouble), DontDelete | DontEnum | ReadOnly);
     97     putDirectWithoutTransition(Identifier(exec, "SQRT1_2"), jsNumber(exec, sqrt(0.5)), DontDelete | DontEnum | ReadOnly);
     98     putDirectWithoutTransition(Identifier(exec, "SQRT2"), jsNumber(exec, sqrt(2.0)), DontDelete | DontEnum | ReadOnly);
     99 }
    100 
    101 // ECMA 15.8
    102 
    103 bool MathObject::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot &slot)
    104 {
    105     return getStaticFunctionSlot<JSObject>(exec, ExecState::mathTable(exec), this, propertyName, slot);
    106 }
    107 
    108 bool MathObject::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
    109 {
    110     return getStaticFunctionDescriptor<JSObject>(exec, ExecState::mathTable(exec), this, propertyName, descriptor);
    111 }
    112 
    113 // ------------------------------ Functions --------------------------------
    114 
    115 JSValue JSC_HOST_CALL mathProtoFuncAbs(ExecState* exec, JSObject*, JSValue, const ArgList& args)
    116 {
    117     return jsNumber(exec, fabs(args.at(0).toNumber(exec)));
    118 }
    119 
    120 JSValue JSC_HOST_CALL mathProtoFuncACos(ExecState* exec, JSObject*, JSValue, const ArgList& args)
    121 {
    122     return jsDoubleNumber(exec, acos(args.at(0).toNumber(exec)));
    123 }
    124 
    125 JSValue JSC_HOST_CALL mathProtoFuncASin(ExecState* exec, JSObject*, JSValue, const ArgList& args)
    126 {
    127     return jsDoubleNumber(exec, asin(args.at(0).toNumber(exec)));
    128 }
    129 
    130 JSValue JSC_HOST_CALL mathProtoFuncATan(ExecState* exec, JSObject*, JSValue, const ArgList& args)
    131 {
    132     return jsDoubleNumber(exec, atan(args.at(0).toNumber(exec)));
    133 }
    134 
    135 JSValue JSC_HOST_CALL mathProtoFuncATan2(ExecState* exec, JSObject*, JSValue, const ArgList& args)
    136 {
    137     return jsDoubleNumber(exec, atan2(args.at(0).toNumber(exec), args.at(1).toNumber(exec)));
    138 }
    139 
    140 JSValue JSC_HOST_CALL mathProtoFuncCeil(ExecState* exec, JSObject*, JSValue, const ArgList& args)
    141 {
    142     return jsNumber(exec, ceil(args.at(0).toNumber(exec)));
    143 }
    144 
    145 JSValue JSC_HOST_CALL mathProtoFuncCos(ExecState* exec, JSObject*, JSValue, const ArgList& args)
    146 {
    147     return jsDoubleNumber(exec, cos(args.at(0).toNumber(exec)));
    148 }
    149 
    150 JSValue JSC_HOST_CALL mathProtoFuncExp(ExecState* exec, JSObject*, JSValue, const ArgList& args)
    151 {
    152     return jsDoubleNumber(exec, exp(args.at(0).toNumber(exec)));
    153 }
    154 
    155 JSValue JSC_HOST_CALL mathProtoFuncFloor(ExecState* exec, JSObject*, JSValue, const ArgList& args)
    156 {
    157     return jsNumber(exec, floor(args.at(0).toNumber(exec)));
    158 }
    159 
    160 JSValue JSC_HOST_CALL mathProtoFuncLog(ExecState* exec, JSObject*, JSValue, const ArgList& args)
    161 {
    162     return jsDoubleNumber(exec, log(args.at(0).toNumber(exec)));
    163 }
    164 
    165 JSValue JSC_HOST_CALL mathProtoFuncMax(ExecState* exec, JSObject*, JSValue, const ArgList& args)
    166 {
    167     unsigned argsCount = args.size();
    168     double result = -Inf;
    169     for (unsigned k = 0; k < argsCount; ++k) {
    170         double val = args.at(k).toNumber(exec);
    171         if (isnan(val)) {
    172             result = NaN;
    173             break;
    174         }
    175         if (val > result || (val == 0 && result == 0 && !signbit(val)))
    176             result = val;
    177     }
    178     return jsNumber(exec, result);
    179 }
    180 
    181 JSValue JSC_HOST_CALL mathProtoFuncMin(ExecState* exec, JSObject*, JSValue, const ArgList& args)
    182 {
    183     unsigned argsCount = args.size();
    184     double result = +Inf;
    185     for (unsigned k = 0; k < argsCount; ++k) {
    186         double val = args.at(k).toNumber(exec);
    187         if (isnan(val)) {
    188             result = NaN;
    189             break;
    190         }
    191         if (val < result || (val == 0 && result == 0 && signbit(val)))
    192             result = val;
    193     }
    194     return jsNumber(exec, result);
    195 }
    196 
    197 JSValue JSC_HOST_CALL mathProtoFuncPow(ExecState* exec, JSObject*, JSValue, const ArgList& args)
    198 {
    199     // ECMA 15.8.2.1.13
    200 
    201     double arg = args.at(0).toNumber(exec);
    202     double arg2 = args.at(1).toNumber(exec);
    203 
    204     if (isnan(arg2))
    205         return jsNaN(exec);
    206     if (isinf(arg2) && fabs(arg) == 1)
    207         return jsNaN(exec);
    208     return jsNumber(exec, pow(arg, arg2));
    209 }
    210 
    211 JSValue JSC_HOST_CALL mathProtoFuncRandom(ExecState* exec, JSObject*, JSValue, const ArgList&)
    212 {
    213     return jsDoubleNumber(exec, exec->globalData().weakRandom.get());
    214 }
    215 
    216 JSValue JSC_HOST_CALL mathProtoFuncRound(ExecState* exec, JSObject*, JSValue, const ArgList& args)
    217 {
    218     double arg = args.at(0).toNumber(exec);
    219     if (signbit(arg) && arg >= -0.5)
    220          return jsNumber(exec, -0.0);
    221     double integer = ceil(arg);
    222     return jsNumber(exec, integer - (integer - arg > 0.5));
    223 }
    224 
    225 JSValue JSC_HOST_CALL mathProtoFuncSin(ExecState* exec, JSObject*, JSValue, const ArgList& args)
    226 {
    227     return jsDoubleNumber(exec, sin(args.at(0).toNumber(exec)));
    228 }
    229 
    230 JSValue JSC_HOST_CALL mathProtoFuncSqrt(ExecState* exec, JSObject*, JSValue, const ArgList& args)
    231 {
    232     return jsDoubleNumber(exec, sqrt(args.at(0).toNumber(exec)));
    233 }
    234 
    235 JSValue JSC_HOST_CALL mathProtoFuncTan(ExecState* exec, JSObject*, JSValue, const ArgList& args)
    236 {
    237     return jsDoubleNumber(exec, tan(args.at(0).toNumber(exec)));
    238 }
    239 
    240 } // namespace JSC
    241