tests: print error locations verbosely
[minix.git] / test / test53.c
blob67794aed04458a4bdff22509bb8051796c84ef25
1 #include <assert.h>
2 #include <minix/u64.h>
3 #include <setjmp.h>
4 #include <signal.h>
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <sys/time.h>
8 #include <unistd.h>
10 #define ERR err(__LINE__)
11 #define MAX_ERROR 4
12 #define TIMED 0
14 #include "common.c"
16 static volatile int expect_SIGFPE;
17 static u64_t i, j, k;
18 static jmp_buf jmpbuf_SIGFPE, jmpbuf_main;
20 static void err(int line)
22 /* print error information */
23 printf("error line %d; i=0x%.8lx%.8lx; j=0x%.8lx%.8lx; k=0x%.8lx%.8lx\n",
24 line,
25 ex64hi(i), ex64lo(i),
26 ex64hi(j), ex64lo(j),
27 ex64hi(k), ex64lo(k));
29 /* quit after too many errors */
30 if (errct++ > MAX_ERROR) {
31 printf("Too many errors; test aborted\n");
32 quit();
36 #define LENGTHOF(arr) (sizeof(arr) / sizeof(arr[0]))
38 static u64_t getargval(int index, int *done)
40 u32_t values[] = {
41 /* corner cases */
42 0,
44 0x7fffffff,
45 0x80000000,
46 0x80000001,
47 0xffffffff,
48 /* random values */
49 0xa9,
50 0x0d88,
51 0x242811,
52 0xeb44d1bc,
53 0x5b,
54 0xfb50,
55 0x569c02,
56 0xb23c8f7d,
57 0xc3,
58 0x2366,
59 0xfabb73,
60 0xcb4e8aef,
61 0xe9,
62 0xffdc,
63 0x05842d,
64 0x3fff902d};
66 assert(done);
68 /* values with corner case and random 32-bit components */
69 if (index < LENGTHOF(values) * LENGTHOF(values))
70 return make64(values[index / LENGTHOF(values)], values[index % LENGTHOF(values)]);
72 index -= LENGTHOF(values) * LENGTHOF(values);
74 /* small numbers */
75 if (index < 16) return make64(index + 2, 0);
76 index -= 16;
78 /* big numbers */
79 if (index < 16) return make64(-index - 2, -1);
80 index -= 16;
82 /* powers of two */
83 if (index < 14) return make64(1 << (index * 2 + 5), 0);
84 index -= 14;
85 if (index < 16) return make64(0, 1 << (index * 2 + 1));
86 index -= 16;
88 /* done */
89 *done = 1;
90 return make64(0, 0);
93 static void handler_SIGFPE(int signum)
95 assert(signum == SIGFPE);
97 /* restore the signal handler */
98 if (signal(SIGFPE, handler_SIGFPE) == SIG_ERR) ERR;
100 /* division by zero occurred, was this expected? */
101 if (expect_SIGFPE) {
102 /* expected: jump back to test */
103 expect_SIGFPE = 0;
104 longjmp(jmpbuf_SIGFPE, -1);
105 } else {
106 /* not expected: error and jump back to main */
107 longjmp(jmpbuf_main, -1);
110 /* not reachable */
111 assert(0);
112 exit(-1);
115 static void testmul(void)
117 int kdone, kidx;
118 u32_t ilo = ex64lo(i), jlo = ex64lo(j);
119 u64_t prod = mul64(i, j);
120 int prodbits;
122 /* compute maximum index of highest-order bit */
123 prodbits = bsr64(i) + bsr64(j) + 1;
124 if (cmp64u(i, 0) == 0 || cmp64u(j, 0) == 0) prodbits = -1;
125 if (bsr64(prod) > prodbits) ERR;
127 /* compare to 32-bit multiplication if possible */
128 if (ex64hi(i) == 0 && ex64hi(j) == 0) {
129 if (cmp64(prod, mul64u(ilo, jlo)) != 0) ERR;
131 /* if there is no overflow we can check against pure 32-bit */
132 if (prodbits < 32 && cmp64u(prod, ilo * jlo) != 0) ERR;
135 /* in 32-bit arith low-order DWORD matches regardless of overflow */
136 if (ex64lo(prod) != ilo * jlo) ERR;
138 /* multiplication by zero yields zero */
139 if (prodbits < 0 && cmp64u(prod, 0) != 0) ERR;
141 /* if there is no overflow, check absence of zero divisors */
142 if (prodbits >= 0 && prodbits < 64 && cmp64u(prod, 0) == 0) ERR;
144 /* commutativity */
145 if (cmp64(prod, mul64(j, i)) != 0) ERR;
147 /* loop though all argument value combinations for third argument */
148 for (kdone = 0, kidx = 0; k = getargval(kidx, &kdone), !kdone; kidx++) {
149 /* associativity */
150 if (cmp64(mul64(mul64(i, j), k), mul64(i, mul64(j, k))) != 0) ERR;
152 /* left and right distributivity */
153 if (cmp64(mul64(add64(i, j), k), add64(mul64(i, k), mul64(j, k))) != 0) ERR;
154 if (cmp64(mul64(i, add64(j, k)), add64(mul64(i, j), mul64(i, k))) != 0) ERR;
158 static void testdiv0(void)
160 int funcidx;
162 assert(cmp64u(j, 0) == 0);
164 /* loop through the 5 different division functions */
165 for (funcidx = 0; funcidx < 5; funcidx++) {
166 expect_SIGFPE = 1;
167 if (setjmp(jmpbuf_SIGFPE) == 0) {
168 /* divide by zero using various functions */
169 switch (funcidx) {
170 case 0: div64(i, j); ERR; break;
171 case 1: div64u64(i, ex64lo(j)); ERR; break;
172 case 2: div64u(i, ex64lo(j)); ERR; break;
173 case 3: rem64(i, j); ERR; break;
174 case 4: rem64u(i, ex64lo(j)); ERR; break;
175 default: assert(0); ERR; break;
178 /* if we reach this point there was no signal and an
179 * error has been recorded
181 expect_SIGFPE = 0;
182 } else {
183 /* a signal has been received and expect_SIGFPE has
184 * been reset; all is ok now
186 assert(!expect_SIGFPE);
191 static void testdiv(void)
193 u64_t q, r;
194 #if TIMED
195 struct timeval tvstart, tvend;
197 printf("i=0x%.8x%.8x; j=0x%.8x%.8x\n",
198 ex64hi(i), ex64lo(i),
199 ex64hi(j), ex64lo(j));
200 fflush(stdout);
201 if (gettimeofday(&tvstart, NULL) < 0) ERR;
202 #endif
204 /* division by zero has a separate test */
205 if (cmp64u(j, 0) == 0) {
206 testdiv0();
207 return;
210 /* perform division, store q in k to make ERR more informative */
211 q = div64(i, j);
212 r = rem64(i, j);
213 k = q;
215 #if TIMED
216 if (gettimeofday(&tvend, NULL) < 0) ERR;
217 tvend.tv_sec -= tvstart.tv_sec;
218 tvend.tv_usec -= tvstart.tv_usec;
219 if (tvend.tv_usec < 0) {
220 tvend.tv_sec -= 1;
221 tvend.tv_usec += 1000000;
223 printf("q=0x%.8x%.8x; r=0x%.8x%.8x; time=%d.%.6d\n",
224 ex64hi(q), ex64lo(q),
225 ex64hi(r), ex64lo(r),
226 tvend.tv_sec, tvend.tv_usec);
227 fflush(stdout);
228 #endif
230 /* compare to 64/32-bit division if possible */
231 if (!ex64hi(j)) {
232 if (cmp64(q, div64u64(i, ex64lo(j))) != 0) ERR;
233 if (!ex64hi(q)) {
234 if (cmp64u(q, div64u(i, ex64lo(j))) != 0) ERR;
236 if (cmp64u(r, rem64u(i, ex64lo(j))) != 0) ERR;
238 /* compare to 32-bit division if possible */
239 if (!ex64hi(i)) {
240 if (cmp64u(q, ex64lo(i) / ex64lo(j)) != 0) ERR;
241 if (cmp64u(r, ex64lo(i) % ex64lo(j)) != 0) ERR;
245 /* check results using i = q j + r and r < j */
246 if (cmp64(i, add64(mul64(q, j), r)) != 0) ERR;
247 if (cmp64(r, j) >= 0) ERR;
250 static void test(void)
252 int idone, jdone, iidx, jidx;
254 /* loop though all argument value combinations */
255 for (idone = 0, iidx = 0; i = getargval(iidx, &idone), !idone; iidx++)
256 for (jdone = 0, jidx = 0; j = getargval(jidx, &jdone), !jdone; jidx++) {
257 testmul();
258 testdiv();
262 int main(void)
264 start(53);
266 /* set up signal handler to deal with div by zero */
267 if (setjmp(jmpbuf_main) == 0) {
268 if (signal(SIGFPE, handler_SIGFPE) == SIG_ERR) ERR;
270 /* perform tests */
271 test();
272 } else {
273 /* an unexpected SIGFPE has occurred */
274 ERR;
277 /* this was all */
278 quit();
280 return(-1); /* Unreachable */