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