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