Fixed errors in asin/atan, where incorrect integer maths was used.

Added a macro (FIXMATH_NO_CACHE) to disable caching.
Added fix16_lerp8 and fix16_lerp32 (should be part of fract module really).
This commit is contained in:
flatmush 2011-02-23 09:47:08 +00:00
parent e06f826388
commit 5d939700e8
4 changed files with 45 additions and 11 deletions

View File

@ -91,6 +91,14 @@ fix16_t fix16_sdiv(fix16_t inArg0, fix16_t inArg1) {
fix16_t fix16_lerp8(fix16_t inArg0, fix16_t inArg1, uint8_t inFract) {
int64_t tempOut;
tempOut = ((int64_t)inArg0 * (256 - inFract));
tempOut += ((int64_t)inArg1 * inFract);
tempOut >>= 8;
return (fix16_t)tempOut;
}
fix16_t fix16_lerp16(fix16_t inArg0, fix16_t inArg1, uint16_t inFract) {
int64_t tempOut;
tempOut = ((int64_t)inArg0 * (fix16_one - inFract));
@ -98,3 +106,11 @@ fix16_t fix16_lerp16(fix16_t inArg0, fix16_t inArg1, uint16_t inFract) {
tempOut >>= 16;
return (fix16_t)tempOut;
}
fix16_t fix16_lerp32(fix16_t inArg0, fix16_t inArg1, uint32_t inFract) {
int64_t tempOut;
tempOut = ((int64_t)inArg0 * (0 - inFract));
tempOut += ((int64_t)inArg1 * inFract);
tempOut >>= 32;
return (fix16_t)tempOut;
}

View File

@ -73,7 +73,9 @@ extern fix16_t fix16_sdiv(fix16_t inArg0, fix16_t inArg1);
/*! Returns the linear interpolation: (inArg0 * (1 - inFract)) + (inArg1 * inFract)
*/
extern fix16_t fix16_lerp8(fix16_t inArg0, fix16_t inArg1, uint8_t inFract);
extern fix16_t fix16_lerp16(fix16_t inArg0, fix16_t inArg1, uint16_t inFract);
extern fix16_t fix16_lerp32(fix16_t inArg0, fix16_t inArg1, uint32_t inFract);

View File

@ -2,15 +2,19 @@
#ifndef FIXMATH_NO_CACHE
fix16_t _fix16_sqrt_cache_index[4096] = { 0 };
fix16_t _fix16_sqrt_cache_value[4096] = { 0 };
#endif
fix16_t fix16_sqrt(fix16_t inValue) {
#ifndef FIXMATH_NO_CACHE
fix16_t tempIndex = (((inValue >> 16) ^ (inValue >> 4)) & 0x00000FFF);
if(_fix16_sqrt_cache_index[tempIndex] == inValue)
return _fix16_sqrt_cache_value[tempIndex];
#endif
int64_t tempOp = inValue; tempOp <<= 16;
int64_t tempOut = 0;
@ -28,8 +32,10 @@ fix16_t fix16_sqrt(fix16_t inValue) {
tempOne >>= 2;
}
#ifndef FIXMATH_NO_CACHE
_fix16_sqrt_cache_index[tempIndex] = inValue;
_fix16_sqrt_cache_value[tempIndex] = tempOut;
#endif
return tempOut;
}

View File

@ -2,10 +2,12 @@
fix16_t _fix16_sin_cache_index[4096] = { 0 };
fix16_t _fix16_sin_cache_value[4096] = { 0 };
fix16_t _fix16_atan_cache_index[4096] = { 0 };
fix16_t _fix16_atan_cache_value[4096] = { 0 };
#ifndef FIXMATH_NO_CACHE
static fix16_t _fix16_sin_cache_index[4096] = { 0 };
static fix16_t _fix16_sin_cache_value[4096] = { 0 };
static fix16_t _fix16_atan_cache_index[4096] = { 0 };
static fix16_t _fix16_atan_cache_value[4096] = { 0 };
#endif
@ -16,9 +18,11 @@ fix16_t fix16_sin(fix16_t inAngle) {
else if(tempAngle < -fix16_pi)
tempAngle += (fix16_pi << 1);
#ifndef FIXMATH_NO_CACHE
fix16_t tempIndex = ((inAngle >> 5) & 0x00000FFF);
if(_fix16_sin_cache_index[tempIndex] == inAngle)
return _fix16_sin_cache_value[tempIndex];
#endif
fix16_t tempAngleSq = fix16_mul(tempAngle, tempAngle);
@ -34,8 +38,10 @@ fix16_t fix16_sin(fix16_t inAngle) {
tempAngle = fix16_mul(tempAngle, tempAngleSq);
tempOut -= (tempAngle / 39916800);
#ifndef FIXMATH_NO_CACHE
_fix16_sin_cache_index[tempIndex] = inAngle;
_fix16_sin_cache_value[tempIndex] = tempOut;
#endif
return tempOut;
}
@ -49,11 +55,11 @@ fix16_t fix16_tan(fix16_t inAngle) {
}
fix16_t fix16_asin(fix16_t inValue) {
if((inValue > 1) || (inValue < -1))
if((inValue > fix16_one) || (inValue < -fix16_one))
return 0;
fix16_t tempOut;
tempOut = (1 - fix16_mul(inValue, inValue));
tempOut = (inValue / fix16_sqrt(tempOut));
tempOut = (fix16_one - fix16_mul(inValue, inValue));
tempOut = fix16_div(inValue, fix16_sqrt(tempOut));
tempOut = fix16_atan(tempOut);
return tempOut;
}
@ -62,12 +68,12 @@ fix16_t fix16_acos(fix16_t inValue) {
return ((fix16_pi >> 1) - fix16_asin(inValue));
}
fix16_t _fix16_atan(fix16_t inValue) {
static fix16_t _fix16_atan(fix16_t inValue) {
fix16_t tempOut;
if(inValue > 29736) {
tempOut = (1 + fix16_mul(inValue, inValue));
tempOut = (1 + fix16_sqrt(tempOut));
tempOut = (inValue / tempOut);
tempOut = (fix16_one + fix16_mul(inValue, inValue));
tempOut = (fix16_one + fix16_sqrt(tempOut));
tempOut = fix16_div(inValue, tempOut);
tempOut = _fix16_atan(tempOut);
return (tempOut << 1);
}
@ -90,12 +96,16 @@ fix16_t _fix16_atan(fix16_t inValue) {
}
fix16_t fix16_atan(fix16_t inValue) {
#ifndef FIXMATH_NO_CACHE
fix16_t tempIndex = (((inValue >> 16) ^ (inValue >> 4)) & 0x00000FFF);
if(_fix16_atan_cache_index[tempIndex] == inValue)
return _fix16_atan_cache_value[tempIndex];
#endif
fix16_t tempOut = _fix16_atan(inValue);
#ifndef FIXMATH_NO_CACHE
_fix16_atan_cache_index[tempIndex] = inValue;
_fix16_atan_cache_value[tempIndex] = tempOut;
#endif
return tempOut;
}