1*1f21f64aSMarius Strobl 
2*1f21f64aSMarius Strobl /*
3*1f21f64aSMarius Strobl ===============================================================================
4*1f21f64aSMarius Strobl 
5*1f21f64aSMarius Strobl This C source file is part of TestFloat, Release 2a, a package of programs
6*1f21f64aSMarius Strobl for testing the correctness of floating-point arithmetic complying to the
7*1f21f64aSMarius Strobl IEC/IEEE Standard for Floating-Point.
8*1f21f64aSMarius Strobl 
9*1f21f64aSMarius Strobl Written by John R. Hauser.  More information is available through the Web
10*1f21f64aSMarius Strobl page `http://HTTP.CS.Berkeley.EDU/~jhauser/arithmetic/TestFloat.html'.
11*1f21f64aSMarius Strobl 
12*1f21f64aSMarius Strobl THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE.  Although reasonable effort
13*1f21f64aSMarius Strobl has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
14*1f21f64aSMarius Strobl TIMES RESULT IN INCORRECT BEHAVIOR.  USE OF THIS SOFTWARE IS RESTRICTED TO
15*1f21f64aSMarius Strobl PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY
16*1f21f64aSMarius Strobl AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE.
17*1f21f64aSMarius Strobl 
18*1f21f64aSMarius Strobl Derivative works are acceptable, even for commercial purposes, so long as
19*1f21f64aSMarius Strobl (1) they include prominent notice that the work is derivative, and (2) they
20*1f21f64aSMarius Strobl include prominent notice akin to these four paragraphs for those parts of
21*1f21f64aSMarius Strobl this code that are retained.
22*1f21f64aSMarius Strobl 
23*1f21f64aSMarius Strobl ===============================================================================
24*1f21f64aSMarius Strobl */
25*1f21f64aSMarius Strobl 
26*1f21f64aSMarius Strobl #include <sys/cdefs.h>
27*1f21f64aSMarius Strobl __FBSDID("$FreeBSD$");
28*1f21f64aSMarius Strobl 
29*1f21f64aSMarius Strobl #include <stdlib.h>
30*1f21f64aSMarius Strobl #include <signal.h>
31*1f21f64aSMarius Strobl #include <string.h>
32*1f21f64aSMarius Strobl #include "milieu.h"
33*1f21f64aSMarius Strobl #include "fail.h"
34*1f21f64aSMarius Strobl #include "softfloat.h"
35*1f21f64aSMarius Strobl #include "testCases.h"
36*1f21f64aSMarius Strobl #include "testLoops.h"
37*1f21f64aSMarius Strobl #include "systflags.h"
38*1f21f64aSMarius Strobl #include "testFunction.h"
39*1f21f64aSMarius Strobl 
catchSIGINT(int signalCode)40*1f21f64aSMarius Strobl static void catchSIGINT( int signalCode )
41*1f21f64aSMarius Strobl {
42*1f21f64aSMarius Strobl 
43*1f21f64aSMarius Strobl     if ( stop ) exit( EXIT_FAILURE );
44*1f21f64aSMarius Strobl     stop = TRUE;
45*1f21f64aSMarius Strobl 
46*1f21f64aSMarius Strobl }
47*1f21f64aSMarius Strobl 
48*1f21f64aSMarius Strobl int
main(int argc,char ** argv)49*1f21f64aSMarius Strobl main( int argc, char **argv )
50*1f21f64aSMarius Strobl {
51*1f21f64aSMarius Strobl     char *argPtr;
52*1f21f64aSMarius Strobl     flag functionArgument;
53*1f21f64aSMarius Strobl     uint8 functionCode;
54*1f21f64aSMarius Strobl     int8 operands, roundingPrecision, roundingMode;
55*1f21f64aSMarius Strobl 
56*1f21f64aSMarius Strobl     fail_programName = "testfloat";
57*1f21f64aSMarius Strobl     if ( argc <= 1 ) goto writeHelpMessage;
58*1f21f64aSMarius Strobl     testCases_setLevel( 1 );
59*1f21f64aSMarius Strobl     trueName = "soft";
60*1f21f64aSMarius Strobl     testName = "syst";
61*1f21f64aSMarius Strobl     errorStop = FALSE;
62*1f21f64aSMarius Strobl     forever = FALSE;
63*1f21f64aSMarius Strobl     maxErrorCount = 20;
64*1f21f64aSMarius Strobl     trueFlagsPtr = &float_exception_flags;
65*1f21f64aSMarius Strobl     testFlagsFunctionPtr = syst_float_flags_clear;
66*1f21f64aSMarius Strobl     tininessModeName = 0;
67*1f21f64aSMarius Strobl     functionArgument = FALSE;
68*1f21f64aSMarius Strobl     functionCode = 0;
69*1f21f64aSMarius Strobl     operands = 0;
70*1f21f64aSMarius Strobl     roundingPrecision = 0;
71*1f21f64aSMarius Strobl     roundingMode = 0;
72*1f21f64aSMarius Strobl     --argc;
73*1f21f64aSMarius Strobl     ++argv;
74*1f21f64aSMarius Strobl     while ( argc && ( argPtr = argv[ 0 ] ) ) {
75*1f21f64aSMarius Strobl         if ( argPtr[ 0 ] == '-' ) ++argPtr;
76*1f21f64aSMarius Strobl         if ( strcmp( argPtr, "help" ) == 0 ) {
77*1f21f64aSMarius Strobl  writeHelpMessage:
78*1f21f64aSMarius Strobl             fputs(
79*1f21f64aSMarius Strobl "testfloat [<option>...] <function>\n"
80*1f21f64aSMarius Strobl "  <option>:  (* is default)\n"
81*1f21f64aSMarius Strobl "    -help            --Write this message and exit.\n"
82*1f21f64aSMarius Strobl "    -list            --List all testable functions and exit.\n"
83*1f21f64aSMarius Strobl "    -level <num>     --Testing level <num> (1 or 2).\n"
84*1f21f64aSMarius Strobl " *  -level 1\n"
85*1f21f64aSMarius Strobl "    -errors <num>    --Stop each function test after <num> errors.\n"
86*1f21f64aSMarius Strobl " *  -errors 20\n"
87*1f21f64aSMarius Strobl "    -errorstop       --Exit after first function with any error.\n"
88*1f21f64aSMarius Strobl "    -forever         --Test one function repeatedly (implies `-level 2').\n"
89*1f21f64aSMarius Strobl "    -checkNaNs       --Check for bitwise correctness of NaN results.\n"
90*1f21f64aSMarius Strobl #ifdef FLOATX80
91*1f21f64aSMarius Strobl "    -precision32     --Only test rounding precision equivalent to float32.\n"
92*1f21f64aSMarius Strobl "    -precision64     --Only test rounding precision equivalent to float64.\n"
93*1f21f64aSMarius Strobl "    -precision80     --Only test maximum rounding precision.\n"
94*1f21f64aSMarius Strobl #endif
95*1f21f64aSMarius Strobl "    -nearesteven     --Only test rounding to nearest/even.\n"
96*1f21f64aSMarius Strobl "    -tozero          --Only test rounding to zero.\n"
97*1f21f64aSMarius Strobl "    -down            --Only test rounding down.\n"
98*1f21f64aSMarius Strobl "    -up              --Only test rounding up.\n"
99*1f21f64aSMarius Strobl "    -tininessbefore  --Underflow tininess detected before rounding.\n"
100*1f21f64aSMarius Strobl "    -tininessafter   --Underflow tininess detected after rounding.\n"
101*1f21f64aSMarius Strobl "  <function>:\n"
102*1f21f64aSMarius Strobl "    int32_to_<float>                 <float>_add   <float>_eq\n"
103*1f21f64aSMarius Strobl "    <float>_to_int32                 <float>_sub   <float>_le\n"
104*1f21f64aSMarius Strobl "    <float>_to_int32_round_to_zero   <float>_mul   <float>_lt\n"
105*1f21f64aSMarius Strobl #ifdef BITS64
106*1f21f64aSMarius Strobl "    int64_to_<float>                 <float>_div   <float>_eq_signaling\n"
107*1f21f64aSMarius Strobl "    <float>_to_int64                 <float>_rem   <float>_le_quiet\n"
108*1f21f64aSMarius Strobl "    <float>_to_int64_round_to_zero                 <float>_lt_quiet\n"
109*1f21f64aSMarius Strobl "    <float>_to_<float>\n"
110*1f21f64aSMarius Strobl "    <float>_round_to_int\n"
111*1f21f64aSMarius Strobl "    <float>_sqrt\n"
112*1f21f64aSMarius Strobl #else
113*1f21f64aSMarius Strobl "    <float>_to_<float>               <float>_div   <float>_eq_signaling\n"
114*1f21f64aSMarius Strobl "    <float>_round_to_int             <float>_rem   <float>_le_quiet\n"
115*1f21f64aSMarius Strobl "    <float>_sqrt                                   <float>_lt_quiet\n"
116*1f21f64aSMarius Strobl #endif
117*1f21f64aSMarius Strobl "    -all1            --All 1-operand functions.\n"
118*1f21f64aSMarius Strobl "    -all2            --All 2-operand functions.\n"
119*1f21f64aSMarius Strobl "    -all             --All functions.\n"
120*1f21f64aSMarius Strobl "  <float>:\n"
121*1f21f64aSMarius Strobl "    float32          --Single precision.\n"
122*1f21f64aSMarius Strobl "    float64          --Double precision.\n"
123*1f21f64aSMarius Strobl #ifdef FLOATX80
124*1f21f64aSMarius Strobl "    floatx80         --Extended double precision.\n"
125*1f21f64aSMarius Strobl #endif
126*1f21f64aSMarius Strobl #ifdef FLOAT128
127*1f21f64aSMarius Strobl "    float128         --Quadruple precision.\n"
128*1f21f64aSMarius Strobl #endif
129*1f21f64aSMarius Strobl                 ,
130*1f21f64aSMarius Strobl                 stdout
131*1f21f64aSMarius Strobl             );
132*1f21f64aSMarius Strobl             return EXIT_SUCCESS;
133*1f21f64aSMarius Strobl         }
134*1f21f64aSMarius Strobl         else if ( strcmp( argPtr, "list" ) == 0 ) {
135*1f21f64aSMarius Strobl             for ( functionCode = 1;
136*1f21f64aSMarius Strobl                   functionCode < NUM_FUNCTIONS;
137*1f21f64aSMarius Strobl                   ++functionCode
138*1f21f64aSMarius Strobl                 ) {
139*1f21f64aSMarius Strobl                 if ( functionExists[ functionCode ] ) {
140*1f21f64aSMarius Strobl                     puts( functions[ functionCode ].name );
141*1f21f64aSMarius Strobl                 }
142*1f21f64aSMarius Strobl             }
143*1f21f64aSMarius Strobl             return EXIT_SUCCESS;
144*1f21f64aSMarius Strobl         }
145*1f21f64aSMarius Strobl         else if ( strcmp( argPtr, "level" ) == 0 ) {
146*1f21f64aSMarius Strobl             if ( argc < 2 ) goto optionError;
147*1f21f64aSMarius Strobl             testCases_setLevel( atoi( argv[ 1 ] ) );
148*1f21f64aSMarius Strobl             --argc;
149*1f21f64aSMarius Strobl             ++argv;
150*1f21f64aSMarius Strobl         }
151*1f21f64aSMarius Strobl         else if ( strcmp( argPtr, "level1" ) == 0 ) {
152*1f21f64aSMarius Strobl             testCases_setLevel( 1 );
153*1f21f64aSMarius Strobl         }
154*1f21f64aSMarius Strobl         else if ( strcmp( argPtr, "level2" ) == 0 ) {
155*1f21f64aSMarius Strobl             testCases_setLevel( 2 );
156*1f21f64aSMarius Strobl         }
157*1f21f64aSMarius Strobl         else if ( strcmp( argPtr, "errors" ) == 0 ) {
158*1f21f64aSMarius Strobl             if ( argc < 2 ) {
159*1f21f64aSMarius Strobl      optionError:
160*1f21f64aSMarius Strobl                 fail( "`%s' option requires numeric argument", argv[ 0 ] );
161*1f21f64aSMarius Strobl             }
162*1f21f64aSMarius Strobl             maxErrorCount = atoi( argv[ 1 ] );
163*1f21f64aSMarius Strobl             --argc;
164*1f21f64aSMarius Strobl             ++argv;
165*1f21f64aSMarius Strobl         }
166*1f21f64aSMarius Strobl         else if ( strcmp( argPtr, "errorstop" ) == 0 ) {
167*1f21f64aSMarius Strobl             errorStop = TRUE;
168*1f21f64aSMarius Strobl         }
169*1f21f64aSMarius Strobl         else if ( strcmp( argPtr, "forever" ) == 0 ) {
170*1f21f64aSMarius Strobl             testCases_setLevel( 2 );
171*1f21f64aSMarius Strobl             forever = TRUE;
172*1f21f64aSMarius Strobl         }
173*1f21f64aSMarius Strobl         else if (    ( strcmp( argPtr, "checkNaNs" ) == 0 )
174*1f21f64aSMarius Strobl                   || ( strcmp( argPtr, "checknans" ) == 0 ) ) {
175*1f21f64aSMarius Strobl             checkNaNs = TRUE;
176*1f21f64aSMarius Strobl         }
177*1f21f64aSMarius Strobl #ifdef FLOATX80
178*1f21f64aSMarius Strobl         else if ( strcmp( argPtr, "precision32" ) == 0 ) {
179*1f21f64aSMarius Strobl             roundingPrecision = 32;
180*1f21f64aSMarius Strobl         }
181*1f21f64aSMarius Strobl         else if ( strcmp( argPtr, "precision64" ) == 0 ) {
182*1f21f64aSMarius Strobl             roundingPrecision = 64;
183*1f21f64aSMarius Strobl         }
184*1f21f64aSMarius Strobl         else if ( strcmp( argPtr, "precision80" ) == 0 ) {
185*1f21f64aSMarius Strobl             roundingPrecision = 80;
186*1f21f64aSMarius Strobl         }
187*1f21f64aSMarius Strobl #endif
188*1f21f64aSMarius Strobl         else if (    ( strcmp( argPtr, "nearesteven" ) == 0 )
189*1f21f64aSMarius Strobl                   || ( strcmp( argPtr, "nearest_even" ) == 0 ) ) {
190*1f21f64aSMarius Strobl             roundingMode = ROUND_NEAREST_EVEN;
191*1f21f64aSMarius Strobl         }
192*1f21f64aSMarius Strobl         else if (    ( strcmp( argPtr, "tozero" ) == 0 )
193*1f21f64aSMarius Strobl                   || ( strcmp( argPtr, "to_zero" ) == 0 ) ) {
194*1f21f64aSMarius Strobl             roundingMode = ROUND_TO_ZERO;
195*1f21f64aSMarius Strobl         }
196*1f21f64aSMarius Strobl         else if ( strcmp( argPtr, "down" ) == 0 ) {
197*1f21f64aSMarius Strobl             roundingMode = ROUND_DOWN;
198*1f21f64aSMarius Strobl         }
199*1f21f64aSMarius Strobl         else if ( strcmp( argPtr, "up" ) == 0 ) {
200*1f21f64aSMarius Strobl             roundingMode = ROUND_UP;
201*1f21f64aSMarius Strobl         }
202*1f21f64aSMarius Strobl         else if ( strcmp( argPtr, "tininessbefore" ) == 0 ) {
203*1f21f64aSMarius Strobl             float_detect_tininess = float_tininess_before_rounding;
204*1f21f64aSMarius Strobl         }
205*1f21f64aSMarius Strobl         else if ( strcmp( argPtr, "tininessafter" ) == 0 ) {
206*1f21f64aSMarius Strobl             float_detect_tininess = float_tininess_after_rounding;
207*1f21f64aSMarius Strobl         }
208*1f21f64aSMarius Strobl         else if ( strcmp( argPtr, "all1" ) == 0 ) {
209*1f21f64aSMarius Strobl             functionArgument = TRUE;
210*1f21f64aSMarius Strobl             functionCode = 0;
211*1f21f64aSMarius Strobl             operands = 1;
212*1f21f64aSMarius Strobl         }
213*1f21f64aSMarius Strobl         else if ( strcmp( argPtr, "all2" ) == 0 ) {
214*1f21f64aSMarius Strobl             functionArgument = TRUE;
215*1f21f64aSMarius Strobl             functionCode = 0;
216*1f21f64aSMarius Strobl             operands = 2;
217*1f21f64aSMarius Strobl         }
218*1f21f64aSMarius Strobl         else if ( strcmp( argPtr, "all" ) == 0 ) {
219*1f21f64aSMarius Strobl             functionArgument = TRUE;
220*1f21f64aSMarius Strobl             functionCode = 0;
221*1f21f64aSMarius Strobl             operands = 0;
222*1f21f64aSMarius Strobl         }
223*1f21f64aSMarius Strobl         else {
224*1f21f64aSMarius Strobl             for ( functionCode = 1;
225*1f21f64aSMarius Strobl                   functionCode < NUM_FUNCTIONS;
226*1f21f64aSMarius Strobl                   ++functionCode
227*1f21f64aSMarius Strobl                 ) {
228*1f21f64aSMarius Strobl                 if ( strcmp( argPtr, functions[ functionCode ].name ) == 0 ) {
229*1f21f64aSMarius Strobl                     break;
230*1f21f64aSMarius Strobl                 }
231*1f21f64aSMarius Strobl             }
232*1f21f64aSMarius Strobl             if ( functionCode == NUM_FUNCTIONS ) {
233*1f21f64aSMarius Strobl                 fail( "Invalid option or function `%s'", argv[ 0 ] );
234*1f21f64aSMarius Strobl             }
235*1f21f64aSMarius Strobl             if ( ! functionExists[ functionCode ] ) {
236*1f21f64aSMarius Strobl                 fail(
237*1f21f64aSMarius Strobl                     "Function `%s' is not supported or cannot be tested",
238*1f21f64aSMarius Strobl                     argPtr
239*1f21f64aSMarius Strobl                 );
240*1f21f64aSMarius Strobl             }
241*1f21f64aSMarius Strobl             functionArgument = TRUE;
242*1f21f64aSMarius Strobl         }
243*1f21f64aSMarius Strobl         --argc;
244*1f21f64aSMarius Strobl         ++argv;
245*1f21f64aSMarius Strobl     }
246*1f21f64aSMarius Strobl     if ( ! functionArgument ) fail( "Function argument required" );
247*1f21f64aSMarius Strobl     (void) signal( SIGINT, catchSIGINT );
248*1f21f64aSMarius Strobl     (void) signal( SIGTERM, catchSIGINT );
249*1f21f64aSMarius Strobl     if ( functionCode ) {
250*1f21f64aSMarius Strobl         if ( forever ) {
251*1f21f64aSMarius Strobl             if ( ! roundingPrecision ) roundingPrecision = 80;
252*1f21f64aSMarius Strobl             if ( ! roundingMode ) roundingMode = ROUND_NEAREST_EVEN;
253*1f21f64aSMarius Strobl         }
254*1f21f64aSMarius Strobl         testFunction( functionCode, roundingPrecision, roundingMode );
255*1f21f64aSMarius Strobl     }
256*1f21f64aSMarius Strobl     else {
257*1f21f64aSMarius Strobl         if ( forever ) {
258*1f21f64aSMarius Strobl             fail( "Can only test one function with `-forever' option" );
259*1f21f64aSMarius Strobl         }
260*1f21f64aSMarius Strobl         if ( operands == 1 ) {
261*1f21f64aSMarius Strobl             for ( functionCode = 1;
262*1f21f64aSMarius Strobl                   functionCode < NUM_FUNCTIONS;
263*1f21f64aSMarius Strobl                   ++functionCode
264*1f21f64aSMarius Strobl                 ) {
265*1f21f64aSMarius Strobl                 if (    functionExists[ functionCode ]
266*1f21f64aSMarius Strobl                      && ( functions[ functionCode ].numInputs == 1 ) ) {
267*1f21f64aSMarius Strobl                     testFunction(
268*1f21f64aSMarius Strobl                         functionCode, roundingPrecision, roundingMode );
269*1f21f64aSMarius Strobl                 }
270*1f21f64aSMarius Strobl             }
271*1f21f64aSMarius Strobl         }
272*1f21f64aSMarius Strobl         else if ( operands == 2 ) {
273*1f21f64aSMarius Strobl             for ( functionCode = 1;
274*1f21f64aSMarius Strobl                   functionCode < NUM_FUNCTIONS;
275*1f21f64aSMarius Strobl                   ++functionCode
276*1f21f64aSMarius Strobl                 ) {
277*1f21f64aSMarius Strobl                 if (    functionExists[ functionCode ]
278*1f21f64aSMarius Strobl                      && ( functions[ functionCode ].numInputs == 2 ) ) {
279*1f21f64aSMarius Strobl                     testFunction(
280*1f21f64aSMarius Strobl                         functionCode, roundingPrecision, roundingMode );
281*1f21f64aSMarius Strobl                 }
282*1f21f64aSMarius Strobl             }
283*1f21f64aSMarius Strobl         }
284*1f21f64aSMarius Strobl         else {
285*1f21f64aSMarius Strobl             for ( functionCode = 1;
286*1f21f64aSMarius Strobl                   functionCode < NUM_FUNCTIONS;
287*1f21f64aSMarius Strobl                   ++functionCode
288*1f21f64aSMarius Strobl                 ) {
289*1f21f64aSMarius Strobl                 if ( functionExists[ functionCode ] ) {
290*1f21f64aSMarius Strobl                     testFunction(
291*1f21f64aSMarius Strobl                         functionCode, roundingPrecision, roundingMode );
292*1f21f64aSMarius Strobl                 }
293*1f21f64aSMarius Strobl             }
294*1f21f64aSMarius Strobl         }
295*1f21f64aSMarius Strobl     }
296*1f21f64aSMarius Strobl     exitWithStatus();
297*1f21f64aSMarius Strobl 
298*1f21f64aSMarius Strobl }
299*1f21f64aSMarius Strobl 
300