math_object.cpp
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 (isNaN(arg)) {
00237 result = arg;
00238 }
00239 else if (isInf(arg) || isInf(-arg)) {
00240 result = arg;
00241 }
00242 else if (arg == -0.5 || IS_NEGATIVE_ZERO(arg)) {
00243 result = -0.0;
00244 }
00245 else {
00246 result = (double)(arg >= 0.0 ? int(arg + 0.5) : int(arg - 0.5));
00247 if (result == 0.0 && arg < 0.0)
00248 result = -0.0;
00249 }
00250 break;
00251 case MathObjectImp::Sin:
00252 result = ::sin(arg);
00253 break;
00254 case MathObjectImp::Sqrt:
00255 result = ::sqrt(arg);
00256 break;
00257 case MathObjectImp::Tan:
00258 result = ::tan(arg);
00259 break;
00260
00261 default:
00262 result = 0.0;
00263 assert(0);
00264 }
00265
00266 return Number(result);
00267 }
This file is part of the documentation for kjs Library Version 3.2.2.