forked from Mirrors/openclonk
Implement operator % for floats
parent
d3f37e5cfd
commit
9b8cfac66e
|
@ -68,6 +68,19 @@ public:
|
|||
inline C4Real &operator -= (const C4Real &rhs) { value = _mm_sub_ps(value, rhs.value); return *this; }
|
||||
inline C4Real &operator *= (const C4Real &rhs) { value = _mm_mul_ps(value, rhs.value); return *this; }
|
||||
inline C4Real &operator /= (const C4Real &rhs) { value = _mm_div_ss(value, rhs.value); return *this; }
|
||||
private: inline __m128 float_hexconst(int32_t c) { union {float f;int i;} fi; fi.i=c; return _mm_set_ps1(fi.f); } public: // can't use a reinterpret_cast here because the parameter is type-punned
|
||||
inline C4Real &operator %= (const C4Real &rhs) {
|
||||
// unfortunately, there is no _mm_mod_ss. The trick is to abuse the 23 bit significancy by adding (or substracting) a value, which will leave the result truncated. We can work with that
|
||||
__m128 div = _mm_div_ss(value, rhs.value);
|
||||
// round
|
||||
__m128 sig = _mm_or_ps(_mm_and_ps(div, float_hexconst(0x80000000)), float_hexconst(0x4b000000)); // generate (sign?+:-)2^23
|
||||
__m128 trunc = _mm_sub_ps(_mm_add_ps(div, sig), sig);
|
||||
// unfortunately, we have rounded towards 0: the hack add -1 when trunc is < 0 (fortunately, < returns 0xffffffff when true)
|
||||
trunc = _mm_add_ps(trunc, _mm_and_ps(_mm_cmplt_ps(trunc, _mm_set_ps1(0.0)), float_hexconst(0xbf800000)));
|
||||
// finish calc
|
||||
value = _mm_sub_ps(value, _mm_mul_ps(trunc, rhs.value));
|
||||
return *this;
|
||||
}
|
||||
|
||||
#define C4REAL_ARITHMETIC_OPERATOR(op) \
|
||||
/* arithmetic operations on copies */ \
|
||||
|
|
|
@ -310,10 +310,9 @@ C4Value C4AulExec::Exec(C4AulBCC *pCPos, bool fPassErrors)
|
|||
{
|
||||
CheckOpPars(C4V_Numeric, C4V_Numeric, "%");
|
||||
C4Value *pPar1 = pCurVal - 1, *pPar2 = pCurVal;
|
||||
if (pPar2->_getInt())
|
||||
pPar1->SetInt(pPar1->_getInt() % pPar2->_getInt());
|
||||
else
|
||||
pPar1->Set0();
|
||||
if(!pPar2->_getInt())
|
||||
throw new C4AulExecError(pCurCtx->Obj, "modulo operation with zero");
|
||||
*pPar1 %= *pPar2;
|
||||
PopValue();
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -181,6 +181,7 @@ public:
|
|||
C4VALUE_ARITHMETIC_OPERATOR(-)
|
||||
C4VALUE_ARITHMETIC_OPERATOR(*)
|
||||
C4VALUE_ARITHMETIC_OPERATOR(/)
|
||||
C4VALUE_ARITHMETIC_OPERATOR(%)
|
||||
#undef C4VALUE_ARITHMETIC_OPERATOR
|
||||
|
||||
C4Value &operator++()
|
||||
|
|
Loading…
Reference in New Issue