Allow exponentiation (** operator) with fp arguments

The operator is implemented by utilizing the equivalence relation of
x**y == exp(y*log(x)). This introduces a non-trivial error, which may
be reduced/eliminated at a later date by implementing a specialized
pow() function.
floating-point
Nicolas Hake 2011-01-06 18:54:23 +01:00
parent 27b544e778
commit 66e2078b21
7 changed files with 29 additions and 3 deletions

View File

@ -67,6 +67,7 @@ class C4RealBase
friend C4RealBase Sin(const C4RealBase &);
friend C4RealBase Cos(const C4RealBase &);
friend C4RealBase Pow(const C4RealBase &, const C4RealBase &);
friend typename C4RealImpl;
public:

View File

@ -37,6 +37,10 @@ inline C4Real_FPU_Float Cos(const C4Real_FPU_Float &real)
{
return std::cos(real.value * static_cast<float>(M_PI) / 180.0f);
}
inline C4Real_FPU_Float Pow(const C4Real_FPU_Float &x, const C4Real_FPU_Float &y)
{
return std::pow(x.value, y.value);
}
// Overload to avoid conversion warning
template<>

View File

@ -42,4 +42,11 @@ C4Real_SSE_Float Cos(const C4Real_SSE_Float &real)
{
return C4RealImpl_SSE(cos_ps(_mm_mul_ps(real.value.value, deg2rad)));
}
C4Real_SSE_Float Pow(const C4Real_SSE_Float &x, const C4Real_SSE_Float &y)
{
C4RealImpl_SSE val;
val.value = log_ps(x.value.value);
val *= y.value;
val.value = exp_ps(val.value);
return val;
}

View File

@ -30,12 +30,15 @@ class C4RealImpl_SSE
{
friend C4Real_SSE_Float Sin(const C4Real_SSE_Float &);
friend C4Real_SSE_Float Cos(const C4Real_SSE_Float &);
friend C4Real_SSE_Float Pow(const C4Real_SSE_Float &, const C4Real_SSE_Float &);
__m128 value;
C4RealImpl_SSE Pow(const C4RealImpl_SSE &y) const; // power function
inline C4RealImpl_SSE(__m128 rhs)
: value(rhs)
{}
public:
inline C4RealImpl_SSE()
: value(_mm_setzero_ps())

View File

@ -296,7 +296,7 @@ C4Value C4AulExec::Exec(C4AulBCC *pCPos, bool fPassErrors)
{
CheckOpPars(pCPos->Par.i);
C4Value *pPar1 = pCurVal - 1, *pPar2 = pCurVal;
pPar1->SetInt(Pow(pPar1->_getInt(), pPar2->_getInt()));
pPar1->Set(pPar1->Pow(*pPar2));
PopValue();
break;
}

View File

@ -440,7 +440,7 @@ C4ScriptOpDef C4ScriptOpMap[] =
{ 16, "--", AB_Dec, AB_Inc, 1, 1, 1, C4V_Int, C4V_Numeric, C4V_Any},
// postfix
{ 14, "**", AB_Pow, AB_ERR, 1, 0, 0, C4V_Int, C4V_Int, C4V_Int},
{ 14, "**", AB_Pow, AB_ERR, 1, 0, 0, C4V_Int, C4V_Numeric, C4V_Numeric},
{ 13, "/", AB_Div, AB_ERR, 1, 0, 0, C4V_Any, C4V_Numeric, C4V_Numeric},
{ 13, "*", AB_Mul, AB_ERR, 1, 0, 0, C4V_Any, C4V_Numeric, C4V_Numeric},
{ 13, "%", AB_Mod, AB_ERR, 1, 0, 0, C4V_Int, C4V_Int, C4V_Int},

View File

@ -222,6 +222,17 @@ public:
operator--();
return nrv;
}
C4Value Pow(const C4Value &rhs) const
{
assert(ConvertTo(C4V_Numeric));
assert(rhs.ConvertTo(C4V_Numeric));
C4Value nrv;
if (Type == C4V_Float || rhs.Type == C4V_Float)
nrv.SetFloat(::Pow(getFloat(), rhs.getFloat()));
else
nrv.SetInt(::Pow(getInt(), rhs.getInt()));
return nrv;
}
// getters
C4V_Data GetData() const { return Data; }