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 
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  /*  M_PI  */
00039 
00040 using namespace KJS;
00041 
00042 // ------------------------------ MathObjectImp --------------------------------
00043 
00044 const ClassInfo MathObjectImp::info = { "Math", 0, &mathTable, 0 };
00045 
00046 /* Source for math_object.lut.h
00047 @begin mathTable 31
00048   E             MathObjectImp::Euler    DontEnum|DontDelete|ReadOnly
00049   LN2           MathObjectImp::Ln2      DontEnum|DontDelete|ReadOnly
00050   LN10          MathObjectImp::Ln10     DontEnum|DontDelete|ReadOnly
00051   LOG2E         MathObjectImp::Log2E    DontEnum|DontDelete|ReadOnly
00052   LOG10E        MathObjectImp::Log10E   DontEnum|DontDelete|ReadOnly
00053   PI            MathObjectImp::Pi       DontEnum|DontDelete|ReadOnly
00054   SQRT1_2       MathObjectImp::Sqrt1_2  DontEnum|DontDelete|ReadOnly
00055   SQRT2         MathObjectImp::Sqrt2    DontEnum|DontDelete|ReadOnly
00056   abs           MathObjectImp::Abs      DontEnum|Function 1
00057   acos          MathObjectImp::ACos     DontEnum|Function 1
00058   asin          MathObjectImp::ASin     DontEnum|Function 1
00059   atan          MathObjectImp::ATan     DontEnum|Function 1
00060   atan2         MathObjectImp::ATan2    DontEnum|Function 2
00061   ceil          MathObjectImp::Ceil     DontEnum|Function 1
00062   cos           MathObjectImp::Cos      DontEnum|Function 1
00063   exp           MathObjectImp::Exp      DontEnum|Function 1
00064   floor         MathObjectImp::Floor    DontEnum|Function 1
00065   log           MathObjectImp::Log      DontEnum|Function 1
00066   max           MathObjectImp::Max      DontEnum|Function 2
00067   min           MathObjectImp::Min      DontEnum|Function 2
00068   pow           MathObjectImp::Pow      DontEnum|Function 2
00069   random        MathObjectImp::Random   DontEnum|Function 0
00070   round         MathObjectImp::Round    DontEnum|Function 1
00071   sin           MathObjectImp::Sin      DontEnum|Function 1
00072   sqrt          MathObjectImp::Sqrt     DontEnum|Function 1
00073   tan           MathObjectImp::Tan      DontEnum|Function 1
00074 @end
00075 */
00076 
00077 MathObjectImp::MathObjectImp(ExecState * /*exec*/,
00078                              ObjectPrototypeImp *objProto)
00079   : ObjectImp(objProto)
00080 {
00081 }
00082 
00083 // ECMA 15.8
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 // ------------------------------ MathObjectImp --------------------------------
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 &/*thisObj*/, 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     // ECMA 15.8.2.1.13 (::pow takes care of most of the critera)
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 }
KDE Logo
This file is part of the documentation for kjs Library Version 3.2.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Tue Feb 14 09:16:51 2006 by doxygen 1.3.6 written by Dimitri van Heesch, © 1997-2003