00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
#ifdef HAVE_CONFIG_H
00024
#include "config.h"
00025
#endif
00026
#ifndef HAVE_FLOAT_H
00027
#define HAVE_FLOAT_H 0
00028
#define HAVE_FUNC__FINITE 0
00029
#endif
00030
00031
#include <stdio.h>
00032
#include <assert.h>
00033
#include <math.h>
00034
#include <stdlib.h>
00035
00036
00037
#ifdef __SUNPRO_CC
00038
#include <sunmath.h>
00039
#endif
00040
00041
#ifndef HAVE_FUNC_ISINF
00042
#ifdef HAVE_IEEEFP_H
00043
#include <ieeefp.h>
00044
#endif
00045
#endif
00046
00047
#if HAVE_FLOAT_H
00048
#include <float.h>
00049
#endif
00050
00051
#include "operations.h"
00052
#include "object.h"
00053
00054
using namespace KJS;
00055
00056
bool KJS::isNaN(
double d)
00057 {
00058
#ifdef HAVE_FUNC_ISNAN
00059
return isnan(d);
00060
#elif defined HAVE_FLOAT_H
00061
return _isnan(d) != 0;
00062
#else
00063
return !(d == d);
00064
#endif
00065
}
00066
00067
bool KJS::isInf(
double d)
00068 {
00069
#if defined(HAVE_FUNC_ISINF)
00070
return isinf(d);
00071
#elif HAVE_FUNC_FINITE
00072
return finite(d) == 0 && d == d;
00073
#elif HAVE_FUNC__FINITE
00074
return _finite(d) == 0 && d == d;
00075
#else
00076
return false;
00077
#endif
00078
}
00079
00080
bool KJS::isPosInf(
double d)
00081 {
00082
#if defined(HAVE_FUNC_ISINF)
00083
return (isinf(d) == 1);
00084
#elif HAVE_FUNC_FINITE
00085
return finite(d) == 0 && d == d;
00086
#elif HAVE_FUNC__FINITE
00087
return _finite(d) == 0 && d == d;
00088
#else
00089
return false;
00090
#endif
00091
}
00092
00093
bool KJS::isNegInf(
double d)
00094 {
00095
#if defined(HAVE_FUNC_ISINF)
00096
return (isinf(d) == -1);
00097
#elif HAVE_FUNC_FINITE
00098
return finite(d) == 0 && d == d;
00099
#elif HAVE_FUNC__FINITE
00100
return _finite(d) == 0 && d == d;
00101
#else
00102
return false;
00103
#endif
00104
}
00105
00106
00107
bool KJS::equal(
ExecState *exec,
const Value& v1,
const Value& v2)
00108 {
00109 Type t1 = v1.
type();
00110 Type t2 = v2.
type();
00111
00112
if (t1 == t2) {
00113
if (t1 == UndefinedType || t1 == NullType)
00114
return true;
00115
if (t1 == NumberType)
00116 {
00117
double d1 = v1.
toNumber(exec);
00118
double d2 = v2.
toNumber(exec);
00119
if ( isNaN( d1 ) || isNaN( d2 ) )
00120
return false;
00121
return ( d1 == d2 );
00122 }
00123
if (t1 == StringType)
00124
return (v1.
toString(exec) == v2.
toString(exec));
00125
if (t1 == BooleanType)
00126
return (v1.
toBoolean(exec) == v2.
toBoolean(exec));
00127
00128
00129
return (v1.
imp() == v2.
imp());
00130 }
00131
00132
00133
if ((t1 == NullType && t2 == UndefinedType) || (t1 == UndefinedType && t2 == NullType))
00134
return true;
00135
if (t1 == NumberType && t2 == StringType) {
00136
Number n2 = v2.
toNumber(exec);
00137
return equal(exec,v1, n2);
00138 }
00139
if ((t1 == StringType && t2 == NumberType) || t1 == BooleanType) {
00140
Number n1 = v1.
toNumber(exec);
00141
return equal(exec,n1, v2);
00142 }
00143
if (t2 == BooleanType) {
00144
Number n2 = v2.
toNumber(exec);
00145
return equal(exec,v1, n2);
00146 }
00147
if ((t1 == StringType || t1 == NumberType) && t2 >= ObjectType) {
00148
Value p2 = v2.
toPrimitive(exec);
00149
return equal(exec,v1, p2);
00150 }
00151
if (t1 >= ObjectType && (t2 == StringType || t2 == NumberType)) {
00152
Value p1 = v1.
toPrimitive(exec);
00153
return equal(exec,p1, v2);
00154 }
00155
00156
return false;
00157 }
00158
00159
bool KJS::strictEqual(
ExecState *exec,
const Value &v1,
const Value &v2)
00160 {
00161 Type t1 = v1.
type();
00162 Type t2 = v2.
type();
00163
00164
if (t1 != t2)
00165
return false;
00166
if (t1 == UndefinedType || t1 == NullType)
00167
return true;
00168
if (t1 == NumberType) {
00169
double n1 = v1.
toNumber(exec);
00170
double n2 = v2.
toNumber(exec);
00171
if (isNaN(n1) || isNaN(n2))
00172
return false;
00173
if (n1 == n2)
00174
return true;
00175
00176
return false;
00177 }
else if (t1 == StringType) {
00178
return v1.
toString(exec) == v2.
toString(exec);
00179 }
else if (t2 == BooleanType) {
00180
return v1.
toBoolean(exec) == v2.
toBoolean(exec);
00181 }
00182
if (v1.
imp() == v2.
imp())
00183
return true;
00184
00185
00186
return false;
00187 }
00188
00189
int KJS::relation(
ExecState *exec,
const Value& v1,
const Value& v2)
00190 {
00191
Value p1 = v1.
toPrimitive(exec,NumberType);
00192
Value p2 = v2.
toPrimitive(exec,NumberType);
00193
00194
if (p1.
type() == StringType && p2.
type() == StringType)
00195
return p1.
toString(exec) < p2.
toString(exec) ? 1 : 0;
00196
00197
double n1 = p1.
toNumber(exec);
00198
double n2 = p2.
toNumber(exec);
00199
if ( isNaN( n1 ) || isNaN( n2 ) )
00200
return -1;
00201
if (n1 == n2)
00202
return 0;
00203
00204
if ( isPosInf( n1 ) )
00205
return 0;
00206
if ( isPosInf( n2 ) )
00207
return 1;
00208
if ( isNegInf( n2 ) )
00209
return 0;
00210
if ( isNegInf( n1 ) )
00211
return 1;
00212
return (n1 < n2) ? 1 : 0;
00213 }
00214
00215
int KJS::maxInt(
int d1,
int d2)
00216 {
00217
return (d1 > d2) ? d1 : d2;
00218 }
00219
00220
int KJS::minInt(
int d1,
int d2)
00221 {
00222
return (d1 < d2) ? d1 : d2;
00223 }
00224
00225
00226
Value KJS::add(
ExecState *exec,
const Value &v1,
const Value &v2,
char oper)
00227 {
00228
00229 Type preferred = oper ==
'+' ? UnspecifiedType : NumberType;
00230
Value p1 = v1.
toPrimitive(exec, preferred);
00231
Value p2 = v2.
toPrimitive(exec, preferred);
00232
00233
if ((p1.
type() == StringType || p2.
type() == StringType) && oper ==
'+') {
00234
UString s1 = p1.
toString(exec);
00235
UString s2 = p2.
toString(exec);
00236
00237
return String(s1 + s2);
00238 }
00239
00240
double n1 = p1.
toNumber(exec);
00241
double n2 = p2.
toNumber(exec);
00242
00243
if (oper ==
'+')
00244
return Number(n1 + n2);
00245
else
00246
return Number(n1 - n2);
00247 }
00248
00249
00250
Value KJS::mult(
ExecState *exec,
const Value &v1,
const Value &v2,
char oper)
00251 {
00252
double n1 = v1.
toNumber(exec);
00253
double n2 = v2.
toNumber(exec);
00254
00255
double result;
00256
00257
if (oper ==
'*')
00258 result = n1 * n2;
00259
else if (oper ==
'/')
00260 result = n1 / n2;
00261
else
00262 result = fmod(n1, n2);
00263
00264
return Number(result);
00265 }