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 #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 }
This file is part of the documentation for kjs Library Version 3.3.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Thu Sep 23 17:12:07 2004 by
doxygen 1.3.8-20040913 written by
Dimitri van Heesch, © 1997-2003