MathObject.cpp revision 635860845790a19bf50bbc51ba8fb66a96dde068
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
32namespace JSC {
33
34ASSERT_CLASS_FITS_IN_CELL(MathObject);
35
36static JSValuePtr mathProtoFuncAbs(ExecState*, JSObject*, JSValuePtr, const ArgList&);
37static JSValuePtr mathProtoFuncACos(ExecState*, JSObject*, JSValuePtr, const ArgList&);
38static JSValuePtr mathProtoFuncASin(ExecState*, JSObject*, JSValuePtr, const ArgList&);
39static JSValuePtr mathProtoFuncATan(ExecState*, JSObject*, JSValuePtr, const ArgList&);
40static JSValuePtr mathProtoFuncATan2(ExecState*, JSObject*, JSValuePtr, const ArgList&);
41static JSValuePtr mathProtoFuncCeil(ExecState*, JSObject*, JSValuePtr, const ArgList&);
42static JSValuePtr mathProtoFuncCos(ExecState*, JSObject*, JSValuePtr, const ArgList&);
43static JSValuePtr mathProtoFuncExp(ExecState*, JSObject*, JSValuePtr, const ArgList&);
44static JSValuePtr mathProtoFuncFloor(ExecState*, JSObject*, JSValuePtr, const ArgList&);
45static JSValuePtr mathProtoFuncLog(ExecState*, JSObject*, JSValuePtr, const ArgList&);
46static JSValuePtr mathProtoFuncMax(ExecState*, JSObject*, JSValuePtr, const ArgList&);
47static JSValuePtr mathProtoFuncMin(ExecState*, JSObject*, JSValuePtr, const ArgList&);
48static JSValuePtr mathProtoFuncPow(ExecState*, JSObject*, JSValuePtr, const ArgList&);
49static JSValuePtr mathProtoFuncRandom(ExecState*, JSObject*, JSValuePtr, const ArgList&);
50static JSValuePtr mathProtoFuncRound(ExecState*, JSObject*, JSValuePtr, const ArgList&);
51static JSValuePtr mathProtoFuncSin(ExecState*, JSObject*, JSValuePtr, const ArgList&);
52static JSValuePtr mathProtoFuncSqrt(ExecState*, JSObject*, JSValuePtr, const ArgList&);
53static JSValuePtr mathProtoFuncTan(ExecState*, JSObject*, JSValuePtr, const ArgList&);
54
55}
56
57#include "MathObject.lut.h"
58
59namespace JSC {
60
61// ------------------------------ MathObject --------------------------------
62
63const 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
88MathObject::MathObject(ExecState* exec, PassRefPtr<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    WTF::initializeWeakRandomNumberGenerator();
100}
101
102// ECMA 15.8
103
104bool MathObject::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot &slot)
105{
106    const HashEntry* entry = ExecState::mathTable(exec)->entry(exec, propertyName);
107
108    if (!entry)
109        return JSObject::getOwnPropertySlot(exec, propertyName, slot);
110
111    ASSERT(entry->attributes() & Function);
112    setUpStaticFunctionSlot(exec, entry, this, propertyName, slot);
113    return true;
114}
115
116// ------------------------------ Functions --------------------------------
117
118JSValuePtr mathProtoFuncAbs(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
119{
120    return jsNumber(exec, fabs(args.at(exec, 0).toNumber(exec)));
121}
122
123JSValuePtr mathProtoFuncACos(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
124{
125    return jsNumber(exec, acos(args.at(exec, 0).toNumber(exec)));
126}
127
128JSValuePtr mathProtoFuncASin(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
129{
130    return jsNumber(exec, asin(args.at(exec, 0).toNumber(exec)));
131}
132
133JSValuePtr mathProtoFuncATan(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
134{
135    return jsNumber(exec, atan(args.at(exec, 0).toNumber(exec)));
136}
137
138JSValuePtr mathProtoFuncATan2(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
139{
140    return jsNumber(exec, atan2(args.at(exec, 0).toNumber(exec), args.at(exec, 1).toNumber(exec)));
141}
142
143JSValuePtr mathProtoFuncCeil(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
144{
145    return jsNumber(exec, ceil(args.at(exec, 0).toNumber(exec)));
146}
147
148JSValuePtr mathProtoFuncCos(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
149{
150    return jsNumber(exec, cos(args.at(exec, 0).toNumber(exec)));
151}
152
153JSValuePtr mathProtoFuncExp(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
154{
155    return jsNumber(exec, exp(args.at(exec, 0).toNumber(exec)));
156}
157
158JSValuePtr mathProtoFuncFloor(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
159{
160    return jsNumber(exec, floor(args.at(exec, 0).toNumber(exec)));
161}
162
163JSValuePtr mathProtoFuncLog(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
164{
165    return jsNumber(exec, log(args.at(exec, 0).toNumber(exec)));
166}
167
168JSValuePtr mathProtoFuncMax(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
169{
170    unsigned argsCount = args.size();
171    double result = -Inf;
172    for (unsigned k = 0; k < argsCount; ++k) {
173        double val = args.at(exec, k).toNumber(exec);
174        if (isnan(val)) {
175            result = NaN;
176            break;
177        }
178        if (val > result || (val == 0 && result == 0 && !signbit(val)))
179            result = val;
180    }
181    return jsNumber(exec, result);
182}
183
184JSValuePtr mathProtoFuncMin(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
185{
186    unsigned argsCount = args.size();
187    double result = +Inf;
188    for (unsigned k = 0; k < argsCount; ++k) {
189        double val = args.at(exec, k).toNumber(exec);
190        if (isnan(val)) {
191            result = NaN;
192            break;
193        }
194        if (val < result || (val == 0 && result == 0 && signbit(val)))
195            result = val;
196    }
197    return jsNumber(exec, result);
198}
199
200JSValuePtr mathProtoFuncPow(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
201{
202    // ECMA 15.8.2.1.13
203
204    double arg = args.at(exec, 0).toNumber(exec);
205    double arg2 = args.at(exec, 1).toNumber(exec);
206
207    if (isnan(arg2))
208        return jsNaN(exec);
209    if (isinf(arg2) && fabs(arg) == 1)
210        return jsNaN(exec);
211    return jsNumber(exec, pow(arg, arg2));
212}
213
214JSValuePtr mathProtoFuncRandom(ExecState* exec, JSObject*, JSValuePtr, const ArgList&)
215{
216    return jsNumber(exec, WTF::weakRandomNumber());
217}
218
219JSValuePtr mathProtoFuncRound(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
220{
221    double arg = args.at(exec, 0).toNumber(exec);
222    if (signbit(arg) && arg >= -0.5)
223         return jsNumber(exec, -0.0);
224    return jsNumber(exec, floor(arg + 0.5));
225}
226
227JSValuePtr mathProtoFuncSin(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
228{
229    return jsNumber(exec, sin(args.at(exec, 0).toNumber(exec)));
230}
231
232JSValuePtr mathProtoFuncSqrt(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
233{
234    return jsNumber(exec, sqrt(args.at(exec, 0).toNumber(exec)));
235}
236
237JSValuePtr mathProtoFuncTan(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
238{
239    return jsNumber(exec, tan(args.at(exec, 0).toNumber(exec)));
240}
241
242} // namespace JSC
243