]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - tools/test/testfloat/testsoftfloat.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / tools / test / testfloat / testsoftfloat.c
1
2 /*
3 ===============================================================================
4
5 This C source file is part of TestFloat, Release 2a, a package of programs
6 for testing the correctness of floating-point arithmetic complying to the
7 IEC/IEEE Standard for Floating-Point.
8
9 Written by John R. Hauser.  More information is available through the Web
10 page `http://HTTP.CS.Berkeley.EDU/~jhauser/arithmetic/TestFloat.html'.
11
12 THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE.  Although reasonable effort
13 has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
14 TIMES RESULT IN INCORRECT BEHAVIOR.  USE OF THIS SOFTWARE IS RESTRICTED TO
15 PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY
16 AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE.
17
18 Derivative works are acceptable, even for commercial purposes, so long as
19 (1) they include prominent notice that the work is derivative, and (2) they
20 include prominent notice akin to these four paragraphs for those parts of
21 this code that are retained.
22
23 ===============================================================================
24 */
25
26 #include <sys/cdefs.h>
27 __FBSDID("$FreeBSD$");
28
29 #include <stdlib.h>
30 #include <signal.h>
31 #include <string.h>
32 #include "milieu.h"
33 #include "fail.h"
34 #include "softfloat.h"
35 #include "slowfloat.h"
36 #include "testCases.h"
37 #include "testLoops.h"
38
39 static void catchSIGINT( int signalCode )
40 {
41
42     if ( stop ) exit( EXIT_FAILURE );
43     stop = TRUE;
44
45 }
46
47 int8 clearFlags( void )
48 {
49     int8 flags;
50
51     flags = float_exception_flags;
52     float_exception_flags = 0;
53     return flags;
54
55 }
56
57 enum {
58     INT32_TO_FLOAT32 = 1,
59     INT32_TO_FLOAT64,
60 #ifdef FLOATX80
61     INT32_TO_FLOATX80,
62 #endif
63 #ifdef FLOAT128
64     INT32_TO_FLOAT128,
65 #endif
66 #ifdef BITS64
67     INT64_TO_FLOAT32,
68     INT64_TO_FLOAT64,
69 #ifdef FLOATX80
70     INT64_TO_FLOATX80,
71 #endif
72 #ifdef FLOAT128
73     INT64_TO_FLOAT128,
74 #endif
75 #endif
76     FLOAT32_TO_INT32,
77     FLOAT32_TO_INT32_ROUND_TO_ZERO,
78 #ifdef BITS64
79     FLOAT32_TO_INT64,
80     FLOAT32_TO_INT64_ROUND_TO_ZERO,
81 #endif
82     FLOAT32_TO_FLOAT64,
83 #ifdef FLOATX80
84     FLOAT32_TO_FLOATX80,
85 #endif
86 #ifdef FLOAT128
87     FLOAT32_TO_FLOAT128,
88 #endif
89     FLOAT32_ROUND_TO_INT,
90     FLOAT32_ADD,
91     FLOAT32_SUB,
92     FLOAT32_MUL,
93     FLOAT32_DIV,
94     FLOAT32_REM,
95     FLOAT32_SQRT,
96     FLOAT32_EQ,
97     FLOAT32_LE,
98     FLOAT32_LT,
99     FLOAT32_EQ_SIGNALING,
100     FLOAT32_LE_QUIET,
101     FLOAT32_LT_QUIET,
102     FLOAT64_TO_INT32,
103     FLOAT64_TO_INT32_ROUND_TO_ZERO,
104 #ifdef BITS64
105     FLOAT64_TO_INT64,
106     FLOAT64_TO_INT64_ROUND_TO_ZERO,
107 #endif
108     FLOAT64_TO_FLOAT32,
109 #ifdef FLOATX80
110     FLOAT64_TO_FLOATX80,
111 #endif
112 #ifdef FLOAT128
113     FLOAT64_TO_FLOAT128,
114 #endif
115     FLOAT64_ROUND_TO_INT,
116     FLOAT64_ADD,
117     FLOAT64_SUB,
118     FLOAT64_MUL,
119     FLOAT64_DIV,
120     FLOAT64_REM,
121     FLOAT64_SQRT,
122     FLOAT64_EQ,
123     FLOAT64_LE,
124     FLOAT64_LT,
125     FLOAT64_EQ_SIGNALING,
126     FLOAT64_LE_QUIET,
127     FLOAT64_LT_QUIET,
128 #ifdef FLOATX80
129     FLOATX80_TO_INT32,
130     FLOATX80_TO_INT32_ROUND_TO_ZERO,
131 #ifdef BITS64
132     FLOATX80_TO_INT64,
133     FLOATX80_TO_INT64_ROUND_TO_ZERO,
134 #endif
135     FLOATX80_TO_FLOAT32,
136     FLOATX80_TO_FLOAT64,
137 #ifdef FLOAT128
138     FLOATX80_TO_FLOAT128,
139 #endif
140     FLOATX80_ROUND_TO_INT,
141     FLOATX80_ADD,
142     FLOATX80_SUB,
143     FLOATX80_MUL,
144     FLOATX80_DIV,
145     FLOATX80_REM,
146     FLOATX80_SQRT,
147     FLOATX80_EQ,
148     FLOATX80_LE,
149     FLOATX80_LT,
150     FLOATX80_EQ_SIGNALING,
151     FLOATX80_LE_QUIET,
152     FLOATX80_LT_QUIET,
153 #endif
154 #ifdef FLOAT128
155     FLOAT128_TO_INT32,
156     FLOAT128_TO_INT32_ROUND_TO_ZERO,
157 #ifdef BITS64
158     FLOAT128_TO_INT64,
159     FLOAT128_TO_INT64_ROUND_TO_ZERO,
160 #endif
161     FLOAT128_TO_FLOAT32,
162     FLOAT128_TO_FLOAT64,
163 #ifdef FLOATX80
164     FLOAT128_TO_FLOATX80,
165 #endif
166     FLOAT128_ROUND_TO_INT,
167     FLOAT128_ADD,
168     FLOAT128_SUB,
169     FLOAT128_MUL,
170     FLOAT128_DIV,
171     FLOAT128_REM,
172     FLOAT128_SQRT,
173     FLOAT128_EQ,
174     FLOAT128_LE,
175     FLOAT128_LT,
176     FLOAT128_EQ_SIGNALING,
177     FLOAT128_LE_QUIET,
178     FLOAT128_LT_QUIET,
179 #endif
180     NUM_FUNCTIONS
181 };
182 static struct {
183     char *name;
184     int8 numInputs;
185     flag roundingPrecision, roundingMode;
186     flag tininessMode, tininessModeAtReducedPrecision;
187 } functions[ NUM_FUNCTIONS ] = {
188     { 0, 0, 0, 0, 0, 0 },
189     { "int32_to_float32",                1, FALSE, TRUE,  FALSE, FALSE },
190     { "int32_to_float64",                1, FALSE, FALSE, FALSE, FALSE },
191 #ifdef FLOATX80
192     { "int32_to_floatx80",               1, FALSE, FALSE, FALSE, FALSE },
193 #endif
194 #ifdef FLOAT128
195     { "int32_to_float128",               1, FALSE, FALSE, FALSE, FALSE },
196 #endif
197 #ifdef BITS64
198     { "int64_to_float32",                1, FALSE, TRUE,  FALSE, FALSE },
199     { "int64_to_float64",                1, FALSE, TRUE,  FALSE, FALSE },
200 #ifdef FLOATX80
201     { "int64_to_floatx80",               1, FALSE, FALSE, FALSE, FALSE },
202 #endif
203 #ifdef FLOAT128
204     { "int64_to_float128",               1, FALSE, FALSE, FALSE, FALSE },
205 #endif
206 #endif
207     { "float32_to_int32",                1, FALSE, TRUE,  FALSE, FALSE },
208     { "float32_to_int32_round_to_zero",  1, FALSE, FALSE, FALSE, FALSE },
209 #ifdef BITS64
210     { "float32_to_int64",                1, FALSE, TRUE,  FALSE, FALSE },
211     { "float32_to_int64_round_to_zero",  1, FALSE, FALSE, FALSE, FALSE },
212 #endif
213     { "float32_to_float64",              1, FALSE, FALSE, FALSE, FALSE },
214 #ifdef FLOATX80
215     { "float32_to_floatx80",             1, FALSE, FALSE, FALSE, FALSE },
216 #endif
217 #ifdef FLOAT128
218     { "float32_to_float128",             1, FALSE, FALSE, FALSE, FALSE },
219 #endif
220     { "float32_round_to_int",            1, FALSE, TRUE,  FALSE, FALSE },
221     { "float32_add",                     2, FALSE, TRUE,  FALSE, FALSE },
222     { "float32_sub",                     2, FALSE, TRUE,  FALSE, FALSE },
223     { "float32_mul",                     2, FALSE, TRUE,  TRUE,  FALSE },
224     { "float32_div",                     2, FALSE, TRUE,  FALSE, FALSE },
225     { "float32_rem",                     2, FALSE, FALSE, FALSE, FALSE },
226     { "float32_sqrt",                    1, FALSE, TRUE,  FALSE, FALSE },
227     { "float32_eq",                      2, FALSE, FALSE, FALSE, FALSE },
228     { "float32_le",                      2, FALSE, FALSE, FALSE, FALSE },
229     { "float32_lt",                      2, FALSE, FALSE, FALSE, FALSE },
230     { "float32_eq_signaling",            2, FALSE, FALSE, FALSE, FALSE },
231     { "float32_le_quiet",                2, FALSE, FALSE, FALSE, FALSE },
232     { "float32_lt_quiet",                2, FALSE, FALSE, FALSE, FALSE },
233     { "float64_to_int32",                1, FALSE, TRUE,  FALSE, FALSE },
234     { "float64_to_int32_round_to_zero",  1, FALSE, FALSE, FALSE, FALSE },
235 #ifdef BITS64
236     { "float64_to_int64",                1, FALSE, TRUE,  FALSE, FALSE },
237     { "float64_to_int64_round_to_zero",  1, FALSE, FALSE, FALSE, FALSE },
238 #endif
239     { "float64_to_float32",              1, FALSE, TRUE,  TRUE,  FALSE },
240 #ifdef FLOATX80
241     { "float64_to_floatx80",             1, FALSE, FALSE, FALSE, FALSE },
242 #endif
243 #ifdef FLOAT128
244     { "float64_to_float128",             1, FALSE, FALSE, FALSE, FALSE },
245 #endif
246     { "float64_round_to_int",            1, FALSE, TRUE,  FALSE, FALSE },
247     { "float64_add",                     2, FALSE, TRUE,  FALSE, FALSE },
248     { "float64_sub",                     2, FALSE, TRUE,  FALSE, FALSE },
249     { "float64_mul",                     2, FALSE, TRUE,  TRUE,  FALSE },
250     { "float64_div",                     2, FALSE, TRUE,  FALSE, FALSE },
251     { "float64_rem",                     2, FALSE, FALSE, FALSE, FALSE },
252     { "float64_sqrt",                    1, FALSE, TRUE,  FALSE, FALSE },
253     { "float64_eq",                      2, FALSE, FALSE, FALSE, FALSE },
254     { "float64_le",                      2, FALSE, FALSE, FALSE, FALSE },
255     { "float64_lt",                      2, FALSE, FALSE, FALSE, FALSE },
256     { "float64_eq_signaling",            2, FALSE, FALSE, FALSE, FALSE },
257     { "float64_le_quiet",                2, FALSE, FALSE, FALSE, FALSE },
258     { "float64_lt_quiet",                2, FALSE, FALSE, FALSE, FALSE },
259 #ifdef FLOATX80
260     { "floatx80_to_int32",               1, FALSE, TRUE,  FALSE, FALSE },
261     { "floatx80_to_int32_round_to_zero", 1, FALSE, FALSE, FALSE, FALSE },
262 #ifdef BITS64
263     { "floatx80_to_int64",               1, FALSE, TRUE,  FALSE, FALSE },
264     { "floatx80_to_int64_round_to_zero", 1, FALSE, FALSE, FALSE, FALSE },
265 #endif
266     { "floatx80_to_float32",             1, FALSE, TRUE,  TRUE,  FALSE },
267     { "floatx80_to_float64",             1, FALSE, TRUE,  TRUE,  FALSE },
268 #ifdef FLOAT128
269     { "floatx80_to_float128",            1, FALSE, FALSE, FALSE, FALSE },
270 #endif
271     { "floatx80_round_to_int",           1, FALSE, TRUE,  FALSE, FALSE },
272     { "floatx80_add",                    2, TRUE,  TRUE,  FALSE, TRUE  },
273     { "floatx80_sub",                    2, TRUE,  TRUE,  FALSE, TRUE  },
274     { "floatx80_mul",                    2, TRUE,  TRUE,  TRUE,  TRUE  },
275     { "floatx80_div",                    2, TRUE,  TRUE,  FALSE, TRUE  },
276     { "floatx80_rem",                    2, FALSE, FALSE, FALSE, FALSE },
277     { "floatx80_sqrt",                   1, TRUE,  TRUE,  FALSE, FALSE },
278     { "floatx80_eq",                     2, FALSE, FALSE, FALSE, FALSE },
279     { "floatx80_le",                     2, FALSE, FALSE, FALSE, FALSE },
280     { "floatx80_lt",                     2, FALSE, FALSE, FALSE, FALSE },
281     { "floatx80_eq_signaling",           2, FALSE, FALSE, FALSE, FALSE },
282     { "floatx80_le_quiet",               2, FALSE, FALSE, FALSE, FALSE },
283     { "floatx80_lt_quiet",               2, FALSE, FALSE, FALSE, FALSE },
284 #endif
285 #ifdef FLOAT128
286     { "float128_to_int32",               1, FALSE, TRUE,  FALSE, FALSE },
287     { "float128_to_int32_round_to_zero", 1, FALSE, FALSE, FALSE, FALSE },
288 #ifdef BITS64
289     { "float128_to_int64",               1, FALSE, TRUE,  FALSE, FALSE },
290     { "float128_to_int64_round_to_zero", 1, FALSE, FALSE, FALSE, FALSE },
291 #endif
292     { "float128_to_float32",             1, FALSE, TRUE,  TRUE,  FALSE },
293     { "float128_to_float64",             1, FALSE, TRUE,  TRUE,  FALSE },
294 #ifdef FLOATX80
295     { "float128_to_floatx80",            1, FALSE, TRUE,  TRUE,  FALSE },
296 #endif
297     { "float128_round_to_int",           1, FALSE, TRUE,  FALSE, FALSE },
298     { "float128_add",                    2, FALSE, TRUE,  FALSE, FALSE },
299     { "float128_sub",                    2, FALSE, TRUE,  FALSE, FALSE },
300     { "float128_mul",                    2, FALSE, TRUE,  TRUE,  FALSE },
301     { "float128_div",                    2, FALSE, TRUE,  FALSE, FALSE },
302     { "float128_rem",                    2, FALSE, FALSE, FALSE, FALSE },
303     { "float128_sqrt",                   1, FALSE, TRUE,  FALSE, FALSE },
304     { "float128_eq",                     2, FALSE, FALSE, FALSE, FALSE },
305     { "float128_le",                     2, FALSE, FALSE, FALSE, FALSE },
306     { "float128_lt",                     2, FALSE, FALSE, FALSE, FALSE },
307     { "float128_eq_signaling",           2, FALSE, FALSE, FALSE, FALSE },
308     { "float128_le_quiet",               2, FALSE, FALSE, FALSE, FALSE },
309     { "float128_lt_quiet",               2, FALSE, FALSE, FALSE, FALSE },
310 #endif
311 };
312
313 enum {
314     ROUND_NEAREST_EVEN = 1,
315     ROUND_TO_ZERO,
316     ROUND_DOWN,
317     ROUND_UP,
318     NUM_ROUNDINGMODES
319 };
320 enum {
321     TININESS_BEFORE_ROUNDING = 1,
322     TININESS_AFTER_ROUNDING,
323     NUM_TININESSMODES
324 };
325
326 static void
327  testFunctionVariety(
328      uint8 functionCode,
329      int8 roundingPrecision,
330      int8 roundingMode,
331      int8 tininessMode
332  )
333 {
334     uint8 roundingCode;
335     int8 tininessCode;
336
337     functionName = functions[ functionCode ].name;
338     if ( roundingPrecision == 32 ) {
339         roundingPrecisionName = "32";
340     }
341     else if ( roundingPrecision == 64 ) {
342         roundingPrecisionName = "64";
343     }
344     else if ( roundingPrecision == 80 ) {
345         roundingPrecisionName = "80";
346     }
347     else {
348         roundingPrecisionName = 0;
349     }
350 #ifdef FLOATX80
351     floatx80_rounding_precision = roundingPrecision;
352     slow_floatx80_rounding_precision = roundingPrecision;
353 #endif
354     switch ( roundingMode ) {
355      default:
356         roundingModeName = 0;
357         roundingCode = float_round_nearest_even;
358         break;
359      case ROUND_NEAREST_EVEN:
360         roundingModeName = "nearest_even";
361         roundingCode = float_round_nearest_even;
362         break;
363      case ROUND_TO_ZERO:
364         roundingModeName = "to_zero";
365         roundingCode = float_round_to_zero;
366         break;
367      case ROUND_DOWN:
368         roundingModeName = "down";
369         roundingCode = float_round_down;
370         break;
371      case ROUND_UP:
372         roundingModeName = "up";
373         roundingCode = float_round_up;
374         break;
375     }
376     float_rounding_mode = roundingCode;
377     slow_float_rounding_mode = roundingCode;
378     switch ( tininessMode ) {
379      default:
380         tininessModeName = 0;
381         tininessCode = float_tininess_after_rounding;
382         break;
383      case TININESS_BEFORE_ROUNDING:
384         tininessModeName = "before";
385         tininessCode = float_tininess_before_rounding;
386         break;
387      case TININESS_AFTER_ROUNDING:
388         tininessModeName = "after";
389         tininessCode = float_tininess_after_rounding;
390         break;
391     }
392     float_detect_tininess = tininessCode;
393     slow_float_detect_tininess = tininessCode;
394     fputs( "Testing ", stderr );
395     writeFunctionName( stderr );
396     fputs( ".\n", stderr );
397     switch ( functionCode ) {
398      case INT32_TO_FLOAT32:
399         test_a_int32_z_float32( slow_int32_to_float32, int32_to_float32 );
400         break;
401      case INT32_TO_FLOAT64:
402         test_a_int32_z_float64( slow_int32_to_float64, int32_to_float64 );
403         break;
404 #ifdef FLOATX80
405      case INT32_TO_FLOATX80:
406         test_a_int32_z_floatx80( slow_int32_to_floatx80, int32_to_floatx80 );
407         break;
408 #endif
409 #ifdef FLOAT128
410      case INT32_TO_FLOAT128:
411         test_a_int32_z_float128( slow_int32_to_float128, int32_to_float128 );
412         break;
413 #endif
414 #ifdef BITS64
415      case INT64_TO_FLOAT32:
416         test_a_int64_z_float32( slow_int64_to_float32, int64_to_float32 );
417         break;
418      case INT64_TO_FLOAT64:
419         test_a_int64_z_float64( slow_int64_to_float64, int64_to_float64 );
420         break;
421 #ifdef FLOATX80
422      case INT64_TO_FLOATX80:
423         test_a_int64_z_floatx80( slow_int64_to_floatx80, int64_to_floatx80 );
424         break;
425 #endif
426 #ifdef FLOAT128
427      case INT64_TO_FLOAT128:
428         test_a_int64_z_float128( slow_int64_to_float128, int64_to_float128 );
429         break;
430 #endif
431 #endif
432      case FLOAT32_TO_INT32:
433         test_a_float32_z_int32( slow_float32_to_int32, float32_to_int32 );
434         break;
435      case FLOAT32_TO_INT32_ROUND_TO_ZERO:
436         test_a_float32_z_int32(
437             slow_float32_to_int32_round_to_zero,
438             float32_to_int32_round_to_zero
439         );
440         break;
441 #ifdef BITS64
442      case FLOAT32_TO_INT64:
443         test_a_float32_z_int64( slow_float32_to_int64, float32_to_int64 );
444         break;
445      case FLOAT32_TO_INT64_ROUND_TO_ZERO:
446         test_a_float32_z_int64(
447             slow_float32_to_int64_round_to_zero,
448             float32_to_int64_round_to_zero
449         );
450         break;
451 #endif
452      case FLOAT32_TO_FLOAT64:
453         test_a_float32_z_float64(
454             slow_float32_to_float64, float32_to_float64 );
455         break;
456 #ifdef FLOATX80
457      case FLOAT32_TO_FLOATX80:
458         test_a_float32_z_floatx80(
459             slow_float32_to_floatx80, float32_to_floatx80 );
460         break;
461 #endif
462 #ifdef FLOAT128
463      case FLOAT32_TO_FLOAT128:
464         test_a_float32_z_float128(
465             slow_float32_to_float128, float32_to_float128 );
466         break;
467 #endif
468      case FLOAT32_ROUND_TO_INT:
469         test_az_float32( slow_float32_round_to_int, float32_round_to_int );
470         break;
471      case FLOAT32_ADD:
472         test_abz_float32( slow_float32_add, float32_add );
473         break;
474      case FLOAT32_SUB:
475         test_abz_float32( slow_float32_sub, float32_sub );
476         break;
477      case FLOAT32_MUL:
478         test_abz_float32( slow_float32_mul, float32_mul );
479         break;
480      case FLOAT32_DIV:
481         test_abz_float32( slow_float32_div, float32_div );
482         break;
483      case FLOAT32_REM:
484         test_abz_float32( slow_float32_rem, float32_rem );
485         break;
486      case FLOAT32_SQRT:
487         test_az_float32( slow_float32_sqrt, float32_sqrt );
488         break;
489      case FLOAT32_EQ:
490         test_ab_float32_z_flag( slow_float32_eq, float32_eq );
491         break;
492      case FLOAT32_LE:
493         test_ab_float32_z_flag( slow_float32_le, float32_le );
494         break;
495      case FLOAT32_LT:
496         test_ab_float32_z_flag( slow_float32_lt, float32_lt );
497         break;
498      case FLOAT32_EQ_SIGNALING:
499         test_ab_float32_z_flag(
500             slow_float32_eq_signaling, float32_eq_signaling );
501         break;
502      case FLOAT32_LE_QUIET:
503         test_ab_float32_z_flag( slow_float32_le_quiet, float32_le_quiet );
504         break;
505      case FLOAT32_LT_QUIET:
506         test_ab_float32_z_flag( slow_float32_lt_quiet, float32_lt_quiet );
507         break;
508      case FLOAT64_TO_INT32:
509         test_a_float64_z_int32( slow_float64_to_int32, float64_to_int32 );
510         break;
511      case FLOAT64_TO_INT32_ROUND_TO_ZERO:
512         test_a_float64_z_int32(
513             slow_float64_to_int32_round_to_zero,
514             float64_to_int32_round_to_zero
515         );
516         break;
517 #ifdef BITS64
518      case FLOAT64_TO_INT64:
519         test_a_float64_z_int64( slow_float64_to_int64, float64_to_int64 );
520         break;
521      case FLOAT64_TO_INT64_ROUND_TO_ZERO:
522         test_a_float64_z_int64(
523             slow_float64_to_int64_round_to_zero,
524             float64_to_int64_round_to_zero
525         );
526         break;
527 #endif
528      case FLOAT64_TO_FLOAT32:
529         test_a_float64_z_float32(
530             slow_float64_to_float32, float64_to_float32 );
531         break;
532 #ifdef FLOATX80
533      case FLOAT64_TO_FLOATX80:
534         test_a_float64_z_floatx80(
535             slow_float64_to_floatx80, float64_to_floatx80 );
536         break;
537 #endif
538 #ifdef FLOAT128
539      case FLOAT64_TO_FLOAT128:
540         test_a_float64_z_float128(
541             slow_float64_to_float128, float64_to_float128 );
542         break;
543 #endif
544      case FLOAT64_ROUND_TO_INT:
545         test_az_float64( slow_float64_round_to_int, float64_round_to_int );
546         break;
547      case FLOAT64_ADD:
548         test_abz_float64( slow_float64_add, float64_add );
549         break;
550      case FLOAT64_SUB:
551         test_abz_float64( slow_float64_sub, float64_sub );
552         break;
553      case FLOAT64_MUL:
554         test_abz_float64( slow_float64_mul, float64_mul );
555         break;
556      case FLOAT64_DIV:
557         test_abz_float64( slow_float64_div, float64_div );
558         break;
559      case FLOAT64_REM:
560         test_abz_float64( slow_float64_rem, float64_rem );
561         break;
562      case FLOAT64_SQRT:
563         test_az_float64( slow_float64_sqrt, float64_sqrt );
564         break;
565      case FLOAT64_EQ:
566         test_ab_float64_z_flag( slow_float64_eq, float64_eq );
567         break;
568      case FLOAT64_LE:
569         test_ab_float64_z_flag( slow_float64_le, float64_le );
570         break;
571      case FLOAT64_LT:
572         test_ab_float64_z_flag( slow_float64_lt, float64_lt );
573         break;
574      case FLOAT64_EQ_SIGNALING:
575         test_ab_float64_z_flag(
576             slow_float64_eq_signaling, float64_eq_signaling );
577         break;
578      case FLOAT64_LE_QUIET:
579         test_ab_float64_z_flag( slow_float64_le_quiet, float64_le_quiet );
580         break;
581      case FLOAT64_LT_QUIET:
582         test_ab_float64_z_flag( slow_float64_lt_quiet, float64_lt_quiet );
583         break;
584 #ifdef FLOATX80
585      case FLOATX80_TO_INT32:
586         test_a_floatx80_z_int32( slow_floatx80_to_int32, floatx80_to_int32 );
587         break;
588      case FLOATX80_TO_INT32_ROUND_TO_ZERO:
589         test_a_floatx80_z_int32(
590             slow_floatx80_to_int32_round_to_zero,
591             floatx80_to_int32_round_to_zero
592         );
593         break;
594 #ifdef BITS64
595      case FLOATX80_TO_INT64:
596         test_a_floatx80_z_int64( slow_floatx80_to_int64, floatx80_to_int64 );
597         break;
598      case FLOATX80_TO_INT64_ROUND_TO_ZERO:
599         test_a_floatx80_z_int64(
600             slow_floatx80_to_int64_round_to_zero,
601             floatx80_to_int64_round_to_zero
602         );
603         break;
604 #endif
605      case FLOATX80_TO_FLOAT32:
606         test_a_floatx80_z_float32(
607             slow_floatx80_to_float32, floatx80_to_float32 );
608         break;
609      case FLOATX80_TO_FLOAT64:
610         test_a_floatx80_z_float64(
611             slow_floatx80_to_float64, floatx80_to_float64 );
612         break;
613 #ifdef FLOAT128
614      case FLOATX80_TO_FLOAT128:
615         test_a_floatx80_z_float128(
616             slow_floatx80_to_float128, floatx80_to_float128 );
617         break;
618 #endif
619      case FLOATX80_ROUND_TO_INT:
620         test_az_floatx80( slow_floatx80_round_to_int, floatx80_round_to_int );
621         break;
622      case FLOATX80_ADD:
623         test_abz_floatx80( slow_floatx80_add, floatx80_add );
624         break;
625      case FLOATX80_SUB:
626         test_abz_floatx80( slow_floatx80_sub, floatx80_sub );
627         break;
628      case FLOATX80_MUL:
629         test_abz_floatx80( slow_floatx80_mul, floatx80_mul );
630         break;
631      case FLOATX80_DIV:
632         test_abz_floatx80( slow_floatx80_div, floatx80_div );
633         break;
634      case FLOATX80_REM:
635         test_abz_floatx80( slow_floatx80_rem, floatx80_rem );
636         break;
637      case FLOATX80_SQRT:
638         test_az_floatx80( slow_floatx80_sqrt, floatx80_sqrt );
639         break;
640      case FLOATX80_EQ:
641         test_ab_floatx80_z_flag( slow_floatx80_eq, floatx80_eq );
642         break;
643      case FLOATX80_LE:
644         test_ab_floatx80_z_flag( slow_floatx80_le, floatx80_le );
645         break;
646      case FLOATX80_LT:
647         test_ab_floatx80_z_flag( slow_floatx80_lt, floatx80_lt );
648         break;
649      case FLOATX80_EQ_SIGNALING:
650         test_ab_floatx80_z_flag(
651             slow_floatx80_eq_signaling, floatx80_eq_signaling );
652         break;
653      case FLOATX80_LE_QUIET:
654         test_ab_floatx80_z_flag( slow_floatx80_le_quiet, floatx80_le_quiet );
655         break;
656      case FLOATX80_LT_QUIET:
657         test_ab_floatx80_z_flag( slow_floatx80_lt_quiet, floatx80_lt_quiet );
658         break;
659 #endif
660 #ifdef FLOAT128
661      case FLOAT128_TO_INT32:
662         test_a_float128_z_int32( slow_float128_to_int32, float128_to_int32 );
663         break;
664      case FLOAT128_TO_INT32_ROUND_TO_ZERO:
665         test_a_float128_z_int32(
666             slow_float128_to_int32_round_to_zero,
667             float128_to_int32_round_to_zero
668         );
669         break;
670 #ifdef BITS64
671      case FLOAT128_TO_INT64:
672         test_a_float128_z_int64( slow_float128_to_int64, float128_to_int64 );
673         break;
674      case FLOAT128_TO_INT64_ROUND_TO_ZERO:
675         test_a_float128_z_int64(
676             slow_float128_to_int64_round_to_zero,
677             float128_to_int64_round_to_zero
678         );
679         break;
680 #endif
681      case FLOAT128_TO_FLOAT32:
682         test_a_float128_z_float32(
683             slow_float128_to_float32, float128_to_float32 );
684         break;
685      case FLOAT128_TO_FLOAT64:
686         test_a_float128_z_float64(
687             slow_float128_to_float64, float128_to_float64 );
688         break;
689 #ifdef FLOATX80
690      case FLOAT128_TO_FLOATX80:
691         test_a_float128_z_floatx80(
692             slow_float128_to_floatx80, float128_to_floatx80 );
693         break;
694 #endif
695      case FLOAT128_ROUND_TO_INT:
696         test_az_float128( slow_float128_round_to_int, float128_round_to_int );
697         break;
698      case FLOAT128_ADD:
699         test_abz_float128( slow_float128_add, float128_add );
700         break;
701      case FLOAT128_SUB:
702         test_abz_float128( slow_float128_sub, float128_sub );
703         break;
704      case FLOAT128_MUL:
705         test_abz_float128( slow_float128_mul, float128_mul );
706         break;
707      case FLOAT128_DIV:
708         test_abz_float128( slow_float128_div, float128_div );
709         break;
710      case FLOAT128_REM:
711         test_abz_float128( slow_float128_rem, float128_rem );
712         break;
713      case FLOAT128_SQRT:
714         test_az_float128( slow_float128_sqrt, float128_sqrt );
715         break;
716      case FLOAT128_EQ:
717         test_ab_float128_z_flag( slow_float128_eq, float128_eq );
718         break;
719      case FLOAT128_LE:
720         test_ab_float128_z_flag( slow_float128_le, float128_le );
721         break;
722      case FLOAT128_LT:
723         test_ab_float128_z_flag( slow_float128_lt, float128_lt );
724         break;
725      case FLOAT128_EQ_SIGNALING:
726         test_ab_float128_z_flag(
727             slow_float128_eq_signaling, float128_eq_signaling );
728         break;
729      case FLOAT128_LE_QUIET:
730         test_ab_float128_z_flag( slow_float128_le_quiet, float128_le_quiet );
731         break;
732      case FLOAT128_LT_QUIET:
733         test_ab_float128_z_flag( slow_float128_lt_quiet, float128_lt_quiet );
734         break;
735 #endif
736     }
737     if ( ( errorStop && anyErrors ) || stop ) exitWithStatus();
738
739 }
740
741 static void
742  testFunction(
743      uint8 functionCode,
744      int8 roundingPrecisionIn,
745      int8 roundingModeIn,
746      int8 tininessModeIn
747  )
748 {
749     int8 roundingPrecision, roundingMode, tininessMode;
750
751     roundingPrecision = 32;
752     for (;;) {
753         if ( ! functions[ functionCode ].roundingPrecision ) {
754             roundingPrecision = 0;
755         }
756         else if ( roundingPrecisionIn ) {
757             roundingPrecision = roundingPrecisionIn;
758         }
759         for ( roundingMode = 1;
760               roundingMode < NUM_ROUNDINGMODES;
761               ++roundingMode
762             ) {
763             if ( ! functions[ functionCode ].roundingMode ) {
764                 roundingMode = 0;
765             }
766             else if ( roundingModeIn ) {
767                 roundingMode = roundingModeIn;
768             }
769             for ( tininessMode = 1;
770                   tininessMode < NUM_TININESSMODES;
771                   ++tininessMode
772                 ) {
773                 if (    ( roundingPrecision == 32 )
774                      || ( roundingPrecision == 64 ) ) {
775                     if ( ! functions[ functionCode ]
776                                .tininessModeAtReducedPrecision
777                        ) {
778                         tininessMode = 0;
779                     }
780                     else if ( tininessModeIn ) {
781                         tininessMode = tininessModeIn;
782                     }
783                 }
784                 else {
785                     if ( ! functions[ functionCode ].tininessMode ) {
786                         tininessMode = 0;
787                     }
788                     else if ( tininessModeIn ) {
789                         tininessMode = tininessModeIn;
790                     }
791                 }
792                 testFunctionVariety(
793                     functionCode, roundingPrecision, roundingMode, tininessMode
794                 );
795                 if ( tininessModeIn || ! tininessMode ) break;
796             }
797             if ( roundingModeIn || ! roundingMode ) break;
798         }
799         if ( roundingPrecisionIn || ! roundingPrecision ) break;
800         if ( roundingPrecision == 80 ) {
801             break;
802         }
803         else if ( roundingPrecision == 64 ) {
804             roundingPrecision = 80;
805         }
806         else if ( roundingPrecision == 32 ) {
807             roundingPrecision = 64;
808         }
809     }
810
811 }
812
813 int
814 main( int argc, char **argv )
815 {
816     char *argPtr;
817     flag functionArgument;
818     uint8 functionCode;
819     int8 operands, roundingPrecision, roundingMode, tininessMode;
820
821     fail_programName = "testsoftfloat";
822     if ( argc <= 1 ) goto writeHelpMessage;
823     testCases_setLevel( 1 );
824     trueName = "true";
825     testName = "soft";
826     errorStop = FALSE;
827     forever = FALSE;
828     maxErrorCount = 20;
829     trueFlagsPtr = &slow_float_exception_flags;
830     testFlagsFunctionPtr = clearFlags;
831     functionArgument = FALSE;
832     functionCode = 0;
833     operands = 0;
834     roundingPrecision = 0;
835     roundingMode = 0;
836     tininessMode = 0;
837     --argc;
838     ++argv;
839     while ( argc && ( argPtr = argv[ 0 ] ) ) {
840         if ( argPtr[ 0 ] == '-' ) ++argPtr;
841         if ( strcmp( argPtr, "help" ) == 0 ) {
842  writeHelpMessage:
843             fputs(
844 "testsoftfloat [<option>...] <function>\n"
845 "  <option>:  (* is default)\n"
846 "    -help            --Write this message and exit.\n"
847 "    -level <num>     --Testing level <num> (1 or 2).\n"
848 " *  -level 1\n"
849 "    -errors <num>    --Stop each function test after <num> errors.\n"
850 " *  -errors 20\n"
851 "    -errorstop       --Exit after first function with any error.\n"
852 "    -forever         --Test one function repeatedly (implies `-level 2').\n"
853 #ifdef FLOATX80
854 "    -precision32     --Only test rounding precision equivalent to float32.\n"
855 "    -precision64     --Only test rounding precision equivalent to float64.\n"
856 "    -precision80     --Only test maximum rounding precision.\n"
857 #endif
858 "    -nearesteven     --Only test rounding to nearest/even.\n"
859 "    -tozero          --Only test rounding to zero.\n"
860 "    -down            --Only test rounding down.\n"
861 "    -up              --Only test rounding up.\n"
862 "    -tininessbefore  --Only test underflow tininess before rounding.\n"
863 "    -tininessafter   --Only test underflow tininess after rounding.\n"
864 "  <function>:\n"
865 "    int32_to_<float>                 <float>_add   <float>_eq\n"
866 "    <float>_to_int32                 <float>_sub   <float>_le\n"
867 "    <float>_to_int32_round_to_zero   <float>_mul   <float>_lt\n"
868 #ifdef BITS64
869 "    int64_to_<float>                 <float>_div   <float>_eq_signaling\n"
870 "    <float>_to_int64                 <float>_rem   <float>_le_quiet\n"
871 "    <float>_to_int64_round_to_zero                 <float>_lt_quiet\n"
872 "    <float>_to_<float>\n"
873 "    <float>_round_to_int\n"
874 "    <float>_sqrt\n"
875 #else
876 "    <float>_to_<float>               <float>_div   <float>_eq_signaling\n"
877 "    <float>_round_to_int             <float>_rem   <float>_le_quiet\n"
878 "    <float>_sqrt                                   <float>_lt_quiet\n"
879 #endif
880 "    -all1            --All 1-operand functions.\n"
881 "    -all2            --All 2-operand functions.\n"
882 "    -all             --All functions.\n"
883 "  <float>:\n"
884 "    float32          --Single precision.\n"
885 "    float64          --Double precision.\n"
886 #ifdef FLOATX80
887 "    floatx80         --Extended double precision.\n"
888 #endif
889 #ifdef FLOAT128
890 "    float128         --Quadruple precision.\n"
891 #endif
892                 ,
893                 stdout
894             );
895             return EXIT_SUCCESS;
896         }
897         else if ( strcmp( argPtr, "level" ) == 0 ) {
898             if ( argc < 2 ) goto optionError;
899             testCases_setLevel( atoi( argv[ 1 ] ) );
900             --argc;
901             ++argv;
902         }
903         else if ( strcmp( argPtr, "level1" ) == 0 ) {
904             testCases_setLevel( 1 );
905         }
906         else if ( strcmp( argPtr, "level2" ) == 0 ) {
907             testCases_setLevel( 2 );
908         }
909         else if ( strcmp( argPtr, "errors" ) == 0 ) {
910             if ( argc < 2 ) {
911      optionError:
912                 fail( "`%s' option requires numeric argument", argv[ 0 ] );
913             }
914             maxErrorCount = atoi( argv[ 1 ] );
915             --argc;
916             ++argv;
917         }
918         else if ( strcmp( argPtr, "errorstop" ) == 0 ) {
919             errorStop = TRUE;
920         }
921         else if ( strcmp( argPtr, "forever" ) == 0 ) {
922             testCases_setLevel( 2 );
923             forever = TRUE;
924         }
925 #ifdef FLOATX80
926         else if ( strcmp( argPtr, "precision32" ) == 0 ) {
927             roundingPrecision = 32;
928         }
929         else if ( strcmp( argPtr, "precision64" ) == 0 ) {
930             roundingPrecision = 64;
931         }
932         else if ( strcmp( argPtr, "precision80" ) == 0 ) {
933             roundingPrecision = 80;
934         }
935 #endif
936         else if (    ( strcmp( argPtr, "nearesteven" ) == 0 )
937                   || ( strcmp( argPtr, "nearest_even" ) == 0 ) ) {
938             roundingMode = ROUND_NEAREST_EVEN;
939         }
940         else if (    ( strcmp( argPtr, "tozero" ) == 0 )
941                   || ( strcmp( argPtr, "to_zero" ) == 0 ) ) {
942             roundingMode = ROUND_TO_ZERO;
943         }
944         else if ( strcmp( argPtr, "down" ) == 0 ) {
945             roundingMode = ROUND_DOWN;
946         }
947         else if ( strcmp( argPtr, "up" ) == 0 ) {
948             roundingMode = ROUND_UP;
949         }
950         else if ( strcmp( argPtr, "tininessbefore" ) == 0 ) {
951             tininessMode = TININESS_BEFORE_ROUNDING;
952         }
953         else if ( strcmp( argPtr, "tininessafter" ) == 0 ) {
954             tininessMode = TININESS_AFTER_ROUNDING;
955         }
956         else if ( strcmp( argPtr, "all1" ) == 0 ) {
957             functionArgument = TRUE;
958             functionCode = 0;
959             operands = 1;
960         }
961         else if ( strcmp( argPtr, "all2" ) == 0 ) {
962             functionArgument = TRUE;
963             functionCode = 0;
964             operands = 2;
965         }
966         else if ( strcmp( argPtr, "all" ) == 0 ) {
967             functionArgument = TRUE;
968             functionCode = 0;
969             operands = 0;
970         }
971         else {
972             for ( functionCode = 1;
973                   functionCode < NUM_FUNCTIONS;
974                   ++functionCode
975                 ) {
976                 if ( strcmp( argPtr, functions[ functionCode ].name ) == 0 ) {
977                     break;
978                 }
979             }
980             if ( functionCode == NUM_FUNCTIONS ) {
981                 fail( "Invalid option or function `%s'", argv[ 0 ] );
982             }
983             functionArgument = TRUE;
984         }
985         --argc;
986         ++argv;
987     }
988     if ( ! functionArgument ) fail( "Function argument required" );
989     (void) signal( SIGINT, catchSIGINT );
990     (void) signal( SIGTERM, catchSIGINT );
991     if ( functionCode ) {
992         if ( forever ) {
993             if ( ! roundingPrecision ) roundingPrecision = 80;
994             if ( ! roundingMode ) roundingMode = ROUND_NEAREST_EVEN;
995         }
996         testFunction(
997             functionCode, roundingPrecision, roundingMode, tininessMode );
998     }
999     else {
1000         if ( operands == 1 ) {
1001             for ( functionCode = 1;
1002                   functionCode < NUM_FUNCTIONS;
1003                   ++functionCode
1004                 ) {
1005                 if ( functions[ functionCode ].numInputs == 1 ) {
1006                     testFunction(
1007                         functionCode,
1008                         roundingPrecision,
1009                         roundingMode,
1010                         tininessMode
1011                     );
1012                 }
1013             }
1014         }
1015         else if ( operands == 2 ) {
1016             for ( functionCode = 1;
1017                   functionCode < NUM_FUNCTIONS;
1018                   ++functionCode
1019                 ) {
1020                 if ( functions[ functionCode ].numInputs == 2 ) {
1021                     testFunction(
1022                         functionCode,
1023                         roundingPrecision,
1024                         roundingMode,
1025                         tininessMode
1026                     );
1027                 }
1028             }
1029         }
1030         else {
1031             for ( functionCode = 1;
1032                   functionCode < NUM_FUNCTIONS;
1033                   ++functionCode
1034                 ) {
1035                 testFunction(
1036                     functionCode, roundingPrecision, roundingMode, tininessMode
1037                 );
1038             }
1039         }
1040     }
1041     exitWithStatus();
1042
1043 }
1044