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