| 1 | /* | 
| 2 |  *  Copyright (C) 1999-2000 Harri Porten (porten@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 = { .className: "Math" , .parentClass: 0, .staticPropHashTable: 0, .classPropHashTableGetterFunction: 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(propertyName: Identifier(exec, "E" ), value: jsNumber(exec, d: exp(x: 1.0)), attributes: DontDelete | DontEnum | ReadOnly); | 
| 92 |     putDirectWithoutTransition(propertyName: Identifier(exec, "LN2" ), value: jsNumber(exec, d: log(x: 2.0)), attributes: DontDelete | DontEnum | ReadOnly); | 
| 93 |     putDirectWithoutTransition(propertyName: Identifier(exec, "LN10" ), value: jsNumber(exec, d: log(x: 10.0)), attributes: DontDelete | DontEnum | ReadOnly); | 
| 94 |     putDirectWithoutTransition(propertyName: Identifier(exec, "LOG2E" ), value: jsNumber(exec, d: 1.0 / log(x: 2.0)), attributes: DontDelete | DontEnum | ReadOnly); | 
| 95 |     putDirectWithoutTransition(propertyName: Identifier(exec, "LOG10E" ), value: jsNumber(exec, d: 1.0 / log(x: 10.0)), attributes: DontDelete | DontEnum | ReadOnly); | 
| 96 |     putDirectWithoutTransition(propertyName: Identifier(exec, "PI" ), value: jsNumber(exec, d: piDouble), attributes: DontDelete | DontEnum | ReadOnly); | 
| 97 |     putDirectWithoutTransition(propertyName: Identifier(exec, "SQRT1_2" ), value: jsNumber(exec, d: sqrt(x: 0.5)), attributes: DontDelete | DontEnum | ReadOnly); | 
| 98 |     putDirectWithoutTransition(propertyName: Identifier(exec, "SQRT2" ), value: jsNumber(exec, d: sqrt(x: 2.0)), attributes: 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, table: ExecState::mathTable(callFrame: exec), thisObj: this, propertyName, slot); | 
| 106 | } | 
| 107 |  | 
| 108 | bool MathObject::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor) | 
| 109 | { | 
| 110 |     return getStaticFunctionDescriptor<JSObject>(exec, table: ExecState::mathTable(callFrame: exec), thisObj: 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, d: fabs(x: args.at(idx: 0).toNumber(exec))); | 
| 118 | } | 
| 119 |  | 
| 120 | JSValue JSC_HOST_CALL mathProtoFuncACos(ExecState* exec, JSObject*, JSValue, const ArgList& args) | 
| 121 | { | 
| 122 |     return jsDoubleNumber(exec, d: acos(x: args.at(idx: 0).toNumber(exec))); | 
| 123 | } | 
| 124 |  | 
| 125 | JSValue JSC_HOST_CALL mathProtoFuncASin(ExecState* exec, JSObject*, JSValue, const ArgList& args) | 
| 126 | { | 
| 127 |     return jsDoubleNumber(exec, d: asin(x: args.at(idx: 0).toNumber(exec))); | 
| 128 | } | 
| 129 |  | 
| 130 | JSValue JSC_HOST_CALL mathProtoFuncATan(ExecState* exec, JSObject*, JSValue, const ArgList& args) | 
| 131 | { | 
| 132 |     return jsDoubleNumber(exec, d: atan(x: args.at(idx: 0).toNumber(exec))); | 
| 133 | } | 
| 134 |  | 
| 135 | JSValue JSC_HOST_CALL mathProtoFuncATan2(ExecState* exec, JSObject*, JSValue, const ArgList& args) | 
| 136 | { | 
| 137 |     return jsDoubleNumber(exec, d: atan2(y: args.at(idx: 0).toNumber(exec), x: args.at(idx: 1).toNumber(exec))); | 
| 138 | } | 
| 139 |  | 
| 140 | JSValue JSC_HOST_CALL mathProtoFuncCeil(ExecState* exec, JSObject*, JSValue, const ArgList& args) | 
| 141 | { | 
| 142 |     return jsNumber(exec, d: ceil(x: args.at(idx: 0).toNumber(exec))); | 
| 143 | } | 
| 144 |  | 
| 145 | JSValue JSC_HOST_CALL mathProtoFuncCos(ExecState* exec, JSObject*, JSValue, const ArgList& args) | 
| 146 | { | 
| 147 |     return jsDoubleNumber(exec, d: cos(x: args.at(idx: 0).toNumber(exec))); | 
| 148 | } | 
| 149 |  | 
| 150 | JSValue JSC_HOST_CALL mathProtoFuncExp(ExecState* exec, JSObject*, JSValue, const ArgList& args) | 
| 151 | { | 
| 152 |     return jsDoubleNumber(exec, d: exp(x: args.at(idx: 0).toNumber(exec))); | 
| 153 | } | 
| 154 |  | 
| 155 | JSValue JSC_HOST_CALL mathProtoFuncFloor(ExecState* exec, JSObject*, JSValue, const ArgList& args) | 
| 156 | { | 
| 157 |     return jsNumber(exec, d: floor(x: args.at(idx: 0).toNumber(exec))); | 
| 158 | } | 
| 159 |  | 
| 160 | JSValue JSC_HOST_CALL mathProtoFuncLog(ExecState* exec, JSObject*, JSValue, const ArgList& args) | 
| 161 | { | 
| 162 |     return jsDoubleNumber(exec, d: log(x: args.at(idx: 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(idx: k).toNumber(exec); | 
| 171 |         if (std::isnan(x: val)) { | 
| 172 |             result = NaN; | 
| 173 |             break; | 
| 174 |         } | 
| 175 |         if (val > result || (val == 0 && result == 0 && !std::signbit(x: val))) | 
| 176 |             result = val; | 
| 177 |     } | 
| 178 |     return jsNumber(exec, d: 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(idx: k).toNumber(exec); | 
| 187 |         if (std::isnan(x: val)) { | 
| 188 |             result = NaN; | 
| 189 |             break; | 
| 190 |         } | 
| 191 |         if (val < result || (val == 0 && result == 0 && std::signbit(x: val))) | 
| 192 |             result = val; | 
| 193 |     } | 
| 194 |     return jsNumber(exec, d: 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(idx: 0).toNumber(exec); | 
| 202 |     double arg2 = args.at(idx: 1).toNumber(exec); | 
| 203 |  | 
| 204 |     if (std::isnan(x: arg2)) | 
| 205 |         return jsNaN(exec); | 
| 206 |     if (std::isinf(x: arg2) && fabs(x: arg) == 1) | 
| 207 |         return jsNaN(exec); | 
| 208 |     return jsNumber(exec, d: pow(x: arg, y: arg2)); | 
| 209 | } | 
| 210 |  | 
| 211 | JSValue JSC_HOST_CALL mathProtoFuncRandom(ExecState* exec, JSObject*, JSValue, const ArgList&) | 
| 212 | { | 
| 213 |     return jsDoubleNumber(exec, d: exec->lexicalGlobalObject()->weakRandomNumber()); | 
| 214 | } | 
| 215 |  | 
| 216 | JSValue JSC_HOST_CALL mathProtoFuncRound(ExecState* exec, JSObject*, JSValue, const ArgList& args) | 
| 217 | { | 
| 218 |     double arg = args.at(idx: 0).toNumber(exec); | 
| 219 |     if (std::signbit(x: arg) && arg >= -0.5) | 
| 220 |          return jsNumber(exec, d: -0.0); | 
| 221 |     double integer = ceil(x: arg); | 
| 222 |     return jsNumber(exec, d: 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, d: sin(x: args.at(idx: 0).toNumber(exec))); | 
| 228 | } | 
| 229 |  | 
| 230 | JSValue JSC_HOST_CALL mathProtoFuncSqrt(ExecState* exec, JSObject*, JSValue, const ArgList& args) | 
| 231 | { | 
| 232 |     return jsDoubleNumber(exec, d: sqrt(x: args.at(idx: 0).toNumber(exec))); | 
| 233 | } | 
| 234 |  | 
| 235 | JSValue JSC_HOST_CALL mathProtoFuncTan(ExecState* exec, JSObject*, JSValue, const ArgList& args) | 
| 236 | { | 
| 237 |     return jsDoubleNumber(exec, d: tan(x: args.at(idx: 0).toNumber(exec))); | 
| 238 | } | 
| 239 |  | 
| 240 | } // namespace JSC | 
| 241 |  |