forked from Mirrors/openclonk
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
parent
27b544e778
commit
66e2078b21
|
@ -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:
|
||||
|
|
|
@ -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<>
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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},
|
||||
|
|
|
@ -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; }
|
||||
|
|
Loading…
Reference in New Issue