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