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