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