blob: 93f14580cf6f4421d0d0255bb7867e46a461f61d [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "XalanEXSLTMath.hpp"
#include "XalanEXSLTMathImpl.hpp"
#include <cmath>
#include <ctime>
#include <xalanc/PlatformSupport/DoubleSupport.hpp>
#include <xalanc/PlatformSupport/XalanMessageLoader.hpp>
#include <xalanc/PlatformSupport/XalanUnicode.hpp>
#include <xalanc/DOMSupport/DOMServices.hpp>
#include <xalanc/XPath/XObjectFactory.hpp>
#include <xalanc/XPath/XPathEnvSupportDefault.hpp>
XALAN_CPP_NAMESPACE_BEGIN
template<class FunctionType>
XObjectPtr
findNodes(
XPathExecutionContext& executionContext,
const NodeRefListBase& theNodeSet,
FunctionType theCompareFunction)
{
const NodeRefListBase::size_type theLength = theNodeSet.getLength();
XPathExecutionContext::BorrowReturnMutableNodeRefList theNodes(executionContext);
theNodes->setDocumentOrder();
if (theLength != 0)
{
const XPathExecutionContext::GetCachedString theGuard(executionContext);
XalanDOMString& theStringValue = theGuard.get();
XalanNode* theCurrentNode = theNodeSet.item(0);
assert(theCurrentNode != 0);
DOMServices::getNodeData(*theCurrentNode, executionContext, theStringValue);
double theNumericValue = DOMStringToDouble(theStringValue, executionContext.getMemoryManager());
if (DoubleSupport::isNaN(theNumericValue) == false)
{
theNodes->addNode(theCurrentNode);
for (NodeRefListBase::size_type i = 1; i < theLength; ++i)
{
theCurrentNode = theNodeSet.item(i);
assert(theCurrentNode != 0);
theStringValue.clear();
DOMServices::getNodeData(*theCurrentNode, executionContext, theStringValue);
const double theCurrent = DOMStringToDouble(theStringValue, executionContext.getMemoryManager());
if (DoubleSupport::isNaN(theCurrent) == true)
{
theNodes->clear();
break;
}
else if (DoubleSupport::equal(theCurrent, theNumericValue) == true)
{
theNodes->addNodeInDocOrder(theCurrentNode, executionContext);
}
else if (theCompareFunction(theCurrent, theNumericValue) == true)
{
theNodes->clear();
theNodes->addNode(theCurrentNode);
theNumericValue = theCurrent;
}
}
}
}
return executionContext.getXObjectFactory().createNodeSet(theNodes);
}
static const XalanDOMChar s_highestFunctionName[] =
{
XalanUnicode::charLetter_h,
XalanUnicode::charLetter_i,
XalanUnicode::charLetter_g,
XalanUnicode::charLetter_h,
XalanUnicode::charLetter_e,
XalanUnicode::charLetter_s,
XalanUnicode::charLetter_t,
0
};
XObjectPtr
XalanEXSLTFunctionHighest::execute(
XPathExecutionContext& executionContext,
XalanNode* context,
const XObjectArgVectorType& args,
const Locator* locator) const
{
if (args.size() != 1)
{
generalError(
executionContext,
context,
locator);
}
assert(args[0].null() == false);
return findNodes(
executionContext,
args[0]->nodeset(),
DoubleSupport::greaterThan);
}
const XalanDOMString&
XalanEXSLTFunctionHighest::getError(XalanDOMString& theBuffer) const
{
return XalanMessageLoader::getMessage(
theBuffer,
XalanMessages::EXSLTFunctionAcceptsOneArgument_1Param,
s_highestFunctionName);
}
static const XalanDOMChar s_lowestFunctionName[] =
{
XalanUnicode::charLetter_l,
XalanUnicode::charLetter_o,
XalanUnicode::charLetter_w,
XalanUnicode::charLetter_e,
XalanUnicode::charLetter_s,
XalanUnicode::charLetter_t,
0
};
XObjectPtr
XalanEXSLTFunctionLowest::execute(
XPathExecutionContext& executionContext,
XalanNode* context,
const XObjectArgVectorType& args,
const Locator* locator) const
{
if (args.size() != 1)
{
generalError(
executionContext,
context,
locator);
}
assert(args[0].null() == false);
return findNodes(
executionContext,
args[0]->nodeset(),
DoubleSupport::lessThan);
}
const XalanDOMString&
XalanEXSLTFunctionLowest::getError(XalanDOMString& theBuffer) const
{
return XalanMessageLoader::getMessage(
theBuffer,
XalanMessages::EXSLTFunctionAcceptsOneArgument_1Param,
s_lowestFunctionName);
}
template<class FunctionType>
XObjectPtr
findValue(
XPathExecutionContext& executionContext,
const NodeRefListBase& theNodeSet,
FunctionType theCompareFunction)
{
const NodeRefListBase::size_type theLength = theNodeSet.getLength();
if (theLength == 0)
{
return executionContext.getXObjectFactory().createNumber(DoubleSupport::getNaN());
}
else
{
const XPathExecutionContext::GetCachedString theGuard(executionContext);
XalanDOMString& theStringValue = theGuard.get();
assert(theNodeSet.item(0) != 0);
DOMServices::getNodeData(*theNodeSet.item(0), executionContext, theStringValue);
double theResult = DOMStringToDouble(theStringValue, executionContext.getMemoryManager());
for (NodeRefListBase::size_type i = 1; i < theLength; ++i)
{
assert(theNodeSet.item(i) != 0);
theStringValue.clear();
DOMServices::getNodeData(*theNodeSet.item(i), executionContext, theStringValue);
const double theCurrent =
DOMStringToDouble(
theStringValue,
executionContext.getMemoryManager());
if (DoubleSupport::isNaN(theCurrent) == true)
{
theResult = theCurrent;
break;
}
else if (theCompareFunction(theCurrent, theResult) == true)
{
theResult = theCurrent;
}
}
return executionContext.getXObjectFactory().createNumber(theResult);
}
}
static const XalanDOMChar s_minFunctionName[] =
{
XalanUnicode::charLetter_m,
XalanUnicode::charLetter_i,
XalanUnicode::charLetter_n,
0
};
XObjectPtr
XalanEXSLTFunctionMin::execute(
XPathExecutionContext& executionContext,
XalanNode* context,
const XObjectArgVectorType& args,
const Locator* locator) const
{
if (args.size() != 1)
{
generalError(
executionContext,
context,
locator);
}
assert(args[0].null() == false);
return findValue(
executionContext,
args[0]->nodeset(),
DoubleSupport::lessThan);
}
const XalanDOMString&
XalanEXSLTFunctionMin::getError(XalanDOMString& theBuffer) const
{
return XalanMessageLoader::getMessage(
theBuffer,
XalanMessages::EXSLTFunctionAcceptsOneArgument_1Param,
s_minFunctionName);
}
static const XalanDOMChar s_maxFunctionName[] =
{
XalanUnicode::charLetter_m,
XalanUnicode::charLetter_a,
XalanUnicode::charLetter_x,
0
};
XObjectPtr
XalanEXSLTFunctionMax::execute(
XPathExecutionContext& executionContext,
XalanNode* context,
const XObjectArgVectorType& args,
const Locator* locator) const
{
if (args.size() != 1)
{
generalError(
executionContext,
context,
locator);
}
assert(args[0].null() == false);
return findValue(
executionContext,
args[0]->nodeset(),
DoubleSupport::greaterThan);
}
const XalanDOMString&
XalanEXSLTFunctionMax::getError(XalanDOMString& theBuffer) const
{
return XalanMessageLoader::getMessage(
theBuffer,
XalanMessages::EXSLTFunctionAcceptsOneArgument_1Param,
s_maxFunctionName);
}
static const XalanDOMChar s_absFunctionName[] =
{
XalanUnicode::charLetter_a,
XalanUnicode::charLetter_b,
XalanUnicode::charLetter_s,
0
};
XObjectPtr
XalanEXSLTFunctionAbs::execute(
XPathExecutionContext& executionContext,
XalanNode* context,
const XObjectArgVectorType& args,
const Locator* locator) const
{
if (args.size() != 1)
{
generalError(
executionContext,
context,
locator);
}
assert(args[0].null() == false);
return executionContext.getXObjectFactory().createNumber(DoubleSupport::abs(args[0]->num(executionContext)));
}
const XalanDOMString&
XalanEXSLTFunctionAbs::getError(XalanDOMString& theBuffer) const
{
return XalanMessageLoader::getMessage(
theBuffer,
XalanMessages::EXSLTFunctionAcceptsOneArgument_1Param,
s_absFunctionName);
}
static const XalanDOMChar s_randomFunctionName[] =
{
XalanUnicode::charLetter_r,
XalanUnicode::charLetter_a,
XalanUnicode::charLetter_n,
XalanUnicode::charLetter_d,
XalanUnicode::charLetter_o,
XalanUnicode::charLetter_m,
0
};
XObjectPtr
XalanEXSLTFunctionRandom::execute(
XPathExecutionContext& executionContext,
XalanNode* context,
const XObjectArgVectorType& args,
const Locator* locator) const
{
if (args.empty() == false)
{
generalError(
executionContext,
context,
locator);
}
#if defined(XALAN_STRICT_ANSI_HEADERS)
using std::rand;
#endif
const int value = rand();
double result = 0.0;
if (value != 0)
{
result = double(value) / RAND_MAX;
}
assert(result >= 0.0L && result <= 1.0L);
return executionContext.getXObjectFactory().createNumber(result);
}
const XalanDOMString&
XalanEXSLTFunctionRandom::getError(XalanDOMString& theBuffer) const
{
return XalanMessageLoader::getMessage(
theBuffer,
XalanMessages::EXSLTFunctionAcceptsNoArgument_1Param,
s_randomFunctionName);
}
static const XalanDOMChar s_acosFunctionName[] =
{
XalanUnicode::charLetter_a,
XalanUnicode::charLetter_c,
XalanUnicode::charLetter_o,
XalanUnicode::charLetter_s,
0
};
XObjectPtr
XalanEXSLTFunctionAcos::execute(
XPathExecutionContext& executionContext,
XalanNode* context,
const XObjectArgVectorType& args,
const Locator* locator) const
{
if (args.size() != 1)
{
generalError(
executionContext,
context,
locator);
}
assert(args[0].null() == false);
#if defined(XALAN_STRICT_ANSI_HEADERS)
using std::acos;
#endif
return executionContext.getXObjectFactory().createNumber(acos(args[0]->num(executionContext)));
}
const XalanDOMString&
XalanEXSLTFunctionAcos::getError(XalanDOMString& theBuffer) const
{
return XalanMessageLoader::getMessage(
theBuffer,
XalanMessages::EXSLTFunctionAcceptsOneArgument_1Param,
s_acosFunctionName);
}
static const XalanDOMChar s_asinFunctionName[] =
{
XalanUnicode::charLetter_a,
XalanUnicode::charLetter_s,
XalanUnicode::charLetter_i,
XalanUnicode::charLetter_n,
0
};
XObjectPtr
XalanEXSLTFunctionAsin::execute(
XPathExecutionContext& executionContext,
XalanNode* context,
const XObjectArgVectorType& args,
const Locator* locator) const
{
if (args.size() != 1)
{
generalError(
executionContext,
context,
locator);
}
assert(args[0].null() == false);
#if defined(XALAN_STRICT_ANSI_HEADERS)
using std::asin;
#endif
return executionContext.getXObjectFactory().createNumber(asin(args[0]->num(executionContext)));
}
const XalanDOMString&
XalanEXSLTFunctionAsin::getError(XalanDOMString& theBuffer) const
{
return XalanMessageLoader::getMessage(
theBuffer,
XalanMessages::EXSLTFunctionAcceptsOneArgument_1Param,
s_asinFunctionName);
}
static const XalanDOMChar s_atanFunctionName[] =
{
XalanUnicode::charLetter_a,
XalanUnicode::charLetter_t,
XalanUnicode::charLetter_a,
XalanUnicode::charLetter_n,
0
};
XObjectPtr
XalanEXSLTFunctionAtan::execute(
XPathExecutionContext& executionContext,
XalanNode* context,
const XObjectArgVectorType& args,
const Locator* locator) const
{
if (args.size() != 1)
{
generalError(
executionContext,
context,
locator);
}
assert(args[0].null() == false);
#if defined(XALAN_STRICT_ANSI_HEADERS)
using std::atan;
#endif
return executionContext.getXObjectFactory().createNumber(atan(args[0]->num(executionContext)));
}
const XalanDOMString&
XalanEXSLTFunctionAtan::getError(XalanDOMString& theBuffer) const
{
return XalanMessageLoader::getMessage(
theBuffer,
XalanMessages::EXSLTFunctionAcceptsOneArgument_1Param,
s_atanFunctionName);
}
static const XalanDOMChar s_atan2FunctionName[] =
{
XalanUnicode::charLetter_a,
XalanUnicode::charLetter_t,
XalanUnicode::charLetter_a,
XalanUnicode::charLetter_n,
XalanUnicode::charDigit_2,
0
};
XObjectPtr
XalanEXSLTFunctionAtan2::execute(
XPathExecutionContext& executionContext,
XalanNode* context,
const XObjectArgVectorType& args,
const Locator* locator) const
{
if (args.size() != 2)
{
generalError(
executionContext,
context,
locator);
}
assert(args[0].null() == false && args[1].null() == false);
#if defined(XALAN_STRICT_ANSI_HEADERS)
using std::atan2;
#endif
return executionContext.getXObjectFactory().createNumber(
atan2(args[0]->num(executionContext), args[1]->num(executionContext)));
}
const XalanDOMString&
XalanEXSLTFunctionAtan2::getError(XalanDOMString& theBuffer) const
{
return XalanMessageLoader::getMessage(
theBuffer,
XalanMessages::EXSLTFunctionAcceptsTwoArguments_1Param,
s_atan2FunctionName);
}
const XalanDOMChar XalanEXSLTFunctionConstant::s_eString[] =
{
XalanUnicode::charLetter_E,
0
};
const XalanDOMChar XalanEXSLTFunctionConstant::s_ln10String[] =
{
XalanUnicode::charLetter_L,
XalanUnicode::charLetter_N,
XalanUnicode::charDigit_1,
XalanUnicode::charDigit_0,
0
};
const XalanDOMChar XalanEXSLTFunctionConstant::s_ln2String[] =
{
XalanUnicode::charLetter_L,
XalanUnicode::charLetter_N,
XalanUnicode::charDigit_2,
0
};
const XalanDOMChar XalanEXSLTFunctionConstant::s_log2EString[] =
{
XalanUnicode::charLetter_L,
XalanUnicode::charLetter_O,
XalanUnicode::charLetter_G,
XalanUnicode::charDigit_2,
XalanUnicode::charLetter_E,
0
};
const XalanDOMChar XalanEXSLTFunctionConstant::s_piString[] =
{
XalanUnicode::charLetter_P,
XalanUnicode::charLetter_I,
0
};
const XalanDOMChar XalanEXSLTFunctionConstant::s_sqrt1_2String[] =
{
XalanUnicode::charLetter_S,
XalanUnicode::charLetter_Q,
XalanUnicode::charLetter_R,
XalanUnicode::charLetter_T,
XalanUnicode::charDigit_1,
XalanUnicode::charLowLine,
XalanUnicode::charDigit_2,
0
};
const XalanDOMChar XalanEXSLTFunctionConstant::s_sqrt2String[] =
{
XalanUnicode::charLetter_S,
XalanUnicode::charLetter_Q,
XalanUnicode::charLetter_R,
XalanUnicode::charLetter_R,
XalanUnicode::charLetter_T,
XalanUnicode::charDigit_2,
0
};
const double XalanEXSLTFunctionConstant::s_eValues[] =
{
0.0L,
2.7L,
2.71L,
2.718L,
2.7182L,
2.71828L,
2.718281L,
2.7182818L,
2.71828182L,
2.718281828L,
2.7182818284L,
2.71828182845L,
2.718281828459L,
2.7182818284590L,
2.71828182845904L,
2.718281828459045L,
2.7182818284590452L,
2.71828182845904523L,
2.718281828459045235L,
2.7182818284590452353L,
2.71828182845904523536L,
2.718281828459045235360L,
2.7182818284590452353602L,
2.71828182845904523536028L,
2.718281828459045235360287L,
2.7182818284590452353602874L,
2.71828182845904523536028747L,
2.718281828459045235360287471L,
2.7182818284590452353602874713L,
2.71828182845904523536028747135L,
2.718281828459045235360287471352L,
2.7182818284590452353602874713526L,
2.71828182845904523536028747135266L,
2.718281828459045235360287471352662L,
2.7182818284590452353602874713526624L,
2.71828182845904523536028747135266249L,
2.718281828459045235360287471352662497L,
2.7182818284590452353602874713526624977L,
2.71828182845904523536028747135266249775L,
2.718281828459045235360287471352662497757L,
2.7182818284590452353602874713526624977572L,
2.71828182845904523536028747135266249775724L,
2.718281828459045235360287471352662497757247L,
2.7182818284590452353602874713526624977572470L,
2.71828182845904523536028747135266249775724709L,
2.718281828459045235360287471352662497757247093L,
2.7182818284590452353602874713526624977572470936L,
2.71828182845904523536028747135266249775724709369L,
2.718281828459045235360287471352662497757247093699L,
2.7182818284590452353602874713526624977572470936999L,
2.71828182845904523536028747135266249775724709369996L,
};
const double XalanEXSLTFunctionConstant::s_ln10Values[] =
{
0.0L,
2.3L,
2.30L,
2.302L,
2.3025L,
2.30258L,
2.302585L,
2.3025850L,
2.30258509L,
2.302585092L,
2.3025850929L,
2.30258509299L,
2.302585092994L,
2.3025850929940L,
2.30258509299404L,
2.302585092994046L
};
const double XalanEXSLTFunctionConstant::s_ln2Values[] =
{
0.0L,
0.6L,
0.69L,
0.693L,
0.6931L,
0.69314L,
0.693147L,
0.6931471L,
0.69314718L,
0.693147180L,
0.6931471805L,
0.69314718055L,
0.693147180559L,
0.6931471805599L,
0.69314718055994L,
0.693147180559945L,
0.6931471805599453L,
0.69314718055994530L,
0.693147180559945309L,
0.6931471805599453094L,
0.69314718055994530941L,
0.693147180559945309417L,
0.6931471805599453094172L,
0.69314718055994530941723L,
0.693147180559945309417232L,
0.6931471805599453094172321L,
0.69314718055994530941723212L,
0.693147180559945309417232121L,
0.6931471805599453094172321214L,
0.69314718055994530941723212145L,
0.693147180559945309417232121458L,
0.6931471805599453094172321214581L,
0.69314718055994530941723212145817L,
0.693147180559945309417232121458176L,
0.6931471805599453094172321214581765L,
0.69314718055994530941723212145817656L,
0.693147180559945309417232121458176568L,
0.6931471805599453094172321214581765680L,
0.69314718055994530941723212145817656807L,
0.693147180559945309417232121458176568075L,
0.6931471805599453094172321214581765680755L,
0.69314718055994530941723212145817656807550L,
0.693147180559945309417232121458176568075500L,
0.6931471805599453094172321214581765680755001L,
0.69314718055994530941723212145817656807550013L,
0.693147180559945309417232121458176568075500134L,
0.6931471805599453094172321214581765680755001343L,
0.69314718055994530941723212145817656807550013436L,
0.693147180559945309417232121458176568075500134360L,
0.6931471805599453094172321214581765680755001343602L,
0.69314718055994530941723212145817656807550013436025L
};
const double XalanEXSLTFunctionConstant::s_log2EValues[] =
{
0.0L,
1.4L,
1.44L,
1.442L,
1.4426L,
1.44269L,
1.442695L,
1.4426950L,
1.44269504L,
1.442695040L,
1.4426950408L,
1.44269504088L,
1.442695040888L,
1.4426950408889L,
1.44269504088896L,
1.442695040888963L,
1.4426950408889633L
};
const double XalanEXSLTFunctionConstant::s_piValues[] =
{
0.0L,
3.1L,
3.14L,
3.141L,
3.1415L,
3.14159L,
3.141592L,
3.1415926L,
3.14159265L,
3.141592653L,
3.1415926535L,
3.14159265358L,
3.141592653589L,
3.1415926535897L,
3.14159265358979L,
3.141592653589793L,
3.1415926535897932L,
3.14159265358979323L,
3.141592653589793238L,
3.1415926535897932384L,
3.14159265358979323846L,
3.141592653589793238462L,
3.1415926535897932384626L,
3.14159265358979323846264L,
3.141592653589793238462643L,
3.1415926535897932384626433L,
3.14159265358979323846264338L,
3.141592653589793238462643383L,
3.1415926535897932384626433832L,
3.14159265358979323846264338327L,
3.141592653589793238462643383279L,
3.1415926535897932384626433832795L,
3.14159265358979323846264338327950L,
3.141592653589793238462643383279502L,
3.1415926535897932384626433832795028L,
3.14159265358979323846264338327950288L,
3.141592653589793238462643383279502884L,
3.1415926535897932384626433832795028841L,
3.14159265358979323846264338327950288419L,
3.141592653589793238462643383279502884197L,
3.1415926535897932384626433832795028841971L,
3.14159265358979323846264338327950288419716L,
3.141592653589793238462643383279502884197169L,
3.1415926535897932384626433832795028841971693L,
3.14159265358979323846264338327950288419716939L,
3.141592653589793238462643383279502884197169399L,
3.1415926535897932384626433832795028841971693993L,
3.14159265358979323846264338327950288419716939937L,
3.141592653589793238462643383279502884197169399375L,
3.1415926535897932384626433832795028841971693993751L
};
const double XalanEXSLTFunctionConstant::s_sqrt1_2Values[] =
{
0.0L,
0.7L,
0.70L,
0.707L,
0.7071L,
0.70710L,
0.707106L,
0.7071067L,
0.70710678L,
0.707106781L,
0.7071067811L,
0.70710678118L,
0.707106781186L,
0.7071067811865L,
0.70710678118654L,
0.707106781186547L,
0.7071067811865476L
};
const double XalanEXSLTFunctionConstant::s_sqrt2Values[] =
{
0.0L,
1.4L,
1.41L,
1.414L,
1.4142L,
1.41421L,
1.414213L,
1.4142135L,
1.41421356L,
1.414213562L,
1.4142135623L,
1.41421356237L,
1.414213562373L,
1.4142135623730L,
1.41421356237309L,
1.414213562373095L,
1.4142135623730950L,
1.41421356237309504L,
1.414213562373095048L,
1.4142135623730950488L,
1.41421356237309504880L,
1.414213562373095048801L,
1.4142135623730950488016L,
1.41421356237309504880168L,
1.414213562373095048801688L,
1.4142135623730950488016887L,
1.41421356237309504880168872L,
1.414213562373095048801688724L,
1.4142135623730950488016887242L,
1.41421356237309504880168872420L,
1.414213562373095048801688724209L,
1.4142135623730950488016887242096L,
1.41421356237309504880168872420969L,
1.414213562373095048801688724209698L,
1.4142135623730950488016887242096980L,
1.41421356237309504880168872420969807L,
1.414213562373095048801688724209698078L,
1.4142135623730950488016887242096980785L,
1.41421356237309504880168872420969807856L,
1.414213562373095048801688724209698078569L,
1.4142135623730950488016887242096980785696L,
1.41421356237309504880168872420969807856967L,
1.414213562373095048801688724209698078569671L,
1.4142135623730950488016887242096980785696718L,
1.41421356237309504880168872420969807856967187L,
1.414213562373095048801688724209698078569671875L,
1.4142135623730950488016887242096980785696718753L,
1.41421356237309504880168872420969807856967187537L,
1.414213562373095048801688724209698078569671875376L,
1.4142135623730950488016887242096980785696718753769L,
1.41421356237309504880168872420969807856967187537694L
};
XObjectPtr
doConvert(
XPathExecutionContext& executionContext,
const double theValues[],
size_t theSize,
double thePrecision)
{
return executionContext.getXObjectFactory().createNumber(
theValues[XalanDOMString::size_type(thePrecision <= theSize ? thePrecision : theSize)]);
}
XObjectPtr
XalanEXSLTFunctionConstant::execute(
XPathExecutionContext& executionContext,
XalanNode* context,
const XObjectArgVectorType& args,
const Locator* locator) const
{
if (args.size() != 2)
{
generalError(
executionContext,
context,
locator);
}
assert(args[0].null() == false && args[1].null() == false);
const XalanDOMString& theConstant = args[0]->str(executionContext);
const double thePrecision = DoubleSupport::round(args[1]->num(executionContext));
if (thePrecision <= 0.0L)
{
return executionContext.getXObjectFactory().createNumber(DoubleSupport::getNaN());
}
else if (equals(s_eString, theConstant) == true)
{
return doConvert(
executionContext,
s_eValues,
sizeof(s_eValues) / sizeof(s_eValues[0]),
thePrecision);
}
else if (equals(s_ln10String, theConstant) == true)
{
return doConvert(
executionContext,
s_ln10Values,
sizeof(s_ln10Values) / sizeof(s_ln10Values[0]),
thePrecision);
}
else if (equals(s_ln2String, theConstant) == true)
{
return doConvert(
executionContext,
s_ln2Values,
sizeof(s_ln2Values) / sizeof(s_ln2Values[0]),
thePrecision);
}
else if (equals(s_log2EString, theConstant) == true)
{
return doConvert(
executionContext,
s_log2EValues,
sizeof(s_log2EValues) / sizeof(s_log2EValues[0]),
thePrecision);
}
else if (equals(s_piString, theConstant) == true)
{
return doConvert(
executionContext,
s_piValues,
sizeof(s_piValues) / sizeof(s_piValues[0]),
thePrecision);
}
else if (equals(s_sqrt1_2String, theConstant) == true)
{
return doConvert(
executionContext,
s_sqrt1_2Values,
sizeof(s_sqrt1_2Values) / sizeof(s_sqrt1_2Values[0]),
thePrecision);
}
else if (equals(s_sqrt2String, theConstant) == true)
{
return doConvert(
executionContext,
s_sqrt2Values,
sizeof(s_sqrt2Values) / sizeof(s_sqrt2Values[0]),
thePrecision);
}
else
{
return executionContext.getXObjectFactory().createNumber(DoubleSupport::getNaN());
}
}
static const XalanDOMChar s_cosFunctionName[] =
{
XalanUnicode::charLetter_c,
XalanUnicode::charLetter_o,
XalanUnicode::charLetter_s,
0
};
XObjectPtr
XalanEXSLTFunctionCos::execute(
XPathExecutionContext& executionContext,
XalanNode* context,
const XObjectArgVectorType& args,
const Locator* locator) const
{
if (args.size() != 1)
{
generalError(
executionContext,
context,
locator);
}
assert(args[0].null() == false);
#if defined(XALAN_STRICT_ANSI_HEADERS)
using std::cos;
#endif
return executionContext.getXObjectFactory().createNumber(cos(args[0]->num(executionContext)));
}
const XalanDOMString&
XalanEXSLTFunctionCos::getError(XalanDOMString& theBuffer) const
{
return XalanMessageLoader::getMessage(
theBuffer,
XalanMessages::EXSLTFunctionAcceptsOneArgument_1Param,
s_cosFunctionName);
}
static const XalanDOMChar s_expFunctionName[] =
{
XalanUnicode::charLetter_e,
XalanUnicode::charLetter_x,
XalanUnicode::charLetter_p,
0
};
XObjectPtr
XalanEXSLTFunctionExp::execute(
XPathExecutionContext& executionContext,
XalanNode* context,
const XObjectArgVectorType& args,
const Locator* locator) const
{
if (args.size() != 1)
{
generalError(
executionContext,
context,
locator);
}
assert(args[0].null() == false);
#if defined(XALAN_STRICT_ANSI_HEADERS)
using std::exp;
#endif
return executionContext.getXObjectFactory().createNumber(exp(args[0]->num(executionContext)));
}
const XalanDOMString&
XalanEXSLTFunctionExp::getError(XalanDOMString& theBuffer) const
{
return XalanMessageLoader::getMessage(
theBuffer,
XalanMessages::EXSLTFunctionAcceptsOneArgument_1Param,
s_expFunctionName);
}
static const XalanDOMChar s_logFunctionName[] =
{
XalanUnicode::charLetter_l,
XalanUnicode::charLetter_o,
XalanUnicode::charLetter_g,
0
};
XObjectPtr
XalanEXSLTFunctionLog::execute(
XPathExecutionContext& executionContext,
XalanNode* context,
const XObjectArgVectorType& args,
const Locator* locator) const
{
if (args.size() != 1)
{
generalError(
executionContext,
context,
locator);
}
assert(args[0].null() == false);
#if defined(XALAN_STRICT_ANSI_HEADERS)
using std::log;
#endif
return executionContext.getXObjectFactory().createNumber(log(args[0]->num(executionContext)));
}
const XalanDOMString&
XalanEXSLTFunctionLog::getError(XalanDOMString& theBuffer) const
{
return XalanMessageLoader::getMessage(
theBuffer,
XalanMessages::EXSLTFunctionAcceptsOneArgument_1Param,
s_logFunctionName);
}
static const XalanDOMChar s_powerFunctionName[] =
{
XalanUnicode::charLetter_p,
XalanUnicode::charLetter_o,
XalanUnicode::charLetter_w,
XalanUnicode::charLetter_e,
XalanUnicode::charLetter_r,
0
};
XObjectPtr
XalanEXSLTFunctionPower::execute(
XPathExecutionContext& executionContext,
XalanNode* context,
const XObjectArgVectorType& args,
const Locator* locator) const
{
if (args.size() != 2)
{
generalError(
executionContext,
context,
locator);
}
assert(args[0].null() == false && args[1].null() == false);
#if defined(XALAN_STRICT_ANSI_HEADERS)
using std::pow;
#endif
return executionContext.getXObjectFactory().createNumber(
pow(
args[0]->num(executionContext),
args[1]->num(executionContext)));
}
const XalanDOMString&
XalanEXSLTFunctionPower::getError(XalanDOMString& theBuffer) const
{
return XalanMessageLoader::getMessage(
theBuffer,
XalanMessages::EXSLTFunctionAcceptsTwoArguments_1Param,
s_powerFunctionName);
}
static const XalanDOMChar s_sinFunctionName[] =
{
XalanUnicode::charLetter_s,
XalanUnicode::charLetter_i,
XalanUnicode::charLetter_n,
0
};
XObjectPtr
XalanEXSLTFunctionSin::execute(
XPathExecutionContext& executionContext,
XalanNode* context,
const XObjectArgVectorType& args,
const Locator* locator) const
{
if (args.size() != 1)
{
generalError(
executionContext,
context,
locator);
}
assert(args[0].null() == false);
#if defined(XALAN_STRICT_ANSI_HEADERS)
using std::sin;
#endif
return executionContext.getXObjectFactory().createNumber(sin(args[0]->num(executionContext)));
}
const XalanDOMString&
XalanEXSLTFunctionSin::getError(XalanDOMString& theBuffer) const
{
return XalanMessageLoader::getMessage(
theBuffer,
XalanMessages::EXSLTFunctionAcceptsOneArgument_1Param,
s_sinFunctionName);
}
static const XalanDOMChar s_sqrtFunctionName[] =
{
XalanUnicode::charLetter_s,
XalanUnicode::charLetter_q,
XalanUnicode::charLetter_r,
XalanUnicode::charLetter_t,
0
};
XObjectPtr
XalanEXSLTFunctionSqrt::execute(
XPathExecutionContext& executionContext,
XalanNode* context,
const XObjectArgVectorType& args,
const Locator* locator) const
{
if (args.size() != 1)
{
generalError(
executionContext,
context,
locator);
}
assert(args[0].null() == false);
#if defined(XALAN_STRICT_ANSI_HEADERS)
using std::sqrt;
#endif
return executionContext.getXObjectFactory().createNumber(sqrt(args[0]->num(executionContext)));
}
const XalanDOMString&
XalanEXSLTFunctionSqrt::getError(XalanDOMString& theBuffer) const
{
return XalanMessageLoader::getMessage(
theBuffer,
XalanMessages::EXSLTFunctionAcceptsOneArgument_1Param,
s_sqrtFunctionName);
}
static const XalanDOMChar s_tanFunctionName[] =
{
XalanUnicode::charLetter_t,
XalanUnicode::charLetter_a,
XalanUnicode::charLetter_n,
0
};
XObjectPtr
XalanEXSLTFunctionTan::execute(
XPathExecutionContext& executionContext,
XalanNode* context,
const XObjectArgVectorType& args,
const Locator* locator) const
{
if (args.size() != 1)
{
generalError(
executionContext,
context,
locator);
}
assert(args[0].null() == false);
#if defined(XALAN_STRICT_ANSI_HEADERS)
using std::tan;
#endif
return executionContext.getXObjectFactory().createNumber(tan(args[0]->num(executionContext)));
}
const XalanDOMString&
XalanEXSLTFunctionTan::getError(XalanDOMString& theBuffer) const
{
return XalanMessageLoader::getMessage(
theBuffer,
XalanMessages::EXSLTFunctionAcceptsOneArgument_1Param,
s_tanFunctionName);
}
static const XalanDOMChar s_mathNamespace[] =
{
XalanUnicode::charLetter_h,
XalanUnicode::charLetter_t,
XalanUnicode::charLetter_t,
XalanUnicode::charLetter_p,
XalanUnicode::charColon,
XalanUnicode::charSolidus,
XalanUnicode::charSolidus,
XalanUnicode::charLetter_e,
XalanUnicode::charLetter_x,
XalanUnicode::charLetter_s,
XalanUnicode::charLetter_l,
XalanUnicode::charLetter_t,
XalanUnicode::charFullStop,
XalanUnicode::charLetter_o,
XalanUnicode::charLetter_r,
XalanUnicode::charLetter_g,
XalanUnicode::charSolidus,
XalanUnicode::charLetter_m,
XalanUnicode::charLetter_a,
XalanUnicode::charLetter_t,
XalanUnicode::charLetter_h,
0
};
static const XalanDOMChar s_constantFunctionName[] =
{
XalanUnicode::charLetter_c,
XalanUnicode::charLetter_o,
XalanUnicode::charLetter_n,
XalanUnicode::charLetter_s,
XalanUnicode::charLetter_t,
XalanUnicode::charLetter_a,
XalanUnicode::charLetter_n,
XalanUnicode::charLetter_t,
0
};
static const XalanEXSLTFunctionAbs s_absFunction;
static const XalanEXSLTFunctionAcos s_acosFunction;
static const XalanEXSLTFunctionAsin s_asinFunction;
static const XalanEXSLTFunctionAtan s_atanFunction;
static const XalanEXSLTFunctionAtan2 s_atan2Function;
static const XalanEXSLTFunctionConstant s_constantFunction;
static const XalanEXSLTFunctionCos s_cosFunction;
static const XalanEXSLTFunctionExp s_expFunction;
static const XalanEXSLTFunctionHighest s_highestFunction;
static const XalanEXSLTFunctionLog s_logFunction;
static const XalanEXSLTFunctionLowest s_lowestFunction;
static const XalanEXSLTFunctionMax s_maxFunction;
static const XalanEXSLTFunctionMin s_minFunction;
static const XalanEXSLTFunctionPower s_powerFunction;
static const XalanEXSLTFunctionSin s_sinFunction;
static const XalanEXSLTFunctionSqrt s_sqrtFunction;
static const XalanEXSLTFunctionTan s_tanFunction;
static const XalanEXSLTFunctionRandom s_randomFunction;
static const XalanEXSLTMathFunctionsInstaller::FunctionTableEntry theFunctionTable[] =
{
{ s_absFunctionName, &s_absFunction },
{ s_acosFunctionName, &s_acosFunction },
{ s_asinFunctionName, &s_asinFunction },
{ s_atanFunctionName, &s_atanFunction },
{ s_atan2FunctionName, &s_atan2Function },
{ s_constantFunctionName, &s_constantFunction },
{ s_cosFunctionName, &s_cosFunction },
{ s_expFunctionName, &s_expFunction },
{ s_highestFunctionName, &s_highestFunction },
{ s_logFunctionName, &s_logFunction },
{ s_lowestFunctionName, &s_lowestFunction },
{ s_maxFunctionName, &s_maxFunction },
{ s_minFunctionName, &s_minFunction },
{ s_powerFunctionName, &s_powerFunction },
{ s_sinFunctionName, &s_sinFunction },
{ s_sqrtFunctionName, &s_sqrtFunction },
{ s_tanFunctionName, &s_tanFunction },
{ s_randomFunctionName, &s_randomFunction },
{ 0, 0 }
};
void
XalanEXSLTMathFunctionsInstaller::installLocal(XPathEnvSupportDefault& theSupport)
{
doInstallLocal(s_mathNamespace, theFunctionTable, theSupport);
}
void
XalanEXSLTMathFunctionsInstaller::installGlobal(MemoryManager& theManager)
{
doInstallGlobal(theManager, s_mathNamespace, theFunctionTable);
// Sets the starting point for generating a series of pseudorandom integers,
// we need it for random() EXSLT function
#if defined(XALAN_STRICT_ANSI_HEADERS)
using std::srand;
using std::time;
#endif
srand( (unsigned)time( NULL ) );
}
void
XalanEXSLTMathFunctionsInstaller::uninstallLocal(XPathEnvSupportDefault& theSupport)
{
doUninstallLocal(s_mathNamespace, theFunctionTable, theSupport);
}
void
XalanEXSLTMathFunctionsInstaller::uninstallGlobal(MemoryManager& theManager)
{
doUninstallGlobal(theManager, s_mathNamespace, theFunctionTable);
}
XALAN_CPP_NAMESPACE_END