1
2/*
3===============================================================================
4
5This C source file is part of TestFloat, Release 2a, a package of programs
6for testing the correctness of floating-point arithmetic complying to the
7IEC/IEEE Standard for Floating-Point.
8
9Written by John R. Hauser.  More information is available through the Web
10page `http://HTTP.CS.Berkeley.EDU/~jhauser/arithmetic/TestFloat.html'.
11
12THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE.  Although reasonable effort
13has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
14TIMES RESULT IN INCORRECT BEHAVIOR.  USE OF THIS SOFTWARE IS RESTRICTED TO
15PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY
16AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE.
17
18Derivative works are acceptable, even for commercial purposes, so long as
19(1) they include prominent notice that the work is derivative, and (2) they
20include prominent notice akin to these four paragraphs for those parts of
21this 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
39static void catchSIGINT( int signalCode )
40{
41
42    if ( stop ) exit( EXIT_FAILURE );
43    stop = TRUE;
44
45}
46
47int8 clearFlags( void )
48{
49    int8 flags;
50
51    flags = float_exception_flags;
52    float_exception_flags = 0;
53    return flags;
54
55}
56
57enum {
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};
182static 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
313enum {
314    ROUND_NEAREST_EVEN = 1,
315    ROUND_TO_ZERO,
316    ROUND_DOWN,
317    ROUND_UP,
318    NUM_ROUNDINGMODES
319};
320enum {
321    TININESS_BEFORE_ROUNDING = 1,
322    TININESS_AFTER_ROUNDING,
323    NUM_TININESSMODES
324};
325
326static 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
741static 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
813int
814main( 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
1045