]> git.saurik.com Git - apple/javascriptcore.git/blob - kjs/math_object.cpp
805efdacb222820b795d3b37032aec2e27a8ac10
[apple/javascriptcore.git] / kjs / math_object.cpp
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 "math_object.h"
23 #include "math_object.lut.h"
24
25 #include "operations.h"
26 #include <time.h>
27 #include <wtf/Assertions.h>
28 #include <wtf/MathExtras.h>
29
30 namespace KJS {
31
32 // ------------------------------ MathObjectImp --------------------------------
33
34 const ClassInfo MathObjectImp::info = { "Math", 0, &mathTable };
35
36 /* Source for math_object.lut.h
37 @begin mathTable 21
38 E MathObjectImp::Euler DontEnum|DontDelete|ReadOnly
39 LN2 MathObjectImp::Ln2 DontEnum|DontDelete|ReadOnly
40 LN10 MathObjectImp::Ln10 DontEnum|DontDelete|ReadOnly
41 LOG2E MathObjectImp::Log2E DontEnum|DontDelete|ReadOnly
42 LOG10E MathObjectImp::Log10E DontEnum|DontDelete|ReadOnly
43 PI MathObjectImp::Pi DontEnum|DontDelete|ReadOnly
44 SQRT1_2 MathObjectImp::Sqrt1_2 DontEnum|DontDelete|ReadOnly
45 SQRT2 MathObjectImp::Sqrt2 DontEnum|DontDelete|ReadOnly
46 abs mathProtoFuncAbs DontEnum|Function 1
47 acos mathProtoFuncACos DontEnum|Function 1
48 asin mathProtoFuncASin DontEnum|Function 1
49 atan mathProtoFuncATan DontEnum|Function 1
50 atan2 mathProtoFuncATan2 DontEnum|Function 2
51 ceil mathProtoFuncCeil DontEnum|Function 1
52 cos mathProtoFuncCos DontEnum|Function 1
53 exp mathProtoFuncExp DontEnum|Function 1
54 floor mathProtoFuncFloor DontEnum|Function 1
55 log mathProtoFuncLog DontEnum|Function 1
56 max mathProtoFuncMax DontEnum|Function 2
57 min mathProtoFuncMin DontEnum|Function 2
58 pow mathProtoFuncPow DontEnum|Function 2
59 random mathProtoFuncRandom DontEnum|Function 0
60 round mathProtoFuncRound DontEnum|Function 1
61 sin mathProtoFuncSin DontEnum|Function 1
62 sqrt mathProtoFuncSqrt DontEnum|Function 1
63 tan mathProtoFuncTan DontEnum|Function 1
64 @end
65 */
66
67 MathObjectImp::MathObjectImp(ExecState*, ObjectPrototype* objectPrototype)
68 : JSObject(objectPrototype)
69 {
70 }
71
72 // ECMA 15.8
73
74 bool MathObjectImp::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot &slot)
75 {
76 return getStaticPropertySlot<MathObjectImp, JSObject>(exec, &mathTable, this, propertyName, slot);
77 }
78
79 JSValue* MathObjectImp::getValueProperty(ExecState*, int token) const
80 {
81 switch (token) {
82 case Euler:
83 return jsNumber(exp(1.0));
84 case Ln2:
85 return jsNumber(log(2.0));
86 case Ln10:
87 return jsNumber(log(10.0));
88 case Log2E:
89 return jsNumber(1.0 / log(2.0));
90 case Log10E:
91 return jsNumber(1.0 / log(10.0));
92 case Pi:
93 return jsNumber(piDouble);
94 case Sqrt1_2:
95 return jsNumber(sqrt(0.5));
96 case Sqrt2:
97 return jsNumber(sqrt(2.0));
98 }
99
100 ASSERT_NOT_REACHED();
101 return 0;
102 }
103
104 // ------------------------------ Functions --------------------------------
105
106 JSValue* mathProtoFuncAbs(ExecState* exec, JSObject*, const List& args)
107 {
108 double arg = args[0]->toNumber(exec);
109 return signbit(arg) ? jsNumber(-arg) : jsNumber(arg);
110 }
111
112 JSValue* mathProtoFuncACos(ExecState* exec, JSObject*, const List& args)
113 {
114 return jsNumber(acos(args[0]->toNumber(exec)));
115 }
116
117 JSValue* mathProtoFuncASin(ExecState* exec, JSObject*, const List& args)
118 {
119 return jsNumber(asin(args[0]->toNumber(exec)));
120 }
121
122 JSValue* mathProtoFuncATan(ExecState* exec, JSObject*, const List& args)
123 {
124 return jsNumber(atan(args[0]->toNumber(exec)));
125 }
126
127 JSValue* mathProtoFuncATan2(ExecState* exec, JSObject*, const List& args)
128 {
129 return jsNumber(atan2(args[0]->toNumber(exec), args[1]->toNumber(exec)));
130 }
131
132 JSValue* mathProtoFuncCeil(ExecState* exec, JSObject*, const List& args)
133 {
134 double arg = args[0]->toNumber(exec);
135 if (signbit(arg) && arg > -1.0)
136 return jsNumber(-0.0);
137 return jsNumber(ceil(arg));
138 }
139
140 JSValue* mathProtoFuncCos(ExecState* exec, JSObject*, const List& args)
141 {
142 return jsNumber(cos(args[0]->toNumber(exec)));
143 }
144
145 JSValue* mathProtoFuncExp(ExecState* exec, JSObject*, const List& args)
146 {
147 return jsNumber(exp(args[0]->toNumber(exec)));
148 }
149
150 JSValue* mathProtoFuncFloor(ExecState* exec, JSObject*, const List& args)
151 {
152 double arg = args[0]->toNumber(exec);
153 if (signbit(arg) && arg == 0.0)
154 return jsNumber(-0.0);
155 return jsNumber(floor(arg));
156 }
157
158 JSValue* mathProtoFuncLog(ExecState* exec, JSObject*, const List& args)
159 {
160 return jsNumber(log(args[0]->toNumber(exec)));
161 }
162
163 JSValue* mathProtoFuncMax(ExecState* exec, JSObject*, const List& args)
164 {
165 unsigned argsCount = args.size();
166 double result = -Inf;
167 for (unsigned k = 0; k < argsCount; ++k) {
168 double val = args[k]->toNumber(exec);
169 if (isnan(val)) {
170 result = NaN;
171 break;
172 }
173 if (val > result || (val == 0 && result == 0 && !signbit(val)))
174 result = val;
175 }
176 return jsNumber(result);
177 }
178
179 JSValue* mathProtoFuncMin(ExecState* exec, JSObject*, const List& args)
180 {
181 unsigned argsCount = args.size();
182 double result = +Inf;
183 for (unsigned k = 0; k < argsCount; ++k) {
184 double val = args[k]->toNumber(exec);
185 if (isnan(val)) {
186 result = NaN;
187 break;
188 }
189 if (val < result || (val == 0 && result == 0 && signbit(val)))
190 result = val;
191 }
192 return jsNumber(result);
193 }
194
195 JSValue* mathProtoFuncPow(ExecState* exec, JSObject*, const List& args)
196 {
197 // ECMA 15.8.2.1.13
198
199 double arg = args[0]->toNumber(exec);
200 double arg2 = args[1]->toNumber(exec);
201
202 if (isnan(arg2))
203 return jsNumber(NaN);
204 if (isinf(arg2) && fabs(arg) == 1)
205 return jsNumber(NaN);
206 return jsNumber(pow(arg, arg2));
207 }
208
209 static bool didInitRandom;
210
211 JSValue* mathProtoFuncRandom(ExecState*, JSObject*, const List&)
212 {
213 if (!didInitRandom) {
214 wtf_random_init();
215 didInitRandom = true;
216 }
217 return jsNumber(wtf_random());
218 }
219
220 JSValue* mathProtoFuncRound(ExecState* exec, JSObject*, const List& args)
221 {
222 double arg = args[0]->toNumber(exec);
223 if (signbit(arg) && arg >= -0.5)
224 return jsNumber(-0.0);
225 return jsNumber(floor(arg + 0.5));
226 }
227
228 JSValue* mathProtoFuncSin(ExecState* exec, JSObject*, const List& args)
229 {
230 return jsNumber(sin(args[0]->toNumber(exec)));
231 }
232
233 JSValue* mathProtoFuncSqrt(ExecState* exec, JSObject*, const List& args)
234 {
235 return jsNumber(sqrt(args[0]->toNumber(exec)));
236 }
237
238 JSValue* mathProtoFuncTan(ExecState* exec, JSObject*, const List& args)
239 {
240 return jsNumber(tan(args[0]->toNumber(exec)));
241 }
242
243 } // namespace KJS