fix logic
[personal-kdelibs.git] / kjs / math_object.cpp
blob11cbb7467392c06f38a75e30e312a81f56f32f3c
1 // -*- c-basic-offset: 2 -*-
2 /*
3 * This file is part of the KDE libraries
4 * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 #include "math_object.h"
23 #include <config.h>
24 #include "math_object.lut.h"
25 #include "wtf/MathExtras.h"
27 #include "operations.h"
28 #include <math.h>
29 #include <time.h>
31 #ifndef M_PI
32 #define M_PI 3.14159265358979323846
33 #endif /* M_PI */
35 using namespace KJS;
37 // ------------------------------ MathObjectImp --------------------------------
39 const ClassInfo MathObjectImp::info = { "Math", 0, &mathTable, 0 };
41 /* Source for math_object.lut.h
42 @begin mathTable 21
43 E MathObjectImp::Euler DontEnum|DontDelete|ReadOnly
44 LN2 MathObjectImp::Ln2 DontEnum|DontDelete|ReadOnly
45 LN10 MathObjectImp::Ln10 DontEnum|DontDelete|ReadOnly
46 LOG2E MathObjectImp::Log2E DontEnum|DontDelete|ReadOnly
47 LOG10E MathObjectImp::Log10E DontEnum|DontDelete|ReadOnly
48 PI MathObjectImp::Pi DontEnum|DontDelete|ReadOnly
49 SQRT1_2 MathObjectImp::Sqrt1_2 DontEnum|DontDelete|ReadOnly
50 SQRT2 MathObjectImp::Sqrt2 DontEnum|DontDelete|ReadOnly
51 abs MathObjectImp::Abs DontEnum|Function 1
52 acos MathObjectImp::ACos DontEnum|Function 1
53 asin MathObjectImp::ASin DontEnum|Function 1
54 atan MathObjectImp::ATan DontEnum|Function 1
55 atan2 MathObjectImp::ATan2 DontEnum|Function 2
56 ceil MathObjectImp::Ceil DontEnum|Function 1
57 cos MathObjectImp::Cos DontEnum|Function 1
58 exp MathObjectImp::Exp DontEnum|Function 1
59 floor MathObjectImp::Floor DontEnum|Function 1
60 log MathObjectImp::Log DontEnum|Function 1
61 max MathObjectImp::Max DontEnum|Function 2
62 min MathObjectImp::Min DontEnum|Function 2
63 pow MathObjectImp::Pow DontEnum|Function 2
64 random MathObjectImp::Random DontEnum|Function 0
65 round MathObjectImp::Round DontEnum|Function 1
66 sin MathObjectImp::Sin DontEnum|Function 1
67 sqrt MathObjectImp::Sqrt DontEnum|Function 1
68 tan MathObjectImp::Tan DontEnum|Function 1
69 @end
72 MathObjectImp::MathObjectImp(ExecState * /*exec*/,
73 ObjectPrototype *objProto)
74 : JSObject(objProto)
78 // ECMA 15.8
80 bool MathObjectImp::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot &slot)
82 return getStaticPropertySlot<MathFuncImp, MathObjectImp, JSObject>(exec, &mathTable, this, propertyName, slot);
85 JSValue *MathObjectImp::getValueProperty(ExecState *, int token) const
87 switch (token) {
88 case Euler:
89 return jsNumber(exp(1.0));
90 case Ln2:
91 return jsNumber(log(2.0));
92 case Ln10:
93 return jsNumber(log(10.0));
94 case Log2E:
95 return jsNumber(1.0/log(2.0));
96 case Log10E:
97 return jsNumber(1.0/log(10.0));
98 case Pi:
99 return jsNumber(piDouble);
100 case Sqrt1_2:
101 return jsNumber(sqrt(0.5));
102 case Sqrt2:
103 return jsNumber(sqrt(2.0));
106 assert(0);
107 return 0;
110 // ------------------------------ MathObjectImp --------------------------------
112 static bool randomSeeded = false;
114 MathFuncImp::MathFuncImp(ExecState* exec, int i, int l, const Identifier& name)
115 : InternalFunctionImp(static_cast<FunctionPrototype*>(exec->lexicalInterpreter()->builtinFunctionPrototype()), name)
116 , id(i)
118 putDirect(exec->propertyNames().length, l, DontDelete|ReadOnly|DontEnum);
121 JSValue *MathFuncImp::callAsFunction(ExecState *exec, JSObject* /*thisObj*/, const List &args)
123 double arg = args[0]->toNumber(exec);
124 double arg2 = args[1]->toNumber(exec);
125 double result;
127 switch (id) {
128 case MathObjectImp::Abs:
129 result = ( arg < 0 || arg == -0) ? (-arg) : arg;
130 break;
131 case MathObjectImp::ACos:
132 result = ::acos(arg);
133 break;
134 case MathObjectImp::ASin:
135 result = ::asin(arg);
136 break;
137 case MathObjectImp::ATan:
138 result = ::atan(arg);
139 break;
140 case MathObjectImp::ATan2:
141 result = ::atan2(arg, arg2);
142 break;
143 case MathObjectImp::Ceil:
144 result = ::ceil(arg);
145 break;
146 case MathObjectImp::Cos:
147 result = ::cos(arg);
148 break;
149 case MathObjectImp::Exp:
150 result = ::exp(arg);
151 break;
152 case MathObjectImp::Floor:
153 result = ::floor(arg);
154 break;
155 case MathObjectImp::Log:
156 result = ::log(arg);
157 break;
158 case MathObjectImp::Max: {
159 unsigned int argsCount = args.size();
160 result = -Inf;
161 for ( unsigned int k = 0 ; k < argsCount ; ++k ) {
162 double val = args[k]->toNumber(exec);
163 if ( isNaN( val ) )
165 result = NaN;
166 break;
168 if ( val > result || (val == 0 && result == 0 && !signbit(val)) )
169 result = val;
171 break;
173 case MathObjectImp::Min: {
174 unsigned int argsCount = args.size();
175 result = +Inf;
176 for ( unsigned int k = 0 ; k < argsCount ; ++k ) {
177 double val = args[k]->toNumber(exec);
178 if ( isNaN( val ) )
180 result = NaN;
181 break;
183 if ( val < result || (val == 0 && result == 0 && signbit(val)) )
184 result = val;
186 break;
188 case MathObjectImp::Pow:
189 // ECMA 15.8.2.1.13 (::pow takes care of most of the critera)
190 if (isNaN(arg2))
191 result = NaN;
192 else if (isNaN(arg) && arg2 != 0)
193 result = NaN;
194 else if (::fabs(arg) == 1 && isInf(arg2))
195 result = NaN;
196 else if (arg2 == 0 && arg != 0)
197 result = 1;
198 else
199 result = ::pow(arg, arg2);
200 break;
201 case MathObjectImp::Random:
202 if (!randomSeeded) {
203 srand(static_cast<unsigned>(time(0)));
204 randomSeeded = true;
206 result = (double)rand() / RAND_MAX;
207 break;
208 case MathObjectImp::Round:
209 if (signbit(arg) && arg >= -0.5)
210 result = -0.0;
211 else
212 result = ::floor(arg + 0.5);
213 break;
214 case MathObjectImp::Sin:
215 result = ::sin(arg);
216 break;
217 case MathObjectImp::Sqrt:
218 result = ::sqrt(arg);
219 break;
220 case MathObjectImp::Tan:
221 result = ::tan(arg);
222 break;
224 default:
225 result = 0.0;
226 assert(0);
229 return jsNumber(result);