aboutsummaryrefslogtreecommitdiff
path: root/unittests
diff options
context:
space:
mode:
authorPetteri.Aimonen <Petteri.Aimonen@gmail.com>2012-02-27 16:40:07 +0000
committerPetteri.Aimonen <Petteri.Aimonen@gmail.com>2012-02-27 16:40:07 +0000
commite929442f7113dd321057293b8addd7b6e781d77f (patch)
tree12cd6b204a999d462e09139d7cf89b12069731c5 /unittests
parenteb1cb675612c20c643463804945e74ead9377515 (diff)
downloadlibfixmath-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/Makefile12
-rw-r--r--unittests/fix16_exp_unittests.c124
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