From caabb05333c4e5bbac22f580471df71041020fa9 Mon Sep 17 00:00:00 2001 From: flatmush Date: Mon, 28 Feb 2011 15:49:51 +0000 Subject: Replaced all macros with static inline functions and static consts for typechecking and easier debugging. Made 32-bit division slightly more accurate and added a TODO comment to make it as accurate as the 64-bit division. --- libfixmath/fix16.c | 91 ++++++++++++++++---------------------------------- libfixmath/fix16.h | 35 ++++++++----------- libfixmath/fix16_exp.c | 2 +- 3 files changed, 42 insertions(+), 86 deletions(-) diff --git a/libfixmath/fix16.c b/libfixmath/fix16.c index a40f3c8..49473ca 100644 --- a/libfixmath/fix16.c +++ b/libfixmath/fix16.c @@ -1,27 +1,13 @@ #include "fix16.h" -/* Replaced as macros, these are left here to uncomment for code dependant on the symbols. -const fix16_t fix16_pi = 205887; -const fix16_t fix16_e = 178145; -const fix16_t fix16_one = 0x00010000; - -double fix16_to_dbl(const fix16_t inVal) { return ((double)inVal / 65536.0); } -fix16_t fix16_from_dbl(const double inVal) { return (fix16_t)(inVal * 65536.0); } -float fix16_to_float(const fix16_t inVal) { return ((float)inVal / 65536.0f); } -fix16_t fix16_from_float(const float inVal) { return (fix16_t)(inVal * 65536.0f); } -int32_t fix16_to_int(const fix16_t inVal) { return ((inVal + 0x00008000) >> 16); } -fix16_t fix16_from_int(const int32_t inVal) { return (inVal << 16); } -*/ - - fix16_t fix16_sadd(fix16_t inArg0, fix16_t inArg1) { fix16_t tempResult = (inArg0 + inArg1); if((tempResult > 0) && (inArg0 < 0) && (inArg1 < 0)) - return 0x80000000; + return fix16_min; if((tempResult < 0) && (inArg0 > 0) && (inArg1 > 0)) - return 0x7FFFFFFF; + return fix16_max; return tempResult; } @@ -60,16 +46,16 @@ fix16_t fix16_smul(fix16_t inArg0, fix16_t inArg1) { tempResult += (fix16_one >> 1); #endif tempResult >>= 16; - if(tempResult < fix16_MIN) - return fix16_MIN; - if(tempResult > fix16_MAX) - return fix16_MAX; + if(tempResult < fix16_min) + return fix16_min; + if(tempResult > fix16_max) + return fix16_max; return tempResult; #else int16_t hi[2] = { (inArg0 >> 16), (inArg1 >> 16) }; int32_t r_hi = hi[0] * hi[1]; if(r_hi >> 16) - return (r_hi < 0 ? fix16_MIN : fix16_MAX); + return (r_hi < 0 ? fix16_min : fix16_max); uint16_t lo[2] = { (inArg0 & 0xFFFF), (inArg1 & 0xFFFF) }; int32_t r_md = (hi[0] * lo[1]) + (hi[1] * lo[0]); @@ -97,8 +83,12 @@ fix16_t fix16_div(fix16_t inArg0, fix16_t inArg1) { tempResult /= inArg1; return tempResult; #else - int32_t rcp = (0xFFFFFFFF / inArg1); - int32_t rcp_hi = rcp >> 16; + int32_t rcp = (0xFFFFFFFF / inArg1); + #ifndef FIXMATH_FAST_DIV + if(((0xFFFFFFFF % inArg1) + 1) >= inArg1) + rcp++; + #endif + int32_t rcp_hi = rcp >> 16; uint32_t rcp_lo = rcp & 0xFFFF; int32_t arg_hi = (inArg0 >> 16); @@ -113,28 +103,14 @@ fix16_t fix16_div(fix16_t inArg0, fix16_t inArg1) { res += ((res_lo >> 15) & 1); #endif return res; - - /*int32_t res = (inArg0 / inArg1) << 16; - int32_t mod = inArg0 % inArg1; - uintptr_t i; - for(i = 0; i < 16; i++) { - mod <<= 1; - res += (mod / inArg1) << (15 - i); - mod %= inArg1; - } - #ifndef FIXMATH_NO_ROUNDING - if((mod << 1) / inArg1) - res++; - #endif - return res;*/ #endif } fix16_t fix16_sdiv(fix16_t inArg0, fix16_t inArg1) { if(inArg1 == 0) { if(inArg0 < 0) - return fix16_MIN; - return fix16_MAX; + return fix16_min; + return fix16_max; } #ifndef FIXMATH_NO_64BIT int64_t tempResult = inArg0; @@ -143,18 +119,22 @@ fix16_t fix16_sdiv(fix16_t inArg0, fix16_t inArg1) { tempResult += (inArg1 >> 1); #endif tempResult /= inArg1; - if(tempResult < fix16_MIN) + if(tempResult < fix16_min) return fix16_MIN; - if(tempResult > fix16_MAX) - return fix16_MAX; + if(tempResult > fix16_max) + return fix16_max; return tempResult; #else - int32_t rcp = (0xFFFFFFFF / inArg1); - int32_t rcp_hi = rcp >> 16; + int32_t rcp = (0xFFFFFFFF / inArg1); + #ifndef FIXMATH_FAST_DIV + if(((0xFFFFFFFF % inArg1) + 1) >= inArg1) + rcp++; + #endif + int32_t rcp_hi = rcp >> 16; if(rcp_hi >= 32768) - return fix16_MAX; + return fix16_max; if(rcp_hi < -32768) - return fix16_MIN; + return fix16_min; uint32_t rcp_lo = rcp & 0xFFFF; int32_t arg_hi = (inArg0 >> 16); @@ -164,28 +144,13 @@ fix16_t fix16_sdiv(fix16_t inArg0, fix16_t inArg1) { int32_t res_md = (rcp_hi * arg_lo) + (rcp_lo * arg_hi); uint32_t res_lo = rcp_lo * arg_lo; + // TODO - Check properly for overflows at this stage. + int32_t res = (res_hi << 16) + res_md + (res_lo >> 16); #ifndef FIXMATH_NO_ROUNDING res += ((res_lo >> 15) & 1); #endif return res; - - /*int32_t res = (inArg0 / inArg1); - if((res < -32768) || (res >= 32768)) - return (res < 0 ? fix16_MIN : fix16_MAX); - res <<= 16; - int32_t mod = inArg0 % inArg1; - uintptr_t i; - for(i = 0; i < 16; i++) { - mod <<= 1; - res += (mod / inArg1) << (15 - i); - mod %= inArg1; - } - #ifndef FIXMATH_NO_ROUNDING - if((mod << 1) / inArg1) - res++; - #endif - return res;*/ #endif } diff --git a/libfixmath/fix16.h b/libfixmath/fix16.h index b947976..d1a1230 100644 --- a/libfixmath/fix16.h +++ b/libfixmath/fix16.h @@ -10,42 +10,33 @@ extern "C" typedef int32_t fix16_t; -#define fix16_MAX (fix16_t)0x7FFFFFFF /*!< the maximum value of fix16_t */ -#define fix16_MIN (fix16_t)0x80000000 /*!< the minimum value of fix16_t */ +static const fix16_t fix16_max = 0x7FFFFFFF; /*!< the maximum value of fix16_t */ +static const fix16_t fix16_min = 0x80000000; /*!< the minimum value of fix16_t */ -#define fix16_pi 205887 /*!< fix16_t value of pi */ -#define fix16_e 178145 /*!< fix16_t value of e */ -#define fix16_one 0x00010000 /*!< fix16_t value of 1 */ +static const fix16_t fix16_pi = 205887; /*!< fix16_t value of pi */ +static const fix16_t fix16_e = 178145; /*!< fix16_t value of e */ +static const fix16_t fix16_one = 0x00010000; /*!< fix16_t value of 1 */ #ifdef FIXMATH_NO_ROUNDING /*! Converts a double to a fix16_t and returns the result. */ -#define fix16_from_dbl(inVal) ((fix16_t)((inVal) * 65536.0)) +static inline fix16_t fix16_from_dbl(const double inVal) { return (fix16_t)(inVal * 65536.0); } /*! Converts a float to a fix16_t and returns the result. */ -#define fix16_from_float(inVal) ((fix16_t)((inVal) * 65536.0f)) +static inline fix16_t fix16_from_float(const float inVal) { return (fix16_t)(inVal * 65536.0f); } #else /*! Converts a double to a fix16_t and returns the result. */ -#define fix16_from_dbl(inVal) ((fix16_t)(((inVal) * 65536.0) + 0.5)) +static inline fix16_t fix16_from_dbl(const double inVal) { return (fix16_t)((inVal * 65536.0) + 0.5); } /*! Converts a float to a fix16_t and returns the result. */ -#define fix16_from_float(inVal) ((fix16_t)(((inVal) * 65536.0f) + 0.5f)) +static inline fix16_t fix16_from_float(const float inVal) { return (fix16_t)((inVal * 65536.0f) + 0.5f); } #endif /*! Converts a signed integer to a fix16_t and returns the result. */ -#define fix16_from_int(inVal) ((fix16_t)((inVal) << 16)) +static inline fix16_t fix16_from_int(const int32_t inVal) { return (inVal << 16); } /*! Coverts a fix16_t to a double and returns the result. */ -#define fix16_to_dbl(inVal) ((double)((inVal) / 65536.0)) +static inline double fix16_to_dbl(const fix16_t inVal) { return ((double)inVal / 65536.0); } /*! Converts a fix16_t to a float and returns the result. */ -#define fix16_to_float(inVal) ((float)((inVal) / 65536.0f)) +static inline float fix16_to_float(const fix16_t inVal) { return ((float)inVal / 65536.0f); } /*! Converts a fix16_t to a signed integer and returns the result. */ -#define fix16_to_int(inVal) ((int32_t)(((inVal) + (fix16_one >> 1)) >> 16)) - -/* Replaced with macros, uncomment if symbols are needed by old code. -extern double fix16_to_dbl(const fix16_t inVal); -extern fix16_t fix16_from_dbl(const double inVal); -extern float fix16_to_float(const fix16_t inVal); -extern fix16_t fix16_from_float(const float inVal); -extern int32_t fix16_to_int(const fix16_t inVal); -extern fix16_t fix16_from_int(const int32_t inVal); -*/ +static inline int32_t fix16_to_int(const fix16_t inVal) { return ((inVal + 0x00008000) >> 16); } diff --git a/libfixmath/fix16_exp.c b/libfixmath/fix16_exp.c index 014fa1c..d48698a 100644 --- a/libfixmath/fix16_exp.c +++ b/libfixmath/fix16_exp.c @@ -15,7 +15,7 @@ fix16_t fix16_exp(fix16_t inValue) { if(inValue == fix16_one) return fix16_e; if(inValue > 681391) - return fix16_MAX; + return fix16_max; if(inValue < -726817) return 0; -- cgit v1.2.3