commit
fd01d546a9
|
@ -70,7 +70,7 @@ static inline fix16_t fix16_from_dbl(double a)
|
||||||
{
|
{
|
||||||
double temp = a * fix16_one;
|
double temp = a * fix16_one;
|
||||||
#ifndef FIXMATH_NO_ROUNDING
|
#ifndef FIXMATH_NO_ROUNDING
|
||||||
temp += (temp >= 0) ? 0.5f : -0.5f;
|
temp += (double)((temp >= 0) ? 0.5f : -0.5f);
|
||||||
#endif
|
#endif
|
||||||
return (fix16_t)temp;
|
return (fix16_t)temp;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,18 @@
|
||||||
#include "fix16.h"
|
#include "fix16.h"
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#ifndef FIXMATH_NO_CTYPE
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
#else
|
||||||
|
static inline int isdigit(int c)
|
||||||
|
{
|
||||||
|
return c >= '0' && c <= '9';
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int isspace(int c)
|
||||||
|
{
|
||||||
|
return c == ' ' || c == '\r' || c == '\n' || c == '\t' || c == '\v' || c == '\f';
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static const uint32_t scales[8] = {
|
static const uint32_t scales[8] = {
|
||||||
/* 5 decimals is enough for full fix16_t precision */
|
/* 5 decimals is enough for full fix16_t precision */
|
||||||
|
|
|
@ -33,22 +33,22 @@ static inline int int64_cmp_le(int64_t x, int64_t y) { return (x <= y); }
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int32_t hi;
|
int32_t hi;
|
||||||
uint32_t lo;
|
uint32_t lo;
|
||||||
} __int64_t;
|
} _int64_t;
|
||||||
|
|
||||||
static inline __int64_t int64_const(int32_t hi, uint32_t lo) { return (__int64_t){ hi, lo }; }
|
static inline _int64_t int64_const(int32_t hi, uint32_t lo) { return (_int64_t){ hi, lo }; }
|
||||||
static inline __int64_t int64_from_int32(int32_t x) { return (__int64_t){ (x < 0 ? -1 : 0), x }; }
|
static inline _int64_t int64_from_int32(int32_t x) { return (_int64_t){ (x < 0 ? -1 : 0), x }; }
|
||||||
static inline int32_t int64_hi(__int64_t x) { return x.hi; }
|
static inline int32_t int64_hi(_int64_t x) { return x.hi; }
|
||||||
static inline uint32_t int64_lo(__int64_t x) { return x.lo; }
|
static inline uint32_t int64_lo(_int64_t x) { return x.lo; }
|
||||||
|
|
||||||
static inline int int64_cmp_eq(__int64_t x, __int64_t y) { return ((x.hi == y.hi) && (x.lo == y.lo)); }
|
static inline int int64_cmp_eq(_int64_t x, _int64_t y) { return ((x.hi == y.hi) && (x.lo == y.lo)); }
|
||||||
static inline int int64_cmp_ne(__int64_t x, __int64_t y) { return ((x.hi != y.hi) || (x.lo != y.lo)); }
|
static inline int int64_cmp_ne(_int64_t x, _int64_t y) { return ((x.hi != y.hi) || (x.lo != y.lo)); }
|
||||||
static inline int int64_cmp_gt(__int64_t x, __int64_t y) { return ((x.hi > y.hi) || ((x.hi == y.hi) && (x.lo > y.lo))); }
|
static inline int int64_cmp_gt(_int64_t x, _int64_t y) { return ((x.hi > y.hi) || ((x.hi == y.hi) && (x.lo > y.lo))); }
|
||||||
static inline int int64_cmp_ge(__int64_t x, __int64_t y) { return ((x.hi > y.hi) || ((x.hi == y.hi) && (x.lo >= y.lo))); }
|
static inline int int64_cmp_ge(_int64_t x, _int64_t y) { return ((x.hi > y.hi) || ((x.hi == y.hi) && (x.lo >= y.lo))); }
|
||||||
static inline int int64_cmp_lt(__int64_t x, __int64_t y) { return ((x.hi < y.hi) || ((x.hi == y.hi) && (x.lo < y.lo))); }
|
static inline int int64_cmp_lt(_int64_t x, _int64_t y) { return ((x.hi < y.hi) || ((x.hi == y.hi) && (x.lo < y.lo))); }
|
||||||
static inline int int64_cmp_le(__int64_t x, __int64_t y) { return ((x.hi < y.hi) || ((x.hi == y.hi) && (x.lo <= y.lo))); }
|
static inline int int64_cmp_le(_int64_t x, _int64_t y) { return ((x.hi < y.hi) || ((x.hi == y.hi) && (x.lo <= y.lo))); }
|
||||||
|
|
||||||
static inline __int64_t int64_add(__int64_t x, __int64_t y) {
|
static inline _int64_t int64_add(_int64_t x, _int64_t y) {
|
||||||
__int64_t ret;
|
_int64_t ret;
|
||||||
ret.hi = x.hi + y.hi;
|
ret.hi = x.hi + y.hi;
|
||||||
ret.lo = x.lo + y.lo;
|
ret.lo = x.lo + y.lo;
|
||||||
if((ret.lo < x.lo) || (ret.hi < y.hi))
|
if((ret.lo < x.lo) || (ret.hi < y.hi))
|
||||||
|
@ -56,8 +56,8 @@ static inline __int64_t int64_add(__int64_t x, __int64_t y) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline __int64_t int64_neg(__int64_t x) {
|
static inline _int64_t int64_neg(_int64_t x) {
|
||||||
__int64_t ret;
|
_int64_t ret;
|
||||||
ret.hi = ~x.hi;
|
ret.hi = ~x.hi;
|
||||||
ret.lo = ~x.lo + 1;
|
ret.lo = ~x.lo + 1;
|
||||||
if(ret.lo == 0)
|
if(ret.lo == 0)
|
||||||
|
@ -65,28 +65,28 @@ static inline __int64_t int64_neg(__int64_t x) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline __int64_t int64_sub(__int64_t x, __int64_t y) {
|
static inline _int64_t int64_sub(_int64_t x, _int64_t y) {
|
||||||
return int64_add(x, int64_neg(y));
|
return int64_add(x, int64_neg(y));
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline __int64_t int64_shift(__int64_t x, int8_t y) {
|
static inline _int64_t int64_shift(_int64_t x, int8_t y) {
|
||||||
__int64_t ret;
|
_int64_t ret;
|
||||||
if(y > 0) {
|
if(y > 0) {
|
||||||
if(y >= 32)
|
if(y >= 32)
|
||||||
return (__int64_t){ 0, 0 };
|
return (_int64_t){ 0, 0 };
|
||||||
ret.hi = (x.hi << y) | (x.lo >> (32 - y));
|
ret.hi = (x.hi << y) | (x.lo >> (32 - y));
|
||||||
ret.lo = (x.lo << y);
|
ret.lo = (x.lo << y);
|
||||||
} else {
|
} else {
|
||||||
y = -y;
|
y = -y;
|
||||||
if(y >= 32)
|
if(y >= 32)
|
||||||
return (__int64_t){ 0, 0 };
|
return (_int64_t){ 0, 0 };
|
||||||
ret.lo = (x.lo >> y) | (x.hi << (32 - y));
|
ret.lo = (x.lo >> y) | (x.hi << (32 - y));
|
||||||
ret.hi = (x.hi >> y);
|
ret.hi = (x.hi >> y);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline __int64_t int64_mul_i32_i32(int32_t x, int32_t y) {
|
static inline _int64_t int64_mul_i32_i32(int32_t x, int32_t y) {
|
||||||
int16_t hi[2] = { (x >> 16), (y >> 16) };
|
int16_t hi[2] = { (x >> 16), (y >> 16) };
|
||||||
uint16_t lo[2] = { (x & 0xFFFF), (y & 0xFFFF) };
|
uint16_t lo[2] = { (x & 0xFFFF), (y & 0xFFFF) };
|
||||||
|
|
||||||
|
@ -97,10 +97,10 @@ static inline __int64_t int64_mul_i32_i32(int32_t x, int32_t y) {
|
||||||
r_hi += (r_md >> 16);
|
r_hi += (r_md >> 16);
|
||||||
r_lo += (r_md << 16);
|
r_lo += (r_md << 16);
|
||||||
|
|
||||||
return (__int64_t){ r_hi, r_lo };
|
return (_int64_t){ r_hi, r_lo };
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline __int64_t int64_mul_i64_i32(__int64_t x, int32_t y) {
|
static inline _int64_t int64_mul_i64_i32(_int64_t x, int32_t y) {
|
||||||
int neg = ((x.hi ^ y) < 0);
|
int neg = ((x.hi ^ y) < 0);
|
||||||
if(x.hi < 0)
|
if(x.hi < 0)
|
||||||
x = int64_neg(x);
|
x = int64_neg(x);
|
||||||
|
@ -116,26 +116,26 @@ static inline __int64_t int64_mul_i64_i32(__int64_t x, int32_t y) {
|
||||||
r[2] = (_x[1] * _y[1]) + (_x[2] * _y[0]);
|
r[2] = (_x[1] * _y[1]) + (_x[2] * _y[0]);
|
||||||
r[3] = (_x[2] * _y[0]) + (_x[1] * _y[1]);
|
r[3] = (_x[2] * _y[0]) + (_x[1] * _y[1]);
|
||||||
|
|
||||||
__int64_t ret;
|
_int64_t ret;
|
||||||
ret.lo = r[0] + (r[1] << 16);
|
ret.lo = r[0] + (r[1] << 16);
|
||||||
ret.hi = (r[3] << 16) + r[2] + (r[1] >> 16);
|
ret.hi = (r[3] << 16) + r[2] + (r[1] >> 16);
|
||||||
return (neg ? int64_neg(ret) : ret);
|
return (neg ? int64_neg(ret) : ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline __int64_t int64_div_i64_i32(__int64_t x, int32_t y) {
|
static inline _int64_t int64_div_i64_i32(_int64_t x, int32_t y) {
|
||||||
int neg = ((x.hi ^ y) < 0);
|
int neg = ((x.hi ^ y) < 0);
|
||||||
if(x.hi < 0)
|
if(x.hi < 0)
|
||||||
x = int64_neg(x);
|
x = int64_neg(x);
|
||||||
if(y < 0)
|
if(y < 0)
|
||||||
y = -y;
|
y = -y;
|
||||||
|
|
||||||
__int64_t ret = { (x.hi / y) , (x.lo / y) };
|
_int64_t ret = { (x.hi / y) , (x.lo / y) };
|
||||||
x.hi = x.hi % y;
|
x.hi = x.hi % y;
|
||||||
x.lo = x.lo % y;
|
x.lo = x.lo % y;
|
||||||
|
|
||||||
__int64_t _y = int64_from_int32(y);
|
_int64_t _y = int64_from_int32(y);
|
||||||
|
|
||||||
__int64_t i;
|
_int64_t i;
|
||||||
for(i = int64_from_int32(1); int64_cmp_lt(_y, x); _y = int64_shift(_y, 1), i = int64_shift(i, 1));
|
for(i = int64_from_int32(1); int64_cmp_lt(_y, x); _y = int64_shift(_y, 1), i = int64_shift(i, 1));
|
||||||
|
|
||||||
while(x.hi) {
|
while(x.hi) {
|
||||||
|
@ -151,7 +151,7 @@ static inline __int64_t int64_div_i64_i32(__int64_t x, int32_t y) {
|
||||||
return (neg ? int64_neg(ret) : ret);
|
return (neg ? int64_neg(ret) : ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define int64_t __int64_t
|
#define int64_t _int64_t
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,10 @@ all: run_fix16_unittests run_fix16_exp_unittests run_fix16_str_unittests run_fix
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f fix16_unittests_????
|
rm -f fix16_unittests_????
|
||||||
|
rm -f fix16_str_unittests_default
|
||||||
|
rm -f fix16_str_unittests_no_ctype
|
||||||
|
rm -f fix16_exp_unittests
|
||||||
|
rm -f fix16_macros_unittests
|
||||||
|
|
||||||
# The library is tested automatically under different compilations
|
# The library is tested automatically under different compilations
|
||||||
# options.
|
# options.
|
||||||
|
@ -44,6 +48,7 @@ fix16_unittests_ro08: DEFINES=-DFIXMATH_OPTIMIZE_8BIT
|
||||||
fix16_unittests_no08: DEFINES=-DFIXMATH_NO_ROUNDING -DFIXMATH_OPTIMIZE_8BIT
|
fix16_unittests_no08: DEFINES=-DFIXMATH_NO_ROUNDING -DFIXMATH_OPTIMIZE_8BIT
|
||||||
fix16_unittests_rn08: DEFINES=-DFIXMATH_NO_OVERFLOW -DFIXMATH_OPTIMIZE_8BIT
|
fix16_unittests_rn08: DEFINES=-DFIXMATH_NO_OVERFLOW -DFIXMATH_OPTIMIZE_8BIT
|
||||||
fix16_unittests_nn08: DEFINES=-DFIXMATH_NO_OVERFLOW -DFIXMATH_NO_ROUNDING -DFIXMATH_OPTIMIZE_8BIT
|
fix16_unittests_nn08: DEFINES=-DFIXMATH_NO_OVERFLOW -DFIXMATH_NO_ROUNDING -DFIXMATH_OPTIMIZE_8BIT
|
||||||
|
fix16_str_unittests_no_ctype: DEFINES=-DFIXMATH_NO_CTYPE
|
||||||
|
|
||||||
fix16_unittests_% : fix16_unittests.c $(FIX16_SRC)
|
fix16_unittests_% : fix16_unittests.c $(FIX16_SRC)
|
||||||
$(CC) $(CFLAGS) $(DEFINES) -o $@ $^ -lm
|
$(CC) $(CFLAGS) $(DEFINES) -o $@ $^ -lm
|
||||||
|
@ -55,12 +60,13 @@ run_fix16_exp_unittests: fix16_exp_unittests
|
||||||
|
|
||||||
fix16_exp_unittests: fix16_exp_unittests.c $(FIX16_SRC)
|
fix16_exp_unittests: fix16_exp_unittests.c $(FIX16_SRC)
|
||||||
$(CC) $(CFLAGS) $(DEFINES) -o $@ $^ -lm
|
$(CC) $(CFLAGS) $(DEFINES) -o $@ $^ -lm
|
||||||
|
|
||||||
# Tests for string conversion, run only in default config
|
|
||||||
run_fix16_str_unittests: fix16_str_unittests
|
|
||||||
./fix16_str_unittests > /dev/null
|
|
||||||
|
|
||||||
fix16_str_unittests: fix16_str_unittests.c $(FIX16_SRC)
|
# Tests for string conversion, run only in default config and no ctype
|
||||||
|
run_fix16_str_unittests: fix16_str_unittests_default fix16_str_unittests_no_ctype
|
||||||
|
./fix16_str_unittests_default > /dev/null
|
||||||
|
./fix16_str_unittests_no_ctype > /dev/null
|
||||||
|
|
||||||
|
fix16_str_unittests_%: fix16_str_unittests.c $(FIX16_SRC)
|
||||||
$(CC) $(CFLAGS) $(DEFINES) -o $@ $^ -lm
|
$(CC) $(CFLAGS) $(DEFINES) -o $@ $^ -lm
|
||||||
|
|
||||||
# Tests for literal macros, run only in default config
|
# Tests for literal macros, run only in default config
|
||||||
|
|
Loading…
Reference in New Issue