diff options
| author | Petteri.Aimonen <Petteri.Aimonen@gmail.com> | 2012-02-27 16:40:07 +0000 |
|---|---|---|
| committer | Petteri.Aimonen <Petteri.Aimonen@gmail.com> | 2012-02-27 16:40:07 +0000 |
| commit | e929442f7113dd321057293b8addd7b6e781d77f (patch) | |
| tree | 12cd6b204a999d462e09139d7cf89b12069731c5 /unittests | |
| parent | eb1cb675612c20c643463804945e74ead9377515 (diff) | |
| download | libfixmath-e929442f7113dd321057293b8addd7b6e781d77f.tar.gz | |
Improved fix16_exp() (half runtime, more accuracy), added fix16_log(), made unittests for both.
Diffstat (limited to 'unittests')
| -rw-r--r-- | unittests/Makefile | 12 | ||||
| -rw-r--r-- | unittests/fix16_exp_unittests.c | 124 |
2 files changed, 134 insertions, 2 deletions
diff --git a/unittests/Makefile b/unittests/Makefile index 80df66b..cb5dbb4 100644 --- a/unittests/Makefile +++ b/unittests/Makefile @@ -6,9 +6,9 @@ CFLAGS = -g -O0 -I../libfixmath -Wall -Wextra -Werror # The files required for tests FIX16_SRC = ../libfixmath/fix16.c ../libfixmath/fix16_sqrt.c \ - ../libfixmath/fix16.h + ../libfixmath/fix16_exp.c ../libfixmath/fix16.h -all: run_fix16_unittests +all: run_fix16_unittests run_fix16_exp_unittests clean: rm -f fix16_unittests_???? @@ -47,3 +47,11 @@ fix16_unittests_nn08: DEFINES=-DFIXMATH_NO_OVERFLOW -DFIXMATH_NO_ROUNDING -DFIXM fix16_unittests_% : fix16_unittests.c $(FIX16_SRC) $(CC) $(CFLAGS) $(DEFINES) -o $@ $^ -lm + + +# Tests for the exponential function, run only in default config +run_fix16_exp_unittests: fix16_exp_unittests + ./fix16_exp_unittests > /dev/null + +fix16_exp_unittests: fix16_exp_unittests.c $(FIX16_SRC) + $(CC) $(CFLAGS) $(DEFINES) -o $@ $^ -lm diff --git a/unittests/fix16_exp_unittests.c b/unittests/fix16_exp_unittests.c new file mode 100644 index 0000000..a033a05 --- /dev/null +++ b/unittests/fix16_exp_unittests.c @@ -0,0 +1,124 @@ +#include <fix16.h> +#include <stdio.h> +#include <math.h> +#include <stdbool.h> +#include "unittests.h" + +#define delta(a,b) (((a)>=(b)) ? (a)-(b) : (b)-(a)) + +int main() +{ + int status = 0; + { + COMMENT("Testing fix16_exp() corner cases"); + TEST(fix16_exp(0) == fix16_one); + TEST(fix16_exp(fix16_min) == 0); + TEST(fix16_exp(fix16_max) == fix16_max); + } + + { + COMMENT("Testing fix16_exp() accuracy over -11..4"); + + fix16_t max_delta = -1; + fix16_t worst = 0; + fix16_t sum = 0; + int count = 0; + fix16_t a; + + for (a = fix16_from_dbl(-11.0); a < fix16_from_dbl(4.0); a += 31) + { + fix16_t result = fix16_exp(a); + fix16_t resultf = fix16_from_dbl(exp(fix16_to_dbl(a))); + + fix16_t d = delta(result, resultf); + if (d > max_delta) + { + max_delta = d; + worst = a; + } + + sum += d; + count++; + } + + printf("Worst delta %d with input %d\n", max_delta, worst); + printf("Average delta %0.2f\n", (float)sum / count); + + TEST(max_delta < 200); + } + + { + COMMENT("Testing fix16_exp() accuracy over full range"); + + float max_delta = -1; + fix16_t worst = 0; + float sum = 0; + int count = 0; + fix16_t a; + + // Test the whole range of results 0..32768 with a bit less samples + for (a = -772243; a < 681391; a += 113) + { + fix16_t result = fix16_exp(a); + fix16_t resultf = fix16_from_dbl(exp(fix16_to_dbl(a))); + + fix16_t d1 = delta(result, resultf); + + if (d1 > 0) d1--; // Forgive +-1 for the fix16_t inaccuracy + + float d = (float)d1 / resultf * 100; + + if (resultf < 1000) continue; // Percentages can explode when result is almost 0. + + if (d > max_delta) + { + max_delta = d; + worst = a; + } + + sum += d; + count++; + } + + printf("Worst delta %0.4f%% with input %d\n", max_delta, worst); + printf("Average delta %0.4f%%\n", sum / count); + + TEST(max_delta < 1); + } + + { + COMMENT("Testing fix16_log() accuracy over full range"); + + fix16_t max_delta = -1; + fix16_t worst = 0; + fix16_t sum = 0; + int count = 0; + fix16_t a; + + for (a = 100; a > 0 && a < fix16_max - 7561; a += 7561) + { + fix16_t result = fix16_log(a); + fix16_t resultf = fix16_from_dbl(log(fix16_to_dbl(a))); + + fix16_t d = delta(result, resultf); + if (d > max_delta) + { + max_delta = d; + worst = a; + } + + sum += d; + count++; + } + + printf("Worst delta %d with input %d\n", max_delta, worst); + printf("Average delta %0.2f\n", (float)sum / count); + + TEST(max_delta < 20); + } + + if (status != 0) + fprintf(stdout, "\n\nSome tests FAILED!\n"); + + return status; +}
\ No newline at end of file |
