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