Remove building with NOCRYPTO option
[minix.git] / minix / tests / test53.c
blob672d209317673b6af6625e6959faba8cc5471238
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 int max_error = 4;
12 #include "common.h"
14 #define TIMED 0
17 static volatile int expect_SIGFPE;
18 static u64_t i, j, k;
19 static jmp_buf jmpbuf_SIGFPE, jmpbuf_main;
21 static void err(int line)
23 /* print error information */
24 printf("error line %d; i=0x%.8lx%.8lx; j=0x%.8lx%.8lx; k=0x%.8lx%.8lx\n",
25 line,
26 ex64hi(i), ex64lo(i),
27 ex64hi(j), ex64lo(j),
28 ex64hi(k), ex64lo(k));
30 /* quit after too many errors */
31 e(7);
34 #define LENGTHOF(arr) (sizeof(arr) / sizeof(arr[0]))
36 static u64_t getargval(int index, int *done)
38 u32_t values[] = {
39 /* corner cases */
40 0,
42 0x7fffffff,
43 0x80000000,
44 0x80000001,
45 0xffffffff,
46 /* random values */
47 0xa9,
48 0x0d88,
49 0x242811,
50 0xeb44d1bc,
51 0x5b,
52 0xfb50,
53 0x569c02,
54 0xb23c8f7d,
55 0xc3,
56 0x2366,
57 0xfabb73,
58 0xcb4e8aef,
59 0xe9,
60 0xffdc,
61 0x05842d,
62 0x3fff902d};
64 assert(done);
66 /* values with corner case and random 32-bit components */
67 if (index < LENGTHOF(values) * LENGTHOF(values))
68 return make64(values[index / LENGTHOF(values)], values[index % LENGTHOF(values)]);
70 index -= LENGTHOF(values) * LENGTHOF(values);
72 /* small numbers */
73 if (index < 16) return make64(index + 2, 0);
74 index -= 16;
76 /* big numbers */
77 if (index < 16) return make64(-index - 2, -1);
78 index -= 16;
80 /* powers of two */
81 if (index < 14) return make64(1 << (index * 2 + 5), 0);
82 index -= 14;
83 if (index < 16) return make64(0, 1 << (index * 2 + 1));
84 index -= 16;
86 /* done */
87 *done = 1;
88 return make64(0, 0);
91 static void handler_SIGFPE(int signum)
93 assert(signum == SIGFPE);
95 /* restore the signal handler */
96 if (signal(SIGFPE, handler_SIGFPE) == SIG_ERR) ERR;
98 /* division by zero occurred, was this expected? */
99 if (expect_SIGFPE) {
100 /* expected: jump back to test */
101 expect_SIGFPE = 0;
102 longjmp(jmpbuf_SIGFPE, -1);
103 } else {
104 /* not expected: error and jump back to main */
105 longjmp(jmpbuf_main, -1);
108 /* not reachable */
109 assert(0);
110 exit(-1);
113 static inline int bsr64(u64_t i)
115 int index;
116 u64_t mask;
118 for (index = 63, mask = 1ULL << 63; index >= 0; --index, mask >>= 1) {
119 if (i & mask)
120 return index;
123 return -1;
126 static void testmul(void)
128 int kdone, kidx;
129 u32_t ilo = ex64lo(i), jlo = ex64lo(j);
130 u64_t prod = i * j;
131 int prodbits;
133 /* compute maximum index of highest-order bit */
134 prodbits = bsr64(i) + bsr64(j) + 1;
135 if (i == 0 || j == 0) prodbits = -1;
136 if (bsr64(prod) > prodbits) ERR;
138 /* compare to 32-bit multiplication if possible */
139 if (ex64hi(i) == 0 && ex64hi(j) == 0) {
140 if (prod != (u64_t)ilo * jlo) ERR;
142 /* if there is no overflow we can check against pure 32-bit */
143 if (prodbits < 32 && prod != ilo * jlo) ERR;
146 /* in 32-bit arith low-order DWORD matches regardless of overflow */
147 if (ex64lo(prod) != ilo * jlo) ERR;
149 /* multiplication by zero yields zero */
150 if (prodbits < 0 && prod != 0) ERR;
152 /* if there is no overflow, check absence of zero divisors */
153 if (prodbits >= 0 && prodbits < 64 && prod == 0) ERR;
155 /* commutativity */
156 if (prod != j * i) ERR;
158 /* loop though all argument value combinations for third argument */
159 for (kdone = 0, kidx = 0; k = getargval(kidx, &kdone), !kdone; kidx++) {
160 /* associativity */
161 if ((i * j) * k != i * (j * k)) ERR;
163 /* left and right distributivity */
164 if ((i + j) * k != (i * k) + (j * k)) ERR;
165 if (i * (j + k) != (i * j) + (i * k)) ERR;
169 static void do_not_optimize_away(volatile u64_t * ptr)
172 /* TODO: does this actually do the job? */
173 *ptr ^= 1;
176 static void testdiv0(void)
178 int funcidx;
179 u64_t res;
181 assert(j == 0);
183 /* loop through the 5 different division functions */
184 for (funcidx = 0; funcidx < 5; funcidx++) {
185 expect_SIGFPE = 1;
186 if (setjmp(jmpbuf_SIGFPE) == 0) {
187 /* divide by zero using various functions */
188 switch (funcidx) {
189 case 0: res = i / j; ERR; break;
190 case 1: res = i / ex64lo(j); ERR; break;
191 case 2: res = i / ex64lo(j); ERR; break;
192 case 3: res = i % j; ERR; break;
193 case 4: res = i % ex64lo(j); ERR; break;
194 default: assert(0); ERR; break;
197 do_not_optimize_away((volatile u64_t *)&res);
199 /* if we reach this point there was no signal and an
200 * error has been recorded
202 expect_SIGFPE = 0;
203 } else {
204 /* a signal has been received and expect_SIGFPE has
205 * been reset; all is ok now
207 assert(!expect_SIGFPE);
212 static void testdiv(void)
214 u64_t q, r;
215 #if TIMED
216 struct timeval tvstart, tvend;
218 printf("i=0x%.8x%.8x; j=0x%.8x%.8x\n",
219 ex64hi(i), ex64lo(i),
220 ex64hi(j), ex64lo(j));
221 fflush(stdout);
222 if (gettimeofday(&tvstart, NULL) < 0) ERR;
223 #endif
225 /* division by zero has a separate test */
226 if (j == 0) {
227 testdiv0();
228 return;
231 /* perform division, store q in k to make ERR more informative */
232 q = i / j;
233 r = i % j;
234 k = q;
236 #if TIMED
237 if (gettimeofday(&tvend, NULL) < 0) ERR;
238 tvend.tv_sec -= tvstart.tv_sec;
239 tvend.tv_usec -= tvstart.tv_usec;
240 if (tvend.tv_usec < 0) {
241 tvend.tv_sec -= 1;
242 tvend.tv_usec += 1000000;
244 printf("q=0x%.8x%.8x; r=0x%.8x%.8x; time=%d.%.6d\n",
245 ex64hi(q), ex64lo(q),
246 ex64hi(r), ex64lo(r),
247 tvend.tv_sec, tvend.tv_usec);
248 fflush(stdout);
249 #endif
251 /* compare to 64/32-bit division if possible */
252 if (!ex64hi(j)) {
253 if (q != i / ex64lo(j)) ERR;
254 if (!ex64hi(q)) {
255 if (q != i / ex64lo(j)) ERR;
257 if (r != i % ex64lo(j)) ERR;
259 /* compare to 32-bit division if possible */
260 if (!ex64hi(i)) {
261 if (q != ex64lo(i) / ex64lo(j)) ERR;
262 if (r != ex64lo(i) % ex64lo(j)) ERR;
266 /* check results using i = q j + r and r < j */
267 if (i != (q * j) + r) ERR;
268 if (r >= j) ERR;
271 static void test(void)
273 int idone, jdone, iidx, jidx;
275 /* loop though all argument value combinations */
276 for (idone = 0, iidx = 0; i = getargval(iidx, &idone), !idone; iidx++)
277 for (jdone = 0, jidx = 0; j = getargval(jidx, &jdone), !jdone; jidx++) {
278 testmul();
279 testdiv();
283 int main(void)
285 start(53);
287 /* set up signal handler to deal with div by zero */
288 if (setjmp(jmpbuf_main) == 0) {
289 if (signal(SIGFPE, handler_SIGFPE) == SIG_ERR) ERR;
291 /* perform tests */
292 test();
293 } else {
294 /* an unexpected SIGFPE has occurred */
295 ERR;
298 /* this was all */
299 quit();
301 return(-1); /* Unreachable */