annotate q/t.c @ 23:3c713073dd0c

Remove debug prints and #ifdef now the control code works.
author Daniel O'Connor <darius@dons.net.au>
date Tue, 25 Feb 2025 15:56:49 +1030
parents 388074ff9474
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
14
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
1 /**@file t.c
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
2 * @brief Q-Number (Q16.16, signed) library test bench
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
3 * @copyright Richard James Howe (2018)
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
4 * @license MIT
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
5 * @email howe.r.j.89@gmail.com
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
6 * @site <https://github.com/howerj/q>
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
7 *
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
8 * This file contains a wrapper for testing the Q Number library,
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
9 * it includes a command processor and some built in tests. View
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
10 * the help string later on for more information */
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
11 #include "q.h"
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
12 #include <assert.h>
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
13 #include <ctype.h>
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
14 #include <errno.h>
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
15 #include <stdbool.h>
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
16 #include <stdio.h>
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
17 #include <stdlib.h>
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
18 #include <string.h>
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
19
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
20 #define N (16)
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
21 #define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)]))
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
22
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
23 static int qprint(FILE *out, const q_t p) {
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
24 assert(out);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
25 char buf[64 + 1] = { 0, };
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
26 const int r = qsprint(p, buf, sizeof buf);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
27 return r < 0 ? r : fprintf(out, "%s", buf);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
28 }
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
29
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
30 static int printq(FILE *out, q_t q, const char *msg) {
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
31 assert(out);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
32 assert(msg);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
33 if (fprintf(out, "%s = ", msg) < 0)
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
34 return -1;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
35 if (qprint(out, q) < 0)
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
36 return -1;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
37 if (fputc('\n', out) != '\n')
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
38 return -1;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
39 return 0;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
40 }
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
41
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
42 static int print_sincos(FILE *out, const q_t theta) {
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
43 assert(out);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
44 q_t sine = qinfo.zero, cosine = qinfo.zero;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
45 qsincos(theta, &sine, &cosine);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
46 if (qprint(out, theta) < 0)
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
47 return -1;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
48 if (fputc(',', out) != ',')
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
49 return -1;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
50 if (qprint(out, sine) < 0)
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
51 return -1;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
52 if (fputc(',', out) != ',')
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
53 return -1;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
54 if (qprint(out, cosine) < 0)
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
55 return -1;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
56 if (fputc('\n', out) != '\n')
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
57 return -1;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
58 return 0;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
59 }
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
60
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
61 static int print_sincos_table(FILE *out) {
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
62 assert(out);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
63 const q_t tpi = qdiv(qinfo.pi, qint(20));
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
64 const q_t end = qmul(qinfo.pi, qint(2));
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
65 const q_t start = qnegate(end);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
66 if (fprintf(out, "theta,sine,cosine\n") < 0)
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
67 return -1;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
68 for (q_t i = start; qless(i, end); i = qadd(i, tpi))
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
69 if (print_sincos(out, i) < 0)
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
70 return -1;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
71 return 0;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
72 }
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
73
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
74 static int qinfo_print(FILE *out, const qinfo_t *qi) {
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
75 assert(out);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
76 assert(qi);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
77 if (fprintf(out, "Q%u.%u Info\n", (unsigned)qi->whole, (unsigned)qi->fractional) < 0) return -1;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
78 if (printq(out, qi->bit, "bit") < 0) return -1;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
79 if (printq(out, qi->one, "one") < 0) return -1;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
80 if (printq(out, qi->zero, "zero") < 0) return -1;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
81 if (printq(out, qi->pi, "pi") < 0) return -1;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
82 if (printq(out, qi->e, "e") < 0) return -1;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
83 if (printq(out, qi->sqrt2, "sqrt2") < 0) return -1;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
84 if (printq(out, qi->sqrt3, "sqrt3") < 0) return -1;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
85 if (printq(out, qi->ln2, "ln2") < 0) return -1;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
86 if (printq(out, qi->ln10, "ln10") < 0) return -1;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
87 if (printq(out, qi->min, "min") < 0) return -1;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
88 if (printq(out, qi->max, "max") < 0) return -1;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
89 if (printq(out, qcordic_circular_gain(-1), "circular-gain") < 0) return -1;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
90 if (printq(out, qcordic_hyperbolic_gain(-1), "hyperbolic-gain") < 0) return -1;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
91 return 0;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
92 }
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
93
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
94 static int qconf_print(FILE *out, const qconf_t *qc) {
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
95 assert(out);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
96 assert(qc);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
97 if (fprintf(out, "Q Configuration\n") < 0) return -1;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
98 const char *bounds = "unknown";
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
99 qbounds_t bound = qc->bound;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
100 if (bound == qbound_saturate)
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
101 bounds = "saturate";
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
102 if (bound == qbound_wrap)
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
103 bounds = "wrap";
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
104 if (fprintf(out, "overflow handler: %s\n", bounds) < 0) return -1;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
105 if (fprintf(out, "input/output radix: %u (0 = special case)\n", qc->base) < 0) return -1;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
106 if (fprintf(out, "decimal places: %d\n", qc->dp) < 0) return -1;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
107 return 0;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
108 }
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
109
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
110 static FILE *fopen_or_die(const char *file, const char *mode) {
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
111 assert(file && mode);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
112 FILE *h = NULL;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
113 errno = 0;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
114 if (!(h = fopen(file, mode))) {
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
115 (void)fprintf(stderr, "file open \"%s\" (mode %s) failed: %s\n", file, mode, strerror(errno));
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
116 exit(EXIT_FAILURE);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
117 }
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
118 return h;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
119 }
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
120
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
121 typedef enum {
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
122 EVAL_OK_E,
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
123 EVAL_COMMENT_E,
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
124 EVAL_ERROR_SCAN_E,
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
125 EVAL_ERROR_TYPE_E,
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
126 EVAL_ERROR_CONVERT_E,
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
127 EVAL_ERROR_OPERATION_E,
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
128 EVAL_ERROR_ARG_COUNT_E,
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
129 EVAL_ERROR_UNEXPECTED_RESULT_E,
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
130 EVAL_ERROR_LIMIT_MODE_E,
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
131
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
132 EVAL_ERROR_MAX_ERRORS_E, /**< not an error, but a count of errors */
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
133 } eval_errors_e;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
134
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
135 static const char *eval_error(int e) {
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
136 if (e < 0 || e >= EVAL_ERROR_MAX_ERRORS_E)
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
137 return "unknown";
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
138 const char *msgs[EVAL_ERROR_MAX_ERRORS_E] = {
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
139 [EVAL_OK_E] = "ok",
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
140 [EVAL_COMMENT_E] = "(comment)",
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
141 [EVAL_ERROR_SCAN_E] = "invalid input line",
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
142 [EVAL_ERROR_TYPE_E] = "unknown function type",
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
143 [EVAL_ERROR_CONVERT_E] = "numeric conversion failed",
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
144 [EVAL_ERROR_OPERATION_E] = "unknown operation",
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
145 [EVAL_ERROR_ARG_COUNT_E] = "incorrect argument count",
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
146 [EVAL_ERROR_LIMIT_MODE_E] = "unknown limit mode ('|' or '%' allowed)",
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
147 [EVAL_ERROR_UNEXPECTED_RESULT_E] = "unexpected result",
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
148 };
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
149 return msgs[e] ? msgs[e] : "unknown";
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
150 }
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
151
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
152 static int eval_unary_arith(q_t (*m)(q_t), q_t expected, q_t bound, q_t arg1, q_t *result) {
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
153 assert(m);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
154 assert(result);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
155 const q_t r = m(arg1);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
156 *result = r;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
157 if (qwithin_interval(r, expected, bound))
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
158 return 0;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
159 return -1;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
160 }
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
161
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
162 static int eval_binary_arith(q_t (*f)(q_t, q_t), q_t expected, q_t bound, q_t arg1, q_t arg2, q_t *result) {
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
163 assert(f);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
164 assert(result);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
165 const q_t r = f(arg1, arg2);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
166 *result = r;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
167 if (qwithin_interval(r, expected, bound))
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
168 return 0;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
169 return -1;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
170 }
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
171
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
172 static int comment(char *line) {
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
173 assert(line);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
174 const size_t length = strlen(line);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
175 for (size_t i = 0; i < length; i++) {
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
176 if (line[i] == '#')
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
177 return 1;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
178 if (!isspace(line[i]))
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
179 break;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
180 }
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
181 for (size_t i = 0; i < length; i++) {
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
182 if (line[i] == '#') {
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
183 line[i] = 0;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
184 return 0;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
185 }
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
186 }
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
187 return 0;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
188 }
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
189
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
190 static void bounds_set(char method) {
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
191 assert(method == '|' || method == '%');
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
192 if (method == '|')
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
193 qconf.bound = qbound_saturate;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
194 qconf.bound = qbound_wrap;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
195 }
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
196
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
197 static int eval(char *line, q_t *result) {
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
198 assert(line);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
199 assert(result);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
200 *result = qinfo.zero;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
201 if (comment(line))
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
202 return EVAL_COMMENT_E;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
203 char operation[N] = { 0 }, expected[N] = { 0 }, bounds[N], arg1[N] = { 0 }, arg2[N] = { 0 };
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
204 char limit = '|';
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
205 const int count = sscanf(line, "%15s %15s +- %15s %c %15s %15s", operation, expected, bounds, &limit, arg1, arg2);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
206 if (limit != '|' && limit != '%')
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
207 return -EVAL_ERROR_LIMIT_MODE_E;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
208 bounds_set(limit);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
209 if (count < 5)
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
210 return -EVAL_ERROR_SCAN_E;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
211 const qoperations_t *func = qop(operation);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
212 if (!func)
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
213 return -EVAL_ERROR_OPERATION_E;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
214 q_t e = qinfo.zero, b = qinfo.zero, a1 = qinfo.zero, a2 = qinfo.zero;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
215 const int argc = count - 4;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
216 if (func->arity != argc)
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
217 return -EVAL_ERROR_ARG_COUNT_E;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
218 if (qconv(&e, expected) < 0)
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
219 return -EVAL_ERROR_CONVERT_E;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
220 if (qconv(&b, bounds) < 0)
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
221 return -EVAL_ERROR_CONVERT_E;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
222 if (qconv(&a1, arg1) < 0)
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
223 return -EVAL_ERROR_CONVERT_E;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
224 switch (func->arity) {
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
225 case 1: if (eval_unary_arith(func->eval.unary, e, b, a1, result) < 0)
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
226 return -EVAL_ERROR_UNEXPECTED_RESULT_E;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
227 break;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
228 case 2: if (qconv(&a2, arg2) < 0)
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
229 return -EVAL_ERROR_CONVERT_E;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
230 if (eval_binary_arith(func->eval.binary, e, b, a1, a2, result) < 0)
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
231 return -EVAL_ERROR_UNEXPECTED_RESULT_E;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
232 break;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
233 default:
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
234 return -EVAL_ERROR_TYPE_E;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
235 }
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
236 return EVAL_OK_E;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
237 }
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
238
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
239 static void trim(char *s) {
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
240 assert(s);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
241 const int size = strlen(s);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
242 for (int i = size - 1; i >= 0; i--) {
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
243 if (!isspace(s[i]))
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
244 break;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
245 s[i] = 0;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
246 }
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
247 }
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
248
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
249 static int eval_file(FILE *input, FILE *output) {
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
250 assert(input);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
251 assert(output);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
252 char line[256] = { 0 };
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
253 int rv = 0;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
254 while (fgets(line, sizeof(line) - 1, input)) {
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
255 q_t result = 0;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
256 const int r = eval(line, &result);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
257 if (r == EVAL_COMMENT_E)
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
258 continue;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
259 if (r < 0) {
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
260 const char *msg = eval_error(-r);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
261 trim(line);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
262 if (fprintf(output, "error: %s = ", line) < 0) return -1;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
263 if (qprint(output, result) < 0) return -1;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
264 if (fprintf(output, " : %s/%d\n", msg, r) < 0) return -1;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
265 rv = -1;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
266 continue;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
267 }
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
268 trim(line);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
269 char rstring[64 + 1] = { 0, };
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
270 if (qsprint(result, rstring, sizeof(rstring) - 1) < 0) return -1;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
271 if (fprintf(output, "ok: %s | (%s)\n", line, rstring) < 0) return -1;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
272 memset(line, 0, sizeof line);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
273 }
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
274 return rv;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
275 }
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
276
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
277 /* --- Unit Test Framework --- */
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
278
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
279 typedef struct {
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
280 unsigned passed,
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
281 run;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
282 } unit_test_t;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
283
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
284 static inline unit_test_t _unit_test_start(const char *file, const char *func, unsigned line) {
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
285 assert(file);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
286 assert(func);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
287 unit_test_t t = { .run = 0, .passed = 0 };
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
288 fprintf(stdout, "Start tests: %s in %s:%u\n\n", func, file, line);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
289 return t;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
290 }
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
291
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
292 static inline void _unit_test_statement(const char *expr_str) {
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
293 assert(expr_str);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
294 if (fprintf(stdout, " STATE: %s\n", expr_str) < 0)
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
295 abort();
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
296 }
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
297
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
298 static inline void _unit_test(unit_test_t *t, int failed, const char *expr_str, const char *file, const char *func, unsigned line, int die) {
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
299 assert(t);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
300 assert(expr_str);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
301 assert(file);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
302 assert(func);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
303 if (failed) {
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
304 fprintf(stdout, " FAILED: %s (%s:%s:%u)\n", expr_str, file, func, line);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
305 if (die) {
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
306 fputs("VERIFY FAILED - EXITING\n", stdout);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
307 exit(EXIT_FAILURE);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
308 }
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
309 } else {
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
310 fprintf(stdout, " OK: %s\n", expr_str);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
311 t->passed++;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
312 }
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
313 t->run++;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
314 }
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
315
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
316 static inline int unit_test_finish(unit_test_t *t) {
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
317 assert(t);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
318 fprintf(stdout, "Tests passed/total: %u/%u\n", t->passed, t->run);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
319 if (t->run != t->passed) {
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
320 (void)fputs("[FAILED]\n", stdout);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
321 return -1;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
322 }
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
323 if (fputs("[SUCCESS]\n", stdout) < 0)
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
324 return -1;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
325 return 0;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
326 }
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
327
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
328 #define unit_test_statement(T, EXPR) do { (void)(T); EXPR; _unit_test_statement(( #EXPR)); } while (0)
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
329 #define unit_test_start() _unit_test_start(__FILE__, __func__, __LINE__)
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
330 #define unit_test(T, EXPR) _unit_test((T), 0 == (EXPR), (# EXPR), __FILE__, __func__, __LINE__, 0)
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
331 #define unit_test_verify(T, EXPR) _unit_test((T), 0 == (EXPR), (# EXPR), __FILE__, __func__, __LINE__, 1)
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
332
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
333 static int test_sanity(void) {
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
334 unit_test_t t = unit_test_start();
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
335 q_t t1 = 0, t2 = 0;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
336 unit_test_statement(&t, t1 = qint(1));
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
337 unit_test_statement(&t, t2 = qint(2));
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
338 unit_test(&t, qtoi(qadd(t1, t2)) == 3);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
339 return unit_test_finish(&t);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
340 }
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
341
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
342 static int test_pack(void) {
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
343 unit_test_t t = unit_test_start();
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
344 q_t p1 = 0, p2 = 0;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
345 char buf[sizeof(p1)] = { 0 };
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
346 unit_test_statement(&t, p1 = qnegate(qinfo.pi));
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
347 unit_test_statement(&t, p2 = 0);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
348 unit_test(&t, qunequal(p1, p2));
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
349 unit_test(&t, qpack(&p1, buf, sizeof p1 - 1) < 0);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
350 unit_test(&t, qpack(&p1, buf, sizeof buf) == sizeof(p1));
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
351 unit_test(&t, qunpack(&p2, buf, sizeof buf) == sizeof(p2));
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
352 unit_test(&t, qequal(p1, p2));
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
353 return unit_test_finish(&t);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
354 }
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
355
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
356 static int test_fma(void) {
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
357 unit_test_t t = unit_test_start();
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
358
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
359 q_t a, b, c, r;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
360 const q_t one_and_a_half = qdiv(qint(3), qint(2));
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
361
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
362 /* incorrect, but expected, result due to saturation */
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
363 unit_test_statement(&t, a = qinfo.max);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
364 unit_test_statement(&t, b = one_and_a_half);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
365 unit_test_statement(&t, c = qinfo.min);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
366 unit_test_statement(&t, r = qadd(qmul(a, b), c));
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
367 unit_test(&t, qwithin_interval(r, qint(0), qint(1)));
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
368
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
369 /* correct result using Fused Multiply Add */
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
370 unit_test_statement(&t, a = qinfo.max);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
371 unit_test_statement(&t, b = one_and_a_half);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
372 unit_test_statement(&t, c = qinfo.min);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
373 unit_test_statement(&t, r = qfma(a, b, c));
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
374 unit_test(&t, qwithin_interval(r, qdiv(qinfo.max, qint(2)), qint(1)));
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
375
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
376 return unit_test_finish(&t);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
377 }
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
378
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
379 static inline int test_filter(void) {
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
380 unit_test_t t = unit_test_start();
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
381 qfilter_t lpf = { .raw = 0 }, hpf = { .raw = 0 };
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
382 const q_t beta = qdiv(qint(1), qint(3));
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
383 qfilter_init(&lpf, qint(0), beta, qint(0));
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
384 qfilter_init(&hpf, qint(0), beta, qint(0));
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
385 for (int i = 0; i < 100; i++) {
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
386 char low[64 + 1] = { 0, }, high[64 + 1] = { 0, };
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
387 const q_t step = qdiv(qint(i), qint(100));
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
388 const q_t input = qint(1);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
389 qfilter_low_pass(&lpf, step, input);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
390 qfilter_high_pass(&hpf, step, input);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
391 if (qsprint(qfilter_value(&lpf), low, sizeof(low) - 1ull) < 0) return -1;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
392 if (qsprint(qfilter_value(&hpf), high, sizeof(high) - 1ull) < 0) return -1;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
393 if (fprintf(stdout, "%2d: %s\t%s\n", i, low, high) < 0) return -1;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
394 }
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
395 return unit_test_finish(&t);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
396 }
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
397
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
398 static int qmatrix_print(FILE *out, const q_t *m) {
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
399 assert(out);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
400 assert(m);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
401 const size_t alloc = qmatrix_string_length(m);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
402 char *ms = malloc(alloc + 1);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
403 if (!ms)
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
404 return -1;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
405 int r = qmatrix_sprintb(m, ms, alloc + 1, 10);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
406 if (r >= 0)
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
407 r = fprintf(out, "%s\n", ms);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
408 free(ms);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
409 return r;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
410 }
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
411
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
412 #define QMATRIX(ROW, COLUMN, ...) { 0, ROW * COLUMN, ROW, COLUMN, __VA_ARGS__ }
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
413 #define QMATRIXZ(ROW, COLUMN) QMATRIX((ROW), (COLUMN), 0)
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
414 #define QMATRIXSZ(ROW, COLUMN) ((((ROW)*(COLUMN)) + 4)*sizeof(q_t))
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
415
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
416 static int test_matrix(void) {
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
417 unit_test_t t = unit_test_start();
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
418 FILE *out = stdout;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
419 q_t a[] = QMATRIX(2, 3,
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
420 QINT(1), QINT(2), QINT(3),
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
421 QINT(4), QINT(5), QINT(6),
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
422 );
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
423 q_t b[] = QMATRIX(3, 2,
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
424 QINT(2), QINT(3),
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
425 QINT(4), QINT(5),
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
426 QINT(6), QINT(7),
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
427 );
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
428 const q_t abr[] = QMATRIX(2, 2,
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
429 QINT(28), QINT(34),
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
430 QINT(64), QINT(79),
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
431 );
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
432 const q_t abrp[] = QMATRIX(2, 2,
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
433 QINT(28), QINT(64),
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
434 QINT(34), QINT(79),
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
435 );
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
436 q_t ab[QMATRIXSZ(2, 2)] = QMATRIXZ(2, 2);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
437 q_t abp[QMATRIXSZ(2, 2)] = QMATRIXZ(2, 2);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
438 unit_test_verify(&t, 0 == qmatrix_mul(ab, a, b));
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
439 unit_test_verify(&t, 0 == qmatrix_transpose(abp, ab));
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
440 unit_test(&t, qmatrix_equal(ab, abr));
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
441 unit_test(&t, qmatrix_equal(ab, abrp));
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
442 qmatrix_print(out, a);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
443 qmatrix_print(out, b);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
444 qmatrix_print(out, ab);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
445 qmatrix_print(out, abp);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
446 return unit_test_finish(&t);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
447 }
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
448
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
449 static int test_matrix_trace(void) {
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
450 unit_test_t t = unit_test_start();
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
451 q_t a[] = QMATRIX(2, 2,
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
452 QINT(1), QINT(2),
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
453 QINT(4), QINT(5),
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
454 );
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
455 q_t b[] = QMATRIX(2, 2,
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
456 QINT(2), QINT(3),
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
457 QINT(4), QINT(5),
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
458 );
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
459 q_t ta[sizeof(a) / sizeof(a[0])] = QMATRIX(2, 2, 0);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
460 q_t tb[sizeof(b) / sizeof(b[0])] = QMATRIX(2, 2, 0);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
461 q_t apb[sizeof(a) / sizeof(a[0])] = QMATRIX(2, 2, 0);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
462 BUILD_BUG_ON(sizeof a != sizeof ta);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
463 BUILD_BUG_ON(sizeof a != sizeof tb);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
464 BUILD_BUG_ON(sizeof a != sizeof b);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
465 BUILD_BUG_ON(sizeof a != sizeof apb);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
466 unit_test_verify(&t, 0 == qmatrix_transpose(ta, a));
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
467 unit_test_verify(&t, 0 == qmatrix_transpose(tb, b));
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
468 unit_test_verify(&t, 0 == qmatrix_add(apb, a, b));
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
469 unit_test(&t, qequal(qmatrix_trace(a), QINT(6)));
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
470 unit_test(&t, qequal(qmatrix_trace(b), QINT(7)));
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
471 unit_test(&t, qequal(qmatrix_trace(a), qmatrix_trace(ta)));
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
472 unit_test(&t, qequal(qmatrix_trace(apb), qadd(qmatrix_trace(a), qmatrix_trace(b))));
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
473 printq(stdout, qmatrix_determinant(a), "det(a)");
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
474 return unit_test_finish(&t);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
475 }
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
476
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
477 static q_t qid(q_t x) { return x; }
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
478 static q_t qsq(q_t x) { return qmul(x, x); }
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
479
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
480 static int test_simpson(void) {
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
481 unit_test_t t = unit_test_start();
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
482 unit_test(&t, qwithin_interval(qsimpson(qid, QINT(0), QINT(10), 100), QINT(50), QINT(1))); // (x^2)/2 + C
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
483 unit_test(&t, qwithin_interval(qsimpson(qsq, qnegate(QINT(2)), QINT(5), 100), QINT(44), QINT(1))); // (x^3)/3 + C
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
484 return unit_test_finish(&t);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
485 }
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
486
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
487 static int internal_tests(void) {
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
488 typedef int (*unit_test_t)(void);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
489 unit_test_t tests[] = {
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
490 test_sanity,
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
491 test_pack,
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
492 test_fma,
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
493 // test_filter,
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
494 test_matrix,
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
495 test_matrix_trace,
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
496 test_simpson,
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
497 NULL
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
498 };
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
499 for (size_t i = 0; tests[i]; i++)
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
500 if (tests[i]() < 0)
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
501 return -1;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
502 return 0;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
503 }
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
504
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
505 static int help(FILE *out, const char *arg0) {
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
506 assert(out);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
507 assert(arg0);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
508 const char *h = "\n\
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
509 Program: Q-Number (Q16.16, signed) library testbench\n\
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
510 Author: Richard James Howe (2018)\n\
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
511 License: MIT\n\
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
512 E-mail: howe.r.j.89@gmail.com\n\
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
513 Site: https://github.com/howerj/q\n\n\
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
514 Options:\n\
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
515 \t-s\tprint a sine-cosine table\n\
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
516 \t-h\tprint this help message and exit\n\
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
517 \t-i\tprint library information\n\
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
518 \t-t\trun internal unit tests\n\
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
519 \t-v\tprint version information and exit\n\
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
520 \tfile\texecute commands in file\n\n\
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
521 This program wraps up a Q-Number library and allows it to be tested by\n\
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
522 giving it commands, either from stdin, or from a file. The format is\n\
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
523 strict and the parser primitive, but it is only meant to be used to\n\
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
524 test that the library is doing the correct thing and not as a\n\
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
525 calculator.\n\n\
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
526 Commands evaluated consist of an operator with the require arguments\n\
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
527 (either one or two arguments) and compare the result with an expected\n\
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
528 value, which can within a specified bounds for the test to pass. If\n\
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
529 the test fails the program exits, indicating failure. The format is:\n\
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
530 \n\
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
531 \toperator expected +- allowance | arg1 arg2\n\n\
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
532 operators include '+', '-', '/', 'rem', '<', which require two\n\
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
533 arguments, and unary operators like 'sin', and 'negate', which require\n\
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
534 only one. 'expected', 'allowance', 'arg1' and 'arg2' are all fixed\n\
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
535 numbers of the form '-12.45'. 'expected' is the expected result,\n\
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
536 'allowance' the +/- amount the result is allowed to deviated by, and\n\
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
537 'arg1' and 'arg2' the operator arguments.\n\
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
538 \n\n";
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
539 if (fprintf(out, "usage: %s -h -s -i -v -t -c file\n", arg0) < 0) return -1;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
540 if (fputs(h, out) < 0) return -1;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
541 return 0;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
542 }
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
543
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
544 int main(int argc, char **argv) {
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
545 bool ran = false;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
546 for (int i = 1; i < argc; i++) {
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
547 if (!strcmp("-h", argv[i])) {
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
548 if (help(stdout, argv[0]) < 0)
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
549 return 1;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
550 return 0;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
551 } else if (!strcmp("-s", argv[i])) {
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
552 print_sincos_table(stdout);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
553 ran = true;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
554 } else if (!strcmp("-v", argv[i])) {
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
555 fprintf(stdout, "version 1.0\n");
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
556 return 0;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
557 } else if (!strcmp("-t", argv[i])) {
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
558 if (internal_tests() < 0)
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
559 return 1;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
560 ran = true;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
561 } else if (!strcmp("-i", argv[i])) {
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
562 if (qinfo_print(stdout, &qinfo) < 0)
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
563 return 1;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
564 if (qconf_print(stdout, &qconf) < 0)
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
565 return 1;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
566 ran = true;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
567 } else {
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
568 FILE *input = fopen_or_die(argv[i], "rb");
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
569 FILE *output = stdout;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
570 const int r = eval_file(input, output);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
571 ran = true;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
572 fclose(input);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
573 if (r < 0)
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
574 return 1;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
575 }
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
576 }
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
577 if (!ran)
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
578 return eval_file(stdin, stdout);
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
579 return 0;
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
580 }
388074ff9474 Add fixed point code
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
581