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.
This commit is contained in:
parent
047ab9fba0
commit
caabb05333
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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); }
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Reference in New Issue