10 #define ERR err(__LINE__)
16 static volatile int expect_SIGFPE
;
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",
27 ex64hi(k
), ex64lo(k
));
29 /* quit after too many errors */
30 if (errct
++ > MAX_ERROR
) {
31 printf("Too many errors; test aborted\n");
36 #define LENGTHOF(arr) (sizeof(arr) / sizeof(arr[0]))
38 static u64_t
getargval(int index
, int *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
);
75 if (index
< 16) return make64(index
+ 2, 0);
79 if (index
< 16) return make64(-index
- 2, -1);
83 if (index
< 14) return make64(1 << (index
* 2 + 5), 0);
85 if (index
< 16) return make64(0, 1 << (index
* 2 + 1));
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? */
102 /* expected: jump back to test */
104 longjmp(jmpbuf_SIGFPE
, -1);
106 /* not expected: error and jump back to main */
107 longjmp(jmpbuf_main
, -1);
115 static void testmul(void)
118 u32_t ilo
= ex64lo(i
), jlo
= ex64lo(j
);
119 u64_t prod
= mul64(i
, j
);
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
;
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
++) {
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)
162 assert(cmp64u(j
, 0) == 0);
164 /* loop through the 5 different division functions */
165 for (funcidx
= 0; funcidx
< 5; funcidx
++) {
167 if (setjmp(jmpbuf_SIGFPE
) == 0) {
168 /* divide by zero using various functions */
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
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)
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
));
201 if (gettimeofday(&tvstart
, NULL
) < 0) ERR
;
204 /* division by zero has a separate test */
205 if (cmp64u(j
, 0) == 0) {
210 /* perform division, store q in k to make ERR more informative */
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) {
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
);
230 /* compare to 64/32-bit division if possible */
232 if (cmp64(q
, div64u64(i
, ex64lo(j
))) != 0) ERR
;
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 */
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
++) {
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
;
273 /* an unexpected SIGFPE has occurred */
280 return(-1); /* Unreachable */