Add F16C() macro for defining values without float support.
Implementation by Jonas Zeiger.
This commit is contained in:
parent
516f37428b
commit
cbbfe85a4a
|
@ -228,6 +228,89 @@ extern void fix16_to_str(fix16_t value, char *buf, int decimals);
|
|||
*/
|
||||
extern fix16_t fix16_from_str(const char *buf);
|
||||
|
||||
/** Helper macro for F16C. Replace token with its number of characters/digits. */
|
||||
#define FIXMATH_TOKLEN(token) ( sizeof( #token ) - 1 )
|
||||
|
||||
/** Helper macro for F16C. Handles pow(10, n) for n from 0 to 8. */
|
||||
#define FIXMATH_CONSTANT_POW10(times) ( \
|
||||
(times == 0) ? 1ULL \
|
||||
: (times == 1) ? 10ULL \
|
||||
: (times == 2) ? 100ULL \
|
||||
: (times == 3) ? 1000ULL \
|
||||
: (times == 4) ? 10000ULL \
|
||||
: (times == 5) ? 100000ULL \
|
||||
: (times == 6) ? 1000000ULL \
|
||||
: (times == 7) ? 10000000ULL \
|
||||
: 100000000ULL \
|
||||
)
|
||||
|
||||
|
||||
/** Helper macro for F16C, the type uint64_t is only used at compile time and
|
||||
* shouldn't be visible in the generated code.
|
||||
*
|
||||
* @note We do not use fix16_one instead of 65536ULL, because the
|
||||
* "use of a const variable in a constant expression is nonstandard in C".
|
||||
*/
|
||||
#define FIXMATH_CONVERT_MANTISSA(m) \
|
||||
( (unsigned) \
|
||||
( \
|
||||
( \
|
||||
( \
|
||||
(uint64_t)( ( ( 1 ## m ## ULL ) - FIXMATH_CONSTANT_POW10(FIXMATH_TOKLEN(m)) ) * FIXMATH_CONSTANT_POW10(5 - FIXMATH_TOKLEN(m)) ) \
|
||||
* 100000ULL * 65536ULL \
|
||||
) \
|
||||
+ 5000000000ULL /* rounding: + 0.5 */ \
|
||||
) \
|
||||
/ \
|
||||
10000000000LL \
|
||||
) \
|
||||
)
|
||||
|
||||
|
||||
#define FIXMATH_COMBINE_I_M(i, m) \
|
||||
( \
|
||||
( \
|
||||
( i ) \
|
||||
<< 16 \
|
||||
) \
|
||||
| \
|
||||
( \
|
||||
FIXMATH_CONVERT_MANTISSA(m) \
|
||||
& 0xFFFF \
|
||||
) \
|
||||
)
|
||||
|
||||
|
||||
/** Create int16_t (Q16.16) constant from separate integer and mantissa part.
|
||||
*
|
||||
* Only tested on 32-bit ARM Cortex-M0 / x86 Intel.
|
||||
*
|
||||
* This macro is needed when compiling with options like "--fpu=none",
|
||||
* which forbid all and every use of float and related types and
|
||||
* would thus make it impossible to have fix16_t constants.
|
||||
*
|
||||
* Just replace uses of F16() with F16C() like this:
|
||||
* F16(123.1234) becomes F16C(123,1234)
|
||||
*
|
||||
* @warning Specification of any value outside the mentioned intervals
|
||||
* WILL result in undefined behavior!
|
||||
*
|
||||
* @note Regardless of the specified minimum and maximum values for i and m below,
|
||||
* the total value of the number represented by i and m MUST be in the interval
|
||||
* ]-32768.00000:32767.99999[ else usage with this macro will yield undefined behavior.
|
||||
*
|
||||
* @param i Signed integer constant with a value in the interval ]-32768:32767[.
|
||||
* @param m Positive integer constant in the interval ]0:99999[ (fractional part/mantissa).
|
||||
*/
|
||||
#define F16C(i, m) \
|
||||
( (fix16_t) \
|
||||
( \
|
||||
(( #i[0] ) == '-') \
|
||||
? -FIXMATH_COMBINE_I_M((unsigned)( ( (i) * -1) ), m) \
|
||||
: FIXMATH_COMBINE_I_M(i, m) \
|
||||
) \
|
||||
)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#include "fix16.hpp"
|
||||
|
|
|
@ -8,7 +8,7 @@ CFLAGS = -g -O0 -I../libfixmath -Wall -Wextra -Werror
|
|||
FIX16_SRC = ../libfixmath/fix16.c ../libfixmath/fix16_sqrt.c ../libfixmath/fix16_str.c \
|
||||
../libfixmath/fix16_exp.c ../libfixmath/fix16.h
|
||||
|
||||
all: run_fix16_unittests run_fix16_exp_unittests run_fix16_str_unittests
|
||||
all: run_fix16_unittests run_fix16_exp_unittests run_fix16_str_unittests run_fix16_macros_unittests
|
||||
|
||||
clean:
|
||||
rm -f fix16_unittests_????
|
||||
|
@ -63,3 +63,10 @@ run_fix16_str_unittests: fix16_str_unittests
|
|||
fix16_str_unittests: fix16_str_unittests.c $(FIX16_SRC)
|
||||
$(CC) $(CFLAGS) $(DEFINES) -o $@ $^ -lm
|
||||
|
||||
# Tests for literal macros, run only in default config
|
||||
run_fix16_macros_unittests: fix16_macros_unittests
|
||||
./fix16_macros_unittests > /dev/null
|
||||
|
||||
fix16_macros_unittests: fix16_macros_unittests.c $(FIX16_SRC)
|
||||
$(CC) $(CFLAGS) $(DEFINES) -o $@ $^ -lm
|
||||
|
||||
|
|
|
@ -0,0 +1,110 @@
|
|||
/* This test checks that the F16() and F16C() macros work correctly. */
|
||||
|
||||
#include <fix16.h>
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <stdbool.h>
|
||||
#include "unittests.h"
|
||||
|
||||
#define DO_TEST(i,m) \
|
||||
TEST(F16(i ## . ## m) == F16C(i,m)) \
|
||||
TEST(F16(i ## . ## m) == fix16_from_dbl(i ## . ## m))
|
||||
|
||||
int main()
|
||||
{
|
||||
int status = 0;
|
||||
|
||||
/* Corner cases */
|
||||
DO_TEST(1,234)
|
||||
DO_TEST(0,0)
|
||||
DO_TEST(1,0)
|
||||
DO_TEST(-1,0)
|
||||
DO_TEST(1,5)
|
||||
DO_TEST(-1,5)
|
||||
DO_TEST(000000,00000)
|
||||
DO_TEST(0,00001)
|
||||
DO_TEST(0,00010)
|
||||
DO_TEST(0,1)
|
||||
DO_TEST(0,10001)
|
||||
DO_TEST(0,11000)
|
||||
DO_TEST(25,133)
|
||||
DO_TEST(32767,00000)
|
||||
DO_TEST(32767,00001)
|
||||
DO_TEST(32767,99999)
|
||||
DO_TEST(0,25)
|
||||
DO_TEST(0,99555)
|
||||
DO_TEST(0,99998)
|
||||
DO_TEST(0,99999)
|
||||
DO_TEST(-1,1)
|
||||
DO_TEST(-25,133)
|
||||
DO_TEST(-32767,00001)
|
||||
DO_TEST(-32768,00000)
|
||||
|
||||
/* Random values */
|
||||
DO_TEST( 0,02267)
|
||||
DO_TEST( 1,49887)
|
||||
DO_TEST( 0,27589)
|
||||
DO_TEST( 0,38393)
|
||||
DO_TEST( 0,08934)
|
||||
DO_TEST( 0,95820)
|
||||
DO_TEST( 0,95596)
|
||||
DO_TEST( 72,10642)
|
||||
DO_TEST( 0,48939)
|
||||
DO_TEST( 3,37797)
|
||||
DO_TEST( 1,09194)
|
||||
DO_TEST( 0,08605)
|
||||
DO_TEST( 3,04349)
|
||||
DO_TEST( 3,95401)
|
||||
DO_TEST( 15,36292)
|
||||
DO_TEST( 56,09242)
|
||||
DO_TEST( 0,54071)
|
||||
DO_TEST( 27,08953)
|
||||
DO_TEST( 0,03913)
|
||||
DO_TEST( 1,32707)
|
||||
DO_TEST( 4,50117)
|
||||
DO_TEST( 0,24990)
|
||||
DO_TEST( 44,77319)
|
||||
DO_TEST( 2,59139)
|
||||
DO_TEST( 0,16279)
|
||||
DO_TEST( 17,14712)
|
||||
DO_TEST( 11,54281)
|
||||
DO_TEST( 0,02768)
|
||||
DO_TEST( 0,39278)
|
||||
DO_TEST( 0,19369)
|
||||
DO_TEST( -0,04534)
|
||||
DO_TEST( -0,00349)
|
||||
DO_TEST( -2,30380)
|
||||
DO_TEST( -0,03061)
|
||||
DO_TEST( -7,50065)
|
||||
DO_TEST( -3,97050)
|
||||
DO_TEST( -0,43898)
|
||||
DO_TEST( -3,49876)
|
||||
DO_TEST( -1,35942)
|
||||
DO_TEST( -10,81154)
|
||||
DO_TEST( -0,26676)
|
||||
DO_TEST( -9,52134)
|
||||
DO_TEST( -0,42592)
|
||||
DO_TEST( -0,05424)
|
||||
DO_TEST( -0,62461)
|
||||
DO_TEST( -0,21562)
|
||||
DO_TEST( -0,22366)
|
||||
DO_TEST( -0,09074)
|
||||
DO_TEST( -1,29527)
|
||||
DO_TEST( -4,98427)
|
||||
DO_TEST( -0,10721)
|
||||
DO_TEST( -11,39446)
|
||||
DO_TEST(-451,53916)
|
||||
DO_TEST( -0,04279)
|
||||
DO_TEST( -3,36543)
|
||||
DO_TEST( -0,01003)
|
||||
DO_TEST( -12,08326)
|
||||
DO_TEST( -1,07143)
|
||||
DO_TEST( -1,07737)
|
||||
DO_TEST( -0,22957)
|
||||
|
||||
if (status != 0)
|
||||
fprintf(stdout, "\n\nSome tests FAILED!\n");
|
||||
|
||||
return status;
|
||||
}
|
||||
|
Loading…
Reference in New Issue