blob: 85c2cce553a759fe77841b36770b33ab7ef21ce6 [file] [log] [blame]
// -*- c-basic-offset: 2 -*-
/*
* This file is part of the KDE libraries
* Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#include "config.h"
#include "math_object.h"
#include "math_object.lut.h"
#include "wtf/MathExtras.h"
#include "operations.h"
#include <math.h>
#include <time.h>
using namespace KJS;
// ------------------------------ MathObjectImp --------------------------------
const ClassInfo MathObjectImp::info = { "Math", 0, &mathTable, 0 };
/* Source for math_object.lut.h
@begin mathTable 21
E MathObjectImp::Euler DontEnum|DontDelete|ReadOnly
LN2 MathObjectImp::Ln2 DontEnum|DontDelete|ReadOnly
LN10 MathObjectImp::Ln10 DontEnum|DontDelete|ReadOnly
LOG2E MathObjectImp::Log2E DontEnum|DontDelete|ReadOnly
LOG10E MathObjectImp::Log10E DontEnum|DontDelete|ReadOnly
PI MathObjectImp::Pi DontEnum|DontDelete|ReadOnly
SQRT1_2 MathObjectImp::Sqrt1_2 DontEnum|DontDelete|ReadOnly
SQRT2 MathObjectImp::Sqrt2 DontEnum|DontDelete|ReadOnly
abs MathObjectImp::Abs DontEnum|Function 1
acos MathObjectImp::ACos DontEnum|Function 1
asin MathObjectImp::ASin DontEnum|Function 1
atan MathObjectImp::ATan DontEnum|Function 1
atan2 MathObjectImp::ATan2 DontEnum|Function 2
ceil MathObjectImp::Ceil DontEnum|Function 1
cos MathObjectImp::Cos DontEnum|Function 1
exp MathObjectImp::Exp DontEnum|Function 1
floor MathObjectImp::Floor DontEnum|Function 1
log MathObjectImp::Log DontEnum|Function 1
max MathObjectImp::Max DontEnum|Function 2
min MathObjectImp::Min DontEnum|Function 2
pow MathObjectImp::Pow DontEnum|Function 2
random MathObjectImp::Random DontEnum|Function 0
round MathObjectImp::Round DontEnum|Function 1
sin MathObjectImp::Sin DontEnum|Function 1
sqrt MathObjectImp::Sqrt DontEnum|Function 1
tan MathObjectImp::Tan DontEnum|Function 1
@end
*/
MathObjectImp::MathObjectImp(ExecState * /*exec*/,
ObjectPrototype *objProto)
: JSObject(objProto)
{
}
// ECMA 15.8
bool MathObjectImp::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot &slot)
{
return getStaticPropertySlot<MathFuncImp, MathObjectImp, JSObject>(exec, &mathTable, this, propertyName, slot);
}
JSValue *MathObjectImp::getValueProperty(ExecState *, int token) const
{
double d = -42; // ;)
switch (token) {
case Euler:
d = exp(1.0);
break;
case Ln2:
d = log(2.0);
break;
case Ln10:
d = log(10.0);
break;
case Log2E:
d = 1.0/log(2.0);
break;
case Log10E:
d = 1.0/log(10.0);
break;
case Pi:
d = piDouble;
break;
case Sqrt1_2:
d = sqrt(0.5);
break;
case Sqrt2:
d = sqrt(2.0);
break;
default:
assert(0);
}
return jsNumber(d);
}
// ------------------------------ MathObjectImp --------------------------------
static bool didInitRandom;
MathFuncImp::MathFuncImp(ExecState* exec, int i, int l, const Identifier& name)
: InternalFunctionImp(static_cast<FunctionPrototype*>(exec->lexicalInterpreter()->builtinFunctionPrototype()), name)
, id(i)
{
putDirect(exec->propertyNames().length, l, DontDelete|ReadOnly|DontEnum);
}
JSValue *MathFuncImp::callAsFunction(ExecState *exec, JSObject* /*thisObj*/, const List &args)
{
double arg = args[0]->toNumber(exec);
double arg2 = args[1]->toNumber(exec);
double result;
switch (id) {
case MathObjectImp::Abs:
result = ( arg < 0 || arg == -0) ? (-arg) : arg;
break;
case MathObjectImp::ACos:
result = acos(arg);
break;
case MathObjectImp::ASin:
result = asin(arg);
break;
case MathObjectImp::ATan:
result = atan(arg);
break;
case MathObjectImp::ATan2:
result = atan2(arg, arg2);
break;
case MathObjectImp::Ceil:
result = ceil(arg);
break;
case MathObjectImp::Cos:
result = cos(arg);
break;
case MathObjectImp::Exp:
result = exp(arg);
break;
case MathObjectImp::Floor:
result = floor(arg);
break;
case MathObjectImp::Log:
result = log(arg);
break;
case MathObjectImp::Max: {
unsigned int argsCount = args.size();
result = -Inf;
for ( unsigned int k = 0 ; k < argsCount ; ++k ) {
double val = args[k]->toNumber(exec);
if ( isNaN( val ) )
{
result = NaN;
break;
}
if ( val > result || (val == 0 && result == 0 && !signbit(val)) )
result = val;
}
break;
}
case MathObjectImp::Min: {
unsigned int argsCount = args.size();
result = +Inf;
for ( unsigned int k = 0 ; k < argsCount ; ++k ) {
double val = args[k]->toNumber(exec);
if ( isNaN( val ) )
{
result = NaN;
break;
}
if ( val < result || (val == 0 && result == 0 && signbit(val)) )
result = val;
}
break;
}
case MathObjectImp::Pow:
// ECMA 15.8.2.1.13 (::pow takes care of most of the critera)
if (isNaN(arg2))
result = NaN;
else if (isNaN(arg) && arg2 != 0)
result = NaN;
else if (fabs(arg) == 1 && isInf(arg2))
result = NaN;
else if (arg2 == 0 && arg != 0)
result = 1;
else
result = ::pow(arg, arg2);
break;
case MathObjectImp::Random:
if (!didInitRandom) {
wtf_random_init();
didInitRandom = true;
}
result = wtf_random();
break;
case MathObjectImp::Round:
if (signbit(arg) && arg >= -0.5)
result = -0.0;
else
result = floor(arg + 0.5);
break;
case MathObjectImp::Sin:
result = sin(arg);
break;
case MathObjectImp::Sqrt:
result = sqrt(arg);
break;
case MathObjectImp::Tan:
result = tan(arg);
break;
default:
result = 0.0;
assert(0);
}
return jsNumber(result);
}