source: webkit/trunk/JavaScriptCore/kjs/operations.cpp@ 18837

Last change on this file since 18837 was 15155, checked in by darin, 19 years ago

Reviewed by Maciej.
Tweaked a bit by Darin.

  • wtf/MathExtras.h: Added include of <float.h>. (isinf): Fix to return false for NAN. (wtf_fmod): Added. An inline that works around the bug.
  • kjs/nodes.cpp:
  • kjs/number_object.cpp:
  • kjs/operations.cpp:
  • kjs/value.cpp: Added includes of MathExtras.h to all files using fmod.
  • JavaScriptCore.xcodeproj/project.pbxproj: Let Xcode 2.3 have its way with the project.
  • Property svn:eol-style set to native
File size: 6.5 KB
Line 
1// -*- c-basic-offset: 2 -*-
2/*
3 * This file is part of the KDE libraries
4 * Copyright (C) 1999-2000 Harri Porten ([email protected])
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library 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.
10 *
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 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public License
17 * along with this library; see the file COPYING.LIB. If not, write to
18 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
20 *
21 */
22
23#include "config.h"
24#include "operations.h"
25
26#include "object.h"
27#include <math.h>
28#include <stdio.h>
29#include <wtf/MathExtras.h>
30
31#if HAVE(FUNC_ISINF) && HAVE(IEEEFP_H)
32#include <ieeefp.h>
33#endif
34
35#if HAVE(FLOAT_H)
36#include <float.h>
37#endif
38
39namespace KJS {
40
41#if !PLATFORM(DARWIN)
42
43// FIXME: Should probably be inlined on non-Darwin platforms too, and controlled exclusively
44// by HAVE macros rather than PLATFORM.
45
46// FIXME: Merge with isnan in MathExtras.h and remove this one entirely.
47bool isNaN(double d)
48{
49#if HAVE(FUNC_ISNAN)
50 return isnan(d);
51#elif HAVE(FLOAT_H)
52 return _isnan(d) != 0;
53#else
54 return !(d == d);
55#endif
56}
57
58// FIXME: Merge with isinf in MathExtras.h and remove this one entirely.
59bool isInf(double d)
60{
61 // FIXME: should be HAVE(_FPCLASS)
62#if PLATFORM(WIN_OS)
63 int fpClass = _fpclass(d);
64 return _FPCLASS_PINF == fpClass || _FPCLASS_NINF == fpClass;
65#elif HAVE(FUNC_ISINF)
66 return isinf(d);
67#elif HAVE(FUNC_FINITE)
68 return finite(d) == 0 && d == d;
69#elif HAVE(FUNC__FINITE)
70 return _finite(d) == 0 && d == d;
71#else
72 return false;
73#endif
74}
75
76bool isPosInf(double d)
77{
78 // FIXME: should be HAVE(_FPCLASS)
79#if PLATFORM(WIN_OS)
80 return _FPCLASS_PINF == _fpclass(d);
81#elif HAVE(FUNC_ISINF)
82 return (isinf(d) == 1);
83#elif HAVE(FUNC_FINITE)
84 return !finite(d) && d == d; // ### can we distinguish between + and - ?
85#elif HAVE(FUNC__FINITE)
86 return !_finite(d) && d == d; // ###
87#else
88 return false;
89#endif
90}
91
92bool isNegInf(double d)
93{
94 // FIXME: should be HAVE(_FPCLASS)
95#if PLATFORM(WIN_OS)
96 return _FPCLASS_NINF == _fpclass(d);
97#elif HAVE(FUNC_ISINF)
98 return (isinf(d) == -1);
99#elif HAVE(FUNC_FINITE)
100 return finite(d) == 0 && d == d; // ###
101#elif HAVE(FUNC__FINITE)
102 return _finite(d) == 0 && d == d; // ###
103#else
104 return false;
105#endif
106}
107
108#endif
109
110// ECMA 11.9.3
111bool equal(ExecState *exec, JSValue *v1, JSValue *v2)
112{
113 JSType t1 = v1->type();
114 JSType t2 = v2->type();
115
116 if (t1 != t2) {
117 if (t1 == UndefinedType)
118 t1 = NullType;
119 if (t2 == UndefinedType)
120 t2 = NullType;
121
122 if (t1 == BooleanType)
123 t1 = NumberType;
124 if (t2 == BooleanType)
125 t2 = NumberType;
126
127 if (t1 == NumberType && t2 == StringType) {
128 // use toNumber
129 } else if (t1 == StringType && t2 == NumberType)
130 t1 = NumberType;
131 // use toNumber
132 else {
133 if ((t1 == StringType || t1 == NumberType) && t2 >= ObjectType)
134 return equal(exec, v1, v2->toPrimitive(exec));
135 if (t1 == NullType && t2 == ObjectType)
136 return static_cast<JSObject *>(v2)->masqueradeAsUndefined();
137 if (t1 >= ObjectType && (t2 == StringType || t2 == NumberType))
138 return equal(exec, v1->toPrimitive(exec), v2);
139 if (t1 == ObjectType && t2 == NullType)
140 return static_cast<JSObject *>(v1)->masqueradeAsUndefined();
141 if (t1 != t2)
142 return false;
143 }
144 }
145
146 if (t1 == UndefinedType || t1 == NullType)
147 return true;
148
149 if (t1 == NumberType) {
150 double d1 = v1->toNumber(exec);
151 double d2 = v2->toNumber(exec);
152 return d1 == d2;
153 }
154
155 if (t1 == StringType)
156 return v1->toString(exec) == v2->toString(exec);
157
158 if (t1 == BooleanType)
159 return v1->toBoolean(exec) == v2->toBoolean(exec);
160
161 // types are Object
162 return v1 == v2;
163}
164
165bool strictEqual(ExecState *exec, JSValue *v1, JSValue *v2)
166{
167 JSType t1 = v1->type();
168 JSType t2 = v2->type();
169
170 if (t1 != t2)
171 return false;
172 if (t1 == UndefinedType || t1 == NullType)
173 return true;
174 if (t1 == NumberType) {
175 double n1 = v1->toNumber(exec);
176 double n2 = v2->toNumber(exec);
177 if (n1 == n2)
178 return true;
179 return false;
180 } else if (t1 == StringType)
181 return v1->toString(exec) == v2->toString(exec);
182 else if (t2 == BooleanType)
183 return v1->toBoolean(exec) == v2->toBoolean(exec);
184
185 if (v1 == v2)
186 return true;
187 /* TODO: joined objects */
188
189 return false;
190}
191
192int relation(ExecState *exec, JSValue *v1, JSValue *v2)
193{
194 JSValue *p1 = v1->toPrimitive(exec,NumberType);
195 JSValue *p2 = v2->toPrimitive(exec,NumberType);
196
197 if (p1->isString() && p2->isString())
198 return p1->toString(exec) < p2->toString(exec) ? 1 : 0;
199
200 double n1 = p1->toNumber(exec);
201 double n2 = p2->toNumber(exec);
202 if (n1 < n2)
203 return 1;
204 if (n1 >= n2)
205 return 0;
206 return -1; // must be NaN, so undefined
207}
208
209int maxInt(int d1, int d2)
210{
211 return (d1 > d2) ? d1 : d2;
212}
213
214int minInt(int d1, int d2)
215{
216 return (d1 < d2) ? d1 : d2;
217}
218
219// ECMA 11.6
220JSValue *add(ExecState *exec, JSValue *v1, JSValue *v2, char oper)
221{
222 // exception for the Date exception in defaultValue()
223 JSType preferred = oper == '+' ? UnspecifiedType : NumberType;
224 JSValue *p1 = v1->toPrimitive(exec, preferred);
225 JSValue *p2 = v2->toPrimitive(exec, preferred);
226
227 if ((p1->isString() || p2->isString()) && oper == '+')
228 return jsString(p1->toString(exec) + p2->toString(exec));
229
230 if (oper == '+')
231 return jsNumber(p1->toNumber(exec) + p2->toNumber(exec));
232 else
233 return jsNumber(p1->toNumber(exec) - p2->toNumber(exec));
234}
235
236// ECMA 11.5
237JSValue *mult(ExecState *exec, JSValue *v1, JSValue *v2, char oper)
238{
239 double n1 = v1->toNumber(exec);
240 double n2 = v2->toNumber(exec);
241
242 double result;
243
244 if (oper == '*')
245 result = n1 * n2;
246 else if (oper == '/')
247 result = n1 / n2;
248 else
249 result = fmod(n1, n2);
250
251 return jsNumber(result);
252}
253
254}
Note: See TracBrowser for help on using the repository browser.