From 5d939700e8a1ed33903067c641b7ca93abedab96 Mon Sep 17 00:00:00 2001 From: flatmush Date: Wed, 23 Feb 2011 09:47:08 +0000 Subject: 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). --- libfixmath/fix16.c | 16 ++++++++++++++++ libfixmath/fix16.h | 2 ++ libfixmath/fix16_sqrt.c | 6 ++++++ libfixmath/fix16_trig.c | 32 +++++++++++++++++++++----------- 4 files changed, 45 insertions(+), 11 deletions(-) diff --git a/libfixmath/fix16.c b/libfixmath/fix16.c index 3fef27d..32fc3d1 100644 --- a/libfixmath/fix16.c +++ b/libfixmath/fix16.c @@ -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; +} diff --git a/libfixmath/fix16.h b/libfixmath/fix16.h index aacfd8e..7913b9c 100644 --- a/libfixmath/fix16.h +++ b/libfixmath/fix16.h @@ -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); diff --git a/libfixmath/fix16_sqrt.c b/libfixmath/fix16_sqrt.c index f913a62..3d8e164 100644 --- a/libfixmath/fix16_sqrt.c +++ b/libfixmath/fix16_sqrt.c @@ -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; } diff --git a/libfixmath/fix16_trig.c b/libfixmath/fix16_trig.c index 9d5046b..c162b61 100644 --- a/libfixmath/fix16_trig.c +++ b/libfixmath/fix16_trig.c @@ -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; } -- cgit v1.2.3