1#include <stdio.h>
2#include <stdlib.h>
3#include <math.h>
4
5#include "soft-fp.h"
6#include "single.h"
7#include "double.h"
8
9#include <fpu_control.h>
10
11/*======================================================================*/
12/* declarations for the functions we are testing */
13
14double __adddf3(double, double);
15double __subdf3(double, double);
16double __muldf3(double, double);
17double __divdf3(double, double);
18double __negdf2(double);
19double __sqrtdf2(double);
20double __negdf3(double a, double dummy) { return __negdf2(a); }
21double __sqrtdf3(double a, double dummy) { return __sqrtdf2(a); }
22
23float __addsf3(float, float);
24float __subsf3(float, float);
25float __mulsf3(float, float);
26float __divsf3(float, float);
27float __negsf2(float);
28float __sqrtsf2(float);
29float __negsf3(float a, float dummy) { return __negsf2(a); }
30float __sqrtsf3(float a, float dummy) { return __sqrtsf2(a); }
31
32int __fixdfsi(double);
33int __fixsfsi(float);
34double __floatsidf(int);
35float __floatsisf(int);
36double __extendsfdf2(float);
37float __truncdfsf2(double);
38
39int __eqdf2(double, double);
40int __nedf2(double, double);
41int __gtdf2(double, double);
42int __gedf2(double, double);
43int __ltdf2(double, double);
44int __ledf2(double, double);
45
46int __eqsf2(float, float);
47int __nesf2(float, float);
48int __gtsf2(float, float);
49int __gesf2(float, float);
50int __ltsf2(float, float);
51int __lesf2(float, float);
52
53/*======================================================================*/
54/* definitions for functions we are checking against */
55
56double r_adddf3(double a, double b) { return a + b; }
57double r_subdf3(double a, double b) { return a - b; }
58double r_muldf3(double a, double b) { return a * b; }
59double r_divdf3(double a, double b) { return a / b; }
60double r_negdf3(double a, double b) { return -a; }
61double sqrt(double x);
62double r_sqrtdf3(double a, double b) { return sqrt(x: a); }
63
64float r_addsf3(float a, float b) { return a + b; }
65float r_subsf3(float a, float b) { return a - b; }
66float r_mulsf3(float a, float b) { return a * b; }
67float r_divsf3(float a, float b) { return a / b; }
68float r_negsf3(float a, float b) { return -a; }
69float sqrtf(float x);
70float r_sqrtsf3(float a, float b) { return sqrtf(x: a); }
71
72int r_fixdfsi(double a) { return (int)a; }
73int r_fixsfsi(float a) { return (int)a; }
74double r_floatsidf(int a) { return (double)a; }
75float r_floatsisf(int a) { return (float)a; }
76double r_extendsfdf2(float a) { return (double)a; }
77float r_truncdfsf2(double a) { return (float)a; }
78
79int r_eqdf2(double a, double b) { return !(a == b); }
80int r_nedf2(double a, double b) { return a != b; }
81int r_gtdf2(double a, double b) { return a > b; }
82int r_gedf2(double a, double b) { return (a >= b) - 1; }
83int r_ltdf2(double a, double b) { return -(a < b); }
84int r_ledf2(double a, double b) { return 1 - (a <= b); }
85
86int r_eqsf2(float a, float b) { return !(a == b); }
87int r_nesf2(float a, float b) { return a != b; }
88int r_gtsf2(float a, float b) { return a > b; }
89int r_gesf2(float a, float b) { return (a >= b) - 1; }
90int r_ltsf2(float a, float b) { return -(a < b); }
91int r_lesf2(float a, float b) { return 1 - (a <= b); }
92
93/*======================================================================*/
94
95void print_float(float x)
96{
97 union _FP_UNION_S ux;
98 ux.flt = x;
99 printf(format: "%-20.8e %X %02X %06lX",
100 x, ux.bits.sign, ux.bits.exp, (unsigned long)ux.bits.frac);
101}
102
103void print_double(double x)
104{
105 union _FP_UNION_D ux;
106 ux.flt = x;
107#if _FP_W_TYPE_SIZE < _FP_FRACBITS_D
108 printf("%-30.18e %X %04X %06lX%08lX",
109 x, ux.bits.sign, ux.bits.exp,
110 (unsigned long)ux.bits.frac1, (unsigned long)ux.bits.frac0);
111#else
112 printf(format: "%-30.18e %X %04X %014lX",
113 x, ux.bits.sign, ux.bits.exp,
114 (unsigned long)ux.bits.frac);
115#endif
116}
117
118float rand_float(void)
119{
120 union {
121 union _FP_UNION_S u;
122 int i;
123 } u;
124
125 u.i = lrand48() << 1;
126
127 if (u.u.bits.exp == _FP_EXPMAX_S)
128 u.u.bits.exp--;
129 else if (u.u.bits.exp == 0 && u.u.bits.frac != 0)
130 u.u.bits.exp++;
131
132 return u.u.flt;
133}
134
135
136double rand_double(void)
137{
138 union {
139 union _FP_UNION_D u;
140 int i[2];
141 } u;
142
143 u.i[0] = lrand48() << 1;
144 u.i[1] = lrand48() << 1;
145
146 if (u.u.bits.exp == _FP_EXPMAX_D)
147 u.u.bits.exp--;
148#if _FP_W_TYPE_SIZE < _FP_FRACBITS_D
149 else if (u.u.bits.exp == 0 && !(u.u.bits.frac0 == 0 && u.u.bits.frac1 == 0))
150 u.u.bits.exp++;
151#else
152 else if (u.u.bits.exp == 0 && u.u.bits.frac != 0)
153 u.u.bits.exp++;
154#endif
155
156 return u.u.flt;
157}
158
159#define NSPECIALS 10
160
161float gen_special_float(int i)
162{
163 FP_DECL_EX;
164 FP_DECL_S(X);
165 float x;
166
167 switch (i & ~1)
168 {
169 case 0:
170 X_c = FP_CLS_NAN; X_f = 0x1234;
171 break;
172 case 2:
173 X_c = FP_CLS_NAN; X_f = 0x1;
174 break;
175 case 4:
176 X_c = FP_CLS_INF;
177 break;
178 case 6:
179 X_c = FP_CLS_ZERO;
180 break;
181 case 8:
182 X_c = FP_CLS_NORMAL; X_e = 0;
183 X_f = 0x4321;
184 break;
185 }
186 X_s = (i & 1);
187
188 FP_PACK_S(x, X);
189 return x;
190}
191
192double gen_special_double(int i)
193{
194 FP_DECL_EX;
195 FP_DECL_D(X);
196 double x;
197
198 switch (i & ~1)
199 {
200 case 0:
201 X_c = FP_CLS_NAN;
202#if _FP_W_TYPE_SIZE < _FP_FRACBITS_D
203 __FP_FRAC_SET_2(X, _FP_QNANNEGATEDP ? 0 : _FP_QNANBIT_D, 0x1234);
204#else
205 _FP_FRAC_SET_1(X, (_FP_QNANNEGATEDP ? 0 : _FP_QNANBIT_D) | 0x1234);
206#endif
207 break;
208 case 2:
209 X_c = FP_CLS_NAN;
210#if _FP_W_TYPE_SIZE < _FP_FRACBITS_D
211 __FP_FRAC_SET_2(X, _FP_QNANNEGATEDP ? 0 : _FP_QNANBIT_D, 0x1);
212#else
213 _FP_FRAC_SET_1(X, (_FP_QNANNEGATEDP ? 0 : _FP_QNANBIT_D) | 0x1);
214#endif
215 break;
216 case 4:
217 X_c = FP_CLS_INF;
218 break;
219 case 6:
220 X_c = FP_CLS_ZERO;
221 break;
222 case 8:
223 X_c = FP_CLS_NORMAL; X_e = 0;
224#if _FP_W_TYPE_SIZE < _FP_FRACBITS_D
225 __FP_FRAC_SET_2(X, 0, 0x87654321);
226#else
227 _FP_FRAC_SET_1(X, 0x87654321);
228#endif
229 break;
230 }
231 X_s = (i & 1);
232
233 FP_PACK_D(x, X);
234 return x;
235}
236
237float build_float(const char *s, const char *e, const char *f)
238{
239 union _FP_UNION_S u;
240
241 u.bits.sign = strtoul(s, 0, 16);
242 u.bits.exp = strtoul(e, 0, 16);
243 u.bits.frac = strtoul(f, 0, 16);
244
245 return u.flt;
246}
247
248double build_double(const char *s, const char *e, const char *f)
249{
250 union _FP_UNION_D u;
251
252 u.bits.sign = strtoul(s, 0, 16);
253 u.bits.exp = strtoul(e, 0, 16);
254#if _FP_W_TYPE_SIZE < _FP_FRACBITS_D
255 {
256 size_t len = strlen(f)+1;
257 char *dup = memcpy(alloca(len), f, len);
258 char *low = dup + len - _FP_W_TYPE_SIZE/4 - 1;
259
260 u.bits.frac0 = strtoul(low, 0, 16);
261 *low = 0;
262 u.bits.frac1 = strtoul(dup, 0, 16);
263 }
264#else
265 u.bits.frac = strtoul(f, 0, 16);
266#endif
267
268 return u.flt;
269}
270
271/*======================================================================*/
272
273fpu_control_t fcw0, fcw1;
274
275void test_float_arith(float (*tf)(float, float),
276 float (*rf)(float, float),
277 float x, float y)
278{
279 float tr, rr;
280 rr = (*rf)(x, y);
281 tr = (*tf)(x, y);
282 if (memcmp(&tr, &rr, sizeof(float)) != 0)
283 {
284 fputs("error:\n\tx = ", stdout); print_float(x);
285 fputs("\n\ty = ", stdout); print_float(x: y);
286 fputs("\n\ttrue = ", stdout); print_float(x: rr);
287 fputs("\n\tfalse = ", stdout); print_float(x: tr);
288 putchar(c: '\n');
289 }
290}
291
292void test_double_arith(double (*tf)(double, double),
293 double (*rf)(double, double),
294 double x, double y)
295{
296 double tr, rr;
297#ifdef __i386__
298 /* Don't worry. Even this does not make it error free
299 on ia32. If the result is denormal, it will not
300 honour the double precision and generate bad results
301 anyway. On the other side, who wants to use ia32
302 for IEEE math? I don't. */
303 _FPU_GETCW(fcw0);
304 fcw1 = ((fcw0 & ~_FPU_EXTENDED) | _FPU_DOUBLE);
305 _FPU_SETCW(fcw1);
306#endif
307 rr = (*rf)(x, y);
308#ifdef __i386__
309 _FPU_SETCW(fcw0);
310#endif
311 tr = (*tf)(x, y);
312 if (memcmp(&tr, &rr, sizeof(double)) != 0)
313 {
314 fputs("error:\n\tx = ", stdout); print_double(x);
315 fputs("\n\ty = ", stdout); print_double(x: y);
316 fputs("\n\ttrue = ", stdout); print_double(x: rr);
317 fputs("\n\tfalse = ", stdout); print_double(x: tr);
318 putchar(c: '\n');
319 }
320}
321
322void test_float_double_conv(float x)
323{
324 double tr, rr;
325 rr = r_extendsfdf2(a: x);
326 tr = __extendsfdf2(x);
327 if (memcmp(&tr, &rr, sizeof(double)) != 0)
328 {
329 fputs("error:\n\tx = ", stdout); print_float(x);
330 fputs("\n\ttrue = ", stdout); print_double(x: rr);
331 fputs("\n\tfalse = ", stdout); print_double(x: tr);
332 putchar(c: '\n');
333 }
334}
335
336void test_double_float_conv(double x)
337{
338 float tr, rr;
339 rr = r_truncdfsf2(a: x);
340 tr = __truncdfsf2(x);
341 if (memcmp(&tr, &rr, sizeof(float)) != 0)
342 {
343 fputs("error:\n\tx = ", stdout); print_double(x);
344 fputs("\n\ttrue = ", stdout); print_float(x: rr);
345 fputs("\n\tfalse = ", stdout); print_float(x: tr);
346 putchar(c: '\n');
347 }
348}
349
350void test_int_float_conv(int x)
351{
352 float tr, rr;
353 rr = r_floatsisf(a: x);
354 tr = __floatsisf(x);
355 if (memcmp(&tr, &rr, sizeof(float)) != 0)
356 {
357 printf(format: "error\n\tx = %d", x);
358 fputs("\n\ttrue = ", stdout); print_float(x: rr);
359 fputs("\n\tfalse = ", stdout); print_float(x: tr);
360 putchar(c: '\n');
361 }
362}
363
364void test_int_double_conv(int x)
365{
366 double tr, rr;
367 rr = r_floatsidf(a: x);
368 tr = __floatsidf(x);
369 if (memcmp(&tr, &rr, sizeof(double)) != 0)
370 {
371 printf(format: "error\n\tx = %d", x);
372 fputs("\n\ttrue = ", stdout); print_double(x: rr);
373 fputs("\n\tfalse = ", stdout); print_double(x: tr);
374 putchar(c: '\n');
375 }
376}
377
378void test_float_int_conv(float x)
379{
380 int tr, rr;
381 rr = r_fixsfsi(a: x);
382 tr = __fixsfsi(x);
383 if (rr != tr)
384 {
385 fputs("error:\n\tx = ", stdout); print_float(x);
386 printf(format: "\n\ttrue = %d\n\tfalse = %d\n", rr, tr);
387 }
388}
389
390void test_double_int_conv(double x)
391{
392 int tr, rr;
393 rr = r_fixsfsi(a: x);
394 tr = __fixsfsi(x);
395 if (rr != tr)
396 {
397 fputs("error:\n\tx = ", stdout); print_double(x);
398 printf(format: "\n\ttrue = %d\n\tfalse = %d\n", rr, tr);
399 }
400}
401
402int eq0(int x) { return x == 0; }
403int ne0(int x) { return x != 0; }
404int le0(int x) { return x <= 0; }
405int lt0(int x) { return x < 0; }
406int ge0(int x) { return x >= 0; }
407int gt0(int x) { return x > 0; }
408
409void test_float_cmp(int (*tf)(float, float),
410 int (*rf)(float, float),
411 int (*cmp0)(int),
412 float x, float y)
413{
414 int tr, rr;
415 rr = (*rf)(x, y);
416 tr = (*tf)(x, y);
417 if (cmp0(rr) != cmp0(tr))
418 {
419 fputs("error:\n\tx = ", stdout); print_float(x);
420 fputs("\n\ty = ", stdout); print_float(x: y);
421 printf(format: "\n\ttrue = %d\n\tfalse = %d\n", rr, tr);
422 }
423}
424
425void test_double_cmp(int (*tf)(double, double),
426 int (*rf)(double, double),
427 int (*cmp0)(int),
428 double x, double y)
429{
430 int tr, rr;
431 rr = (*rf)(x, y);
432 tr = (*tf)(x, y);
433 if (cmp0(rr) != cmp0(tr))
434 {
435 fputs("error:\n\tx = ", stdout); print_double(x);
436 fputs("\n\ty = ", stdout); print_double(x: y);
437 printf(format: "\n\ttrue = %d\n\tfalse = %d\n", rr, tr);
438 }
439}
440
441
442/*======================================================================*/
443
444
445int main(int ac, char **av)
446{
447#ifdef __alpha__
448 __ieee_set_fp_control(0);
449#endif
450 av++, ac--;
451 switch (*(*av)++)
452 {
453 {
454 float (*r)(float, float);
455 float (*t)(float, float);
456
457 do {
458 case 'a': r = r_addsf3; t = __addsf3; break;
459 case 's': r = r_subsf3; t = __subsf3; break;
460 case 'm': r = r_mulsf3; t = __mulsf3; break;
461 case 'd': r = r_divsf3; t = __divsf3; break;
462 case 'r': r = r_sqrtsf3; t = __sqrtsf3; break;
463 case 'j': r = r_negsf3; t = __negsf3; break;
464 } while (0);
465
466 switch (*(*av)++)
467 {
468 case 'n':
469 {
470 int count = (ac > 1 ? atoi(av[1]) : 100);
471 while (count--)
472 test_float_arith(tf: t, rf: r, x: rand_float(), y: rand_float());
473 }
474 break;
475
476 case 's':
477 {
478 int i, j;
479 for (i = 0; i < NSPECIALS; i++)
480 for (j = 0; j < NSPECIALS; j++)
481 test_float_arith(tf: t, rf: r, x: gen_special_float(i),
482 y: gen_special_float(i: j));
483 }
484 break;
485
486 case 0:
487 if (ac < 7) abort();
488 test_float_arith(tf: t, rf: r, x: build_float(s: av[1], e: av[2], f: av[3]),
489 y: build_float(s: av[4], e: av[5], f: av[6]));
490 break;
491 }
492 }
493 break;
494
495 {
496 double (*r)(double, double);
497 double (*t)(double, double);
498
499 do {
500 case 'A': r = r_adddf3; t = __adddf3; break;
501 case 'S': r = r_subdf3; t = __subdf3; break;
502 case 'M': r = r_muldf3; t = __muldf3; break;
503 case 'D': r = r_divdf3; t = __divdf3; break;
504 case 'R': r = r_sqrtdf3; t = __sqrtdf3; break;
505 case 'J': r = r_negdf3; t = __negdf3; break;
506 } while (0);
507
508 switch (*(*av)++)
509 {
510 case 'n':
511 {
512 int count = (ac > 1 ? atoi(av[1]) : 100);
513 while (count--)
514 test_double_arith(tf: t, rf: r, x: rand_double(), y: rand_double());
515 }
516 break;
517
518 case 's':
519 {
520 int i, j;
521 for (i = 0; i < NSPECIALS; i++)
522 for (j = 0; j < NSPECIALS; j++)
523 test_double_arith(tf: t, rf: r, x: gen_special_double(i),
524 y: gen_special_double(i: j));
525 }
526 break;
527
528 case 0:
529 if (ac < 7) abort();
530 test_double_arith(tf: t, rf: r, x: build_double(s: av[1], e: av[2], f: av[3]),
531 y: build_double(s: av[4], e: av[5], f: av[6]));
532 break;
533 }
534 }
535 break;
536
537 case 'c':
538 switch (*(*av)++)
539 {
540 case 'n':
541 {
542 int count = (ac > 1 ? atoi(av[1]) : 100);
543 while (count--)
544 test_float_double_conv(x: rand_float());
545 }
546 break;
547
548 case 's':
549 {
550 int i;
551 for (i = 0; i < NSPECIALS; i++)
552 test_float_double_conv(x: gen_special_float(i));
553 }
554 break;
555
556 case 0:
557 if (ac < 4) abort();
558 test_float_double_conv(x: build_float(s: av[1], e: av[2], f: av[3]));
559 break;
560 }
561 break;
562
563 case 'C':
564 switch (*(*av)++)
565 {
566 case 'n':
567 {
568 int count = (ac > 1 ? atoi(av[1]) : 100);
569 while (count--)
570 test_double_float_conv(x: rand_double());
571 }
572 break;
573
574 case 's':
575 {
576 int i;
577 for (i = 0; i < NSPECIALS; i++)
578 test_double_float_conv(x: gen_special_double(i));
579 }
580 break;
581
582 case 0:
583 if (ac < 4) abort();
584 test_double_float_conv(x: build_double(s: av[1], e: av[2], f: av[3]));
585 break;
586 }
587 break;
588
589 case 'i':
590 switch (*(*av)++)
591 {
592 case 'n':
593 {
594 int count = (ac > 1 ? atoi(av[1]) : 100);
595 while (count--)
596 test_int_float_conv(x: lrand48() << 1);
597 }
598 break;
599
600 case 0:
601 if (ac < 2) abort();
602 test_int_float_conv(x: strtol(av[1], 0, 0));
603 break;
604 }
605 break;
606
607 case 'I':
608 switch (*(*av)++)
609 {
610 case 'n':
611 {
612 int count = (ac > 1 ? atoi(av[1]) : 100);
613 while (count--)
614 test_int_double_conv(x: lrand48() << 1);
615 }
616 break;
617
618 case 0:
619 if (ac < 2) abort();
620 test_int_double_conv(x: strtol(av[1], 0, 0));
621 break;
622 }
623 break;
624
625 case 'f':
626 switch (*(*av)++)
627 {
628 case 'n':
629 {
630 int count = (ac > 1 ? atoi(av[1]) : 100);
631 while (count--)
632 test_float_int_conv(x: rand_float());
633 }
634 break;
635
636 case 's':
637 {
638 int i;
639 for (i = 0; i < NSPECIALS; i++)
640 test_float_int_conv(x: gen_special_float(i));
641 }
642 break;
643
644 case 0:
645 if (ac < 4) abort();
646 test_float_int_conv(x: build_float(s: av[1], e: av[2], f: av[3]));
647 break;
648 }
649 break;
650
651 case 'F':
652 switch (*(*av)++)
653 {
654 case 'n':
655 {
656 int count = (ac > 1 ? atoi(av[1]) : 100);
657 while (count--)
658 test_double_int_conv(x: rand_double());
659 }
660 break;
661
662 case 's':
663 {
664 int i;
665 for (i = 0; i < NSPECIALS; i++)
666 test_double_int_conv(x: gen_special_double(i));
667 }
668 break;
669
670 case 0:
671 if (ac < 4) abort();
672 test_double_int_conv(x: build_double(s: av[1], e: av[2], f: av[3]));
673 break;
674 }
675 break;
676
677 {
678 int (*r)(float, float);
679 int (*t)(float, float);
680 int (*c)(int);
681
682 do {
683 case 'e': r = r_eqsf2; t = __eqsf2; c = eq0; break;
684 case 'n': r = r_nesf2; t = __nesf2; c = ne0; break;
685 case 'l':
686 switch (*(*av)++)
687 {
688 case 'e': r = r_lesf2; t = __lesf2; c = le0; break;
689 case 't': r = r_ltsf2; t = __ltsf2; c = lt0; break;
690 }
691 break;
692 case 'g':
693 switch (*(*av)++)
694 {
695 case 'e': r = r_gesf2; t = __gesf2; c = ge0; break;
696 case 't': r = r_gtsf2; t = __gtsf2; c = gt0; break;
697 }
698 break;
699 } while (0);
700
701 switch (*(*av)++)
702 {
703 case 'n':
704 {
705 int count = (ac > 1 ? atoi(av[1]) : 100);
706 while (count--)
707 test_float_cmp(tf: t, rf: r, cmp0: c, x: rand_float(), y: rand_float());
708 }
709 break;
710
711 case 's':
712 {
713 int i, j;
714 for (i = 0; i < NSPECIALS; i++)
715 for (j = 0; j < NSPECIALS; j++)
716 test_float_cmp(tf: t, rf: r, cmp0: c, x: gen_special_float(i),
717 y: gen_special_float(i: j));
718 }
719 break;
720
721 case 0:
722 if (ac < 7) abort();
723 test_float_cmp(tf: t, rf: r, cmp0: c, x: build_float(s: av[1], e: av[2], f: av[3]),
724 y: build_float(s: av[4], e: av[5], f: av[6]));
725 break;
726 }
727 }
728 break;
729
730 {
731 int (*r)(double, double);
732 int (*t)(double, double);
733 int (*c)(int);
734
735 do {
736 case 'E': r = r_eqdf2; t = __eqdf2; c = eq0; break;
737 case 'N': r = r_nedf2; t = __nedf2; c = ne0; break;
738 case 'L':
739 switch (*(*av)++)
740 {
741 case 'E': r = r_ledf2; t = __ledf2; c = le0; break;
742 case 'T': r = r_ltdf2; t = __ltdf2; c = lt0; break;
743 }
744 break;
745 case 'G':
746 switch (*(*av)++)
747 {
748 case 'E': r = r_gedf2; t = __gedf2; c = ge0; break;
749 case 'T': r = r_gtdf2; t = __gtdf2; c = gt0; break;
750 }
751 break;
752 } while (0);
753
754 switch (*(*av)++)
755 {
756 case 'n':
757 {
758 int count = (ac > 1 ? atoi(av[1]) : 100);
759 while (count--)
760 test_double_cmp(tf: t, rf: r, cmp0: c, x: rand_double(), y: rand_double());
761 }
762 break;
763
764 case 's':
765 {
766 int i, j;
767 for (i = 0; i < NSPECIALS; i++)
768 for (j = 0; j < NSPECIALS; j++)
769 test_double_cmp(tf: t, rf: r, cmp0: c, x: gen_special_double(i),
770 y: gen_special_double(i: j));
771 }
772 break;
773
774 case 0:
775 if (ac < 7) abort();
776 test_double_cmp(tf: t, rf: r, cmp0: c, x: build_double(s: av[1], e: av[2], f: av[3]),
777 y: build_double(s: av[4], e: av[5], f: av[6]));
778 break;
779 }
780 }
781 break;
782
783 default:
784 abort();
785 }
786
787 return 0;
788}
789

source code of glibc/soft-fp/testit.c