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.0.