kjs Library API Documentation

math_object.cpp

00001 // -*- c-basic-offset: 2 -*-
00002 /*
00003  *  This file is part of the KDE libraries
00004  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
00005  *
00006  *  This library is free software; you can redistribute it and/or
00007  *  modify it under the terms of the GNU Lesser General Public
00008  *  License as published by the Free Software Foundation; either
00009  *  version 2 of the License, or (at your option) any later version.
00010  *
00011  *  This library is distributed in the hope that it will be useful,
00012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  *  Lesser General Public License for more details.
00015  *
00016  *  You should have received a copy of the GNU Lesser General Public
00017  *  License along with this library; if not, write to the Free Software
00018  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
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  /*  M_PI  */
00040 
00041 using namespace KJS;
00042 
00043 // ------------------------------ MathObjectImp --------------------------------
00044 
00045 const ClassInfo MathObjectImp::info = { "Math", 0, &mathTable, 0 };
00046 
00047 /* Source for math_object.lut.h
00048 @begin mathTable 31
00049   E             MathObjectImp::Euler    DontEnum|DontDelete|ReadOnly
00050   LN2           MathObjectImp::Ln2      DontEnum|DontDelete|ReadOnly
00051   LN10          MathObjectImp::Ln10     DontEnum|DontDelete|ReadOnly
00052   LOG2E         MathObjectImp::Log2E    DontEnum|DontDelete|ReadOnly
00053   LOG10E        MathObjectImp::Log10E   DontEnum|DontDelete|ReadOnly
00054   PI            MathObjectImp::Pi       DontEnum|DontDelete|ReadOnly
00055   SQRT1_2       MathObjectImp::Sqrt1_2  DontEnum|DontDelete|ReadOnly
00056   SQRT2         MathObjectImp::Sqrt2    DontEnum|DontDelete|ReadOnly
00057   abs           MathObjectImp::Abs      DontEnum|Function 1
00058   acos          MathObjectImp::ACos     DontEnum|Function 1
00059   asin          MathObjectImp::ASin     DontEnum|Function 1
00060   atan          MathObjectImp::ATan     DontEnum|Function 1
00061   atan2         MathObjectImp::ATan2    DontEnum|Function 2
00062   ceil          MathObjectImp::Ceil     DontEnum|Function 1
00063   cos           MathObjectImp::Cos      DontEnum|Function 1
00064   exp           MathObjectImp::Exp      DontEnum|Function 1
00065   floor         MathObjectImp::Floor    DontEnum|Function 1
00066   log           MathObjectImp::Log      DontEnum|Function 1
00067   max           MathObjectImp::Max      DontEnum|Function 2
00068   min           MathObjectImp::Min      DontEnum|Function 2
00069   pow           MathObjectImp::Pow      DontEnum|Function 2
00070   random        MathObjectImp::Random   DontEnum|Function 0
00071   round         MathObjectImp::Round    DontEnum|Function 1
00072   sin           MathObjectImp::Sin      DontEnum|Function 1
00073   sqrt          MathObjectImp::Sqrt     DontEnum|Function 1
00074   tan           MathObjectImp::Tan      DontEnum|Function 1
00075 @end
00076 */
00077 
00078 MathObjectImp::MathObjectImp(ExecState * /*exec*/,
00079                              ObjectPrototypeImp *objProto)
00080   : ObjectImp(objProto)
00081 {
00082    unsigned int seed = time(NULL);
00083    ::srand(seed);
00084 }
00085 
00086 // ECMA 15.8
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 // ------------------------------ MathObjectImp --------------------------------
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 &/*thisObj*/, 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     // ECMA 15.8.2.1.13 (::pow takes care of most of the critera)
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 (arg < 0 && arg >= -0.5)
00240       result = -0.0;
00241     else if (IS_NEGATIVE_ZERO(arg))
00242       result = arg;
00243     else
00244       result = ::floor(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 }
KDE Logo
This file is part of the documentation for kjs Library Version 3.4.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Thu Jul 20 12:35:13 2006 by doxygen 1.4.4 written by Dimitri van Heesch, © 1997-2003