00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
#include <math.h>
00023
#include <stdlib.h>
00024
#include <stdio.h>
00025
#include <assert.h>
00026
#include <time.h>
00027
00028
#include "value.h"
00029
#include "object.h"
00030
#include "types.h"
00031
#include "interpreter.h"
00032
#include "operations.h"
00033
#include "math_object.h"
00034
00035
#include "math_object.lut.h"
00036
00037
#ifndef M_PI
00038
#define M_PI 3.14159265358979323846
00039
#endif
00040
00041
using namespace KJS;
00042
00043
00044
00045
const ClassInfo MathObjectImp::info = {
"Math", 0, &mathTable, 0 };
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078 MathObjectImp::MathObjectImp(
ExecState * ,
00079 ObjectPrototypeImp *objProto)
00080 : ObjectImp(objProto)
00081 {
00082
unsigned int seed = time(NULL);
00083 ::srand(seed);
00084 }
00085
00086
00087
Value MathObjectImp::get(
ExecState *exec,
const Identifier &propertyName)
const
00088
{
00089
return lookupGet<MathFuncImp, MathObjectImp, ObjectImp>( exec, propertyName, &mathTable,
this );
00090 }
00091
00092
Value MathObjectImp::getValueProperty(
ExecState *,
int token)
const
00093
{
00094
double d = -42;
00095
switch (token) {
00096
case Euler:
00097 d = exp(1.0);
00098
break;
00099
case Ln2:
00100 d = log(2.0);
00101
break;
00102
case Ln10:
00103 d = log(10.0);
00104
break;
00105
case Log2E:
00106 d = 1.0/log(2.0);
00107
break;
00108
case Log10E:
00109 d = 1.0/log(10.0);
00110
break;
00111
case Pi:
00112 d = M_PI;
00113
break;
00114
case Sqrt1_2:
00115 d = sqrt(0.5);
00116
break;
00117
case Sqrt2:
00118 d = sqrt(2.0);
00119
break;
00120
default:
00121 fprintf( stderr,
"Internal error in MathObjectImp: unhandled token %d\n", token );
00122
break;
00123 }
00124
00125
return Number(d);
00126 }
00127
00128
00129
00130 MathFuncImp::MathFuncImp(
ExecState *exec,
int i,
int l)
00131 :
InternalFunctionImp(
00132 static_cast<
FunctionPrototypeImp*>(exec->interpreter()->builtinFunctionPrototype().imp())
00133 ), id(i)
00134 {
00135
Value protect(
this);
00136 putDirect(lengthPropertyName, l, DontDelete|ReadOnly|DontEnum);
00137 }
00138
00139
bool MathFuncImp::implementsCall()
const
00140
{
00141
return true;
00142 }
00143
00144
Value MathFuncImp::call(
ExecState *exec,
Object &,
const List &args)
00145 {
00146
double arg = args[0].toNumber(exec);
00147
double arg2 = args[1].toNumber(exec);
00148
double result;
00149
00150
switch (
id) {
00151
case MathObjectImp::Abs:
00152 result = ( arg < 0 || arg == -0) ? (-arg) : arg;
00153
break;
00154
case MathObjectImp::ACos:
00155 result = ::acos(arg);
00156
break;
00157
case MathObjectImp::ASin:
00158 result = ::asin(arg);
00159
break;
00160
case MathObjectImp::ATan:
00161 result = ::atan(arg);
00162
break;
00163
case MathObjectImp::ATan2:
00164 result = ::atan2(arg, arg2);
00165
break;
00166
case MathObjectImp::Ceil:
00167 result = ::ceil(arg);
00168
break;
00169
case MathObjectImp::Cos:
00170 result = ::cos(arg);
00171
break;
00172
case MathObjectImp::Exp:
00173 result = ::exp(arg);
00174
break;
00175
case MathObjectImp::Floor:
00176 result = ::floor(arg);
00177
break;
00178
case MathObjectImp::Log:
00179 result = ::log(arg);
00180
break;
00181
case MathObjectImp::Max: {
00182
unsigned int argsCount = args.size();
00183 result = -Inf;
00184
for (
unsigned int k = 0 ; k < argsCount ; ++k ) {
00185
double val = args[k].toNumber(exec);
00186
if ( isNaN( val ) )
00187 {
00188 result = NaN;
00189
break;
00190 }
00191
if ( val > result )
00192 result = val;
00193 }
00194
break;
00195 }
00196
case MathObjectImp::Min: {
00197
unsigned int argsCount = args.size();
00198 result = +Inf;
00199
for (
unsigned int k = 0 ; k < argsCount ; ++k ) {
00200
double val = args[k].toNumber(exec);
00201
if ( isNaN( val ) )
00202 {
00203 result = NaN;
00204
break;
00205 }
00206
if ( val < result || (result == 0 && IS_NEGATIVE_ZERO(val)) )
00207 result = val;
00208 }
00209
break;
00210 }
00211
case MathObjectImp::Pow:
00212
00213
if (KJS::isNaN(arg2))
00214 result = NaN;
00215
else if (arg2 == 0)
00216 result = 1;
00217
else if (KJS::isNaN(arg) && arg2 != 0)
00218 result = NaN;
00219
else if (::fabs(arg) > 1 && KJS::isPosInf(arg2))
00220 result = Inf;
00221
else if (::fabs(arg) > 1 && KJS::isNegInf(arg2))
00222 result = +0;
00223
else if (::fabs(arg) == 1 && KJS::isPosInf(arg2))
00224 result = NaN;
00225
else if (::fabs(arg) == 1 && KJS::isNegInf(arg2))
00226 result = NaN;
00227
else if (::fabs(arg) < 1 && KJS::isPosInf(arg2))
00228 result = +0;
00229
else if (::fabs(arg) < 1 && KJS::isNegInf(arg2))
00230 result = Inf;
00231
else
00232 result = ::pow(arg, arg2);
00233
break;
00234
case MathObjectImp::Random:
00235 result = ::rand();
00236 result = result / RAND_MAX;
00237
break;
00238
case MathObjectImp::Round:
00239
if (isNaN(arg)) {
00240 result = arg;
00241 }
00242
else if (isInf(arg) || isInf(-arg)) {
00243 result = arg;
00244 }
00245
else if (arg == -0.5 || IS_NEGATIVE_ZERO(arg)) {
00246 result = -0.0;
00247 }
00248
else {
00249 result = (
double)(arg >= 0.0 ? int(arg + 0.5) : int(arg - 0.5));
00250
if (result == 0.0 && arg < 0.0)
00251 result = -0.0;
00252 }
00253
break;
00254
case MathObjectImp::Sin:
00255 result = ::sin(arg);
00256
break;
00257
case MathObjectImp::Sqrt:
00258 result = ::sqrt(arg);
00259
break;
00260
case MathObjectImp::Tan:
00261 result = ::tan(arg);
00262
break;
00263
00264
default:
00265 result = 0.0;
00266 assert(0);
00267 }
00268
00269
return Number(result);
00270 }