1 /* $NetBSD: testfloat.c,v 1.5 2002/02/21 07:38:16 itojun Exp $ */ 2 3 /* This is a derivative work. */ 4 5 /*- 6 * Copyright (c) 2001 The NetBSD Foundation, Inc. 7 * All rights reserved. 8 * 9 * This code is derived from software contributed to The NetBSD Foundation 10 * by Ross Harvey. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 3. All advertising materials mentioning features or use of this software 21 * must display the following acknowledgement: 22 * This product includes software developed by the NetBSD 23 * Foundation, Inc. and its contributors. 24 * 4. Neither the name of The NetBSD Foundation nor the names of its 25 * contributors may be used to endorse or promote products derived 26 * from this software without specific prior written permission. 27 * 28 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 29 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 30 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 31 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 32 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 33 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 34 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 35 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 36 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 37 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 38 * POSSIBILITY OF SUCH DAMAGE. 39 */ 40 41 /* 42 =============================================================================== 43 44 This C source file is part of TestFloat, Release 2a, a package of programs 45 for testing the correctness of floating-point arithmetic complying to the 46 IEC/IEEE Standard for Floating-Point. 47 48 Written by John R. Hauser. More information is available through the Web 49 page `http://HTTP.CS.Berkeley.EDU/~jhauser/arithmetic/TestFloat.html'. 50 51 THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort 52 has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT 53 TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO 54 PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY 55 AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE. 56 57 Derivative works are acceptable, even for commercial purposes, so long as 58 (1) they include prominent notice that the work is derivative, and (2) they 59 include prominent notice akin to these four paragraphs for those parts of 60 this code that are retained. 61 62 =============================================================================== 63 */ 64 65 #include <sys/cdefs.h> 66 #ifndef __lint 67 __COPYRIGHT("@(#) Copyright (c) 2001\n\ 68 The NetBSD Foundation, inc. All rights reserved.\n"); 69 __RCSID("$NetBSD: testfloat.c,v 1.5 2002/02/21 07:38:16 itojun Exp $"); 70 #endif /* !__lint */ 71 72 #include <stdlib.h> 73 #include <signal.h> 74 #include <string.h> 75 #include "milieu.h" 76 #include "fail.h" 77 #include "softfloat.h" 78 #include "testCases.h" 79 #include "testLoops.h" 80 #include "systflags.h" 81 #include "testFunction.h" 82 83 static void catchSIGINT( int signalCode ) 84 { 85 86 if ( stop ) exit( EXIT_FAILURE ); 87 stop = TRUE; 88 89 } 90 91 int 92 main( int argc, char **argv ) 93 { 94 char *argPtr; 95 flag functionArgument; 96 uint8 functionCode; 97 int8 operands, roundingPrecision, roundingMode; 98 99 fail_programName = "testfloat"; 100 if ( argc <= 1 ) goto writeHelpMessage; 101 testCases_setLevel( 1 ); 102 trueName = "soft"; 103 testName = "syst"; 104 errorStop = FALSE; 105 forever = FALSE; 106 maxErrorCount = 20; 107 trueFlagsPtr = &float_exception_flags; 108 testFlagsFunctionPtr = syst_float_flags_clear; 109 tininessModeName = 0; 110 functionArgument = FALSE; 111 functionCode = 0; 112 operands = 0; 113 roundingPrecision = 0; 114 roundingMode = 0; 115 --argc; 116 ++argv; 117 while ( argc && ( argPtr = argv[ 0 ] ) ) { 118 if ( argPtr[ 0 ] == '-' ) ++argPtr; 119 if ( strcmp( argPtr, "help" ) == 0 ) { 120 writeHelpMessage: 121 fputs( 122 "testfloat [<option>...] <function>\n" 123 " <option>: (* is default)\n" 124 " -help --Write this message and exit.\n" 125 " -list --List all testable functions and exit.\n" 126 " -level <num> --Testing level <num> (1 or 2).\n" 127 " * -level 1\n" 128 " -errors <num> --Stop each function test after <num> errors.\n" 129 " * -errors 20\n" 130 " -errorstop --Exit after first function with any error.\n" 131 " -forever --Test one function repeatedly (implies `-level 2').\n" 132 " -checkNaNs --Check for bitwise correctness of NaN results.\n" 133 #ifdef FLOATX80 134 " -precision32 --Only test rounding precision equivalent to float32.\n" 135 " -precision64 --Only test rounding precision equivalent to float64.\n" 136 " -precision80 --Only test maximum rounding precision.\n" 137 #endif 138 " -nearesteven --Only test rounding to nearest/even.\n" 139 " -tozero --Only test rounding to zero.\n" 140 " -down --Only test rounding down.\n" 141 " -up --Only test rounding up.\n" 142 " -tininessbefore --Underflow tininess detected before rounding.\n" 143 " -tininessafter --Underflow tininess detected after rounding.\n" 144 " <function>:\n" 145 " int32_to_<float> <float>_add <float>_eq\n" 146 " <float>_to_int32 <float>_sub <float>_le\n" 147 " <float>_to_int32_round_to_zero <float>_mul <float>_lt\n" 148 #ifdef BITS64 149 " int64_to_<float> <float>_div <float>_eq_signaling\n" 150 " <float>_to_int64 <float>_rem <float>_le_quiet\n" 151 " <float>_to_int64_round_to_zero <float>_lt_quiet\n" 152 " <float>_to_<float>\n" 153 " <float>_round_to_int\n" 154 " <float>_sqrt\n" 155 #else 156 " <float>_to_<float> <float>_div <float>_eq_signaling\n" 157 " <float>_round_to_int <float>_rem <float>_le_quiet\n" 158 " <float>_sqrt <float>_lt_quiet\n" 159 #endif 160 " -all1 --All 1-operand functions.\n" 161 " -all2 --All 2-operand functions.\n" 162 " -all --All functions.\n" 163 " <float>:\n" 164 " float32 --Single precision.\n" 165 " float64 --Double precision.\n" 166 #ifdef FLOATX80 167 " floatx80 --Extended double precision.\n" 168 #endif 169 #ifdef FLOAT128 170 " float128 --Quadruple precision.\n" 171 #endif 172 , 173 stdout 174 ); 175 return EXIT_SUCCESS; 176 } 177 else if ( strcmp( argPtr, "list" ) == 0 ) { 178 for ( functionCode = 1; 179 functionCode < NUM_FUNCTIONS; 180 ++functionCode 181 ) { 182 if ( functionExists[ functionCode ] ) { 183 puts( functions[ functionCode ].name ); 184 } 185 } 186 return EXIT_SUCCESS; 187 } 188 else if ( strcmp( argPtr, "level" ) == 0 ) { 189 if ( argc < 2 ) goto optionError; 190 testCases_setLevel( atoi( argv[ 1 ] ) ); 191 --argc; 192 ++argv; 193 } 194 else if ( strcmp( argPtr, "level1" ) == 0 ) { 195 testCases_setLevel( 1 ); 196 } 197 else if ( strcmp( argPtr, "level2" ) == 0 ) { 198 testCases_setLevel( 2 ); 199 } 200 else if ( strcmp( argPtr, "errors" ) == 0 ) { 201 if ( argc < 2 ) { 202 optionError: 203 fail( "`%s' option requires numeric argument", argv[ 0 ] ); 204 } 205 maxErrorCount = atoi( argv[ 1 ] ); 206 --argc; 207 ++argv; 208 } 209 else if ( strcmp( argPtr, "errorstop" ) == 0 ) { 210 errorStop = TRUE; 211 } 212 else if ( strcmp( argPtr, "forever" ) == 0 ) { 213 testCases_setLevel( 2 ); 214 forever = TRUE; 215 } 216 else if ( ( strcmp( argPtr, "checkNaNs" ) == 0 ) 217 || ( strcmp( argPtr, "checknans" ) == 0 ) ) { 218 checkNaNs = TRUE; 219 } 220 #ifdef FLOATX80 221 else if ( strcmp( argPtr, "precision32" ) == 0 ) { 222 roundingPrecision = 32; 223 } 224 else if ( strcmp( argPtr, "precision64" ) == 0 ) { 225 roundingPrecision = 64; 226 } 227 else if ( strcmp( argPtr, "precision80" ) == 0 ) { 228 roundingPrecision = 80; 229 } 230 #endif 231 else if ( ( strcmp( argPtr, "nearesteven" ) == 0 ) 232 || ( strcmp( argPtr, "nearest_even" ) == 0 ) ) { 233 roundingMode = ROUND_NEAREST_EVEN; 234 } 235 else if ( ( strcmp( argPtr, "tozero" ) == 0 ) 236 || ( strcmp( argPtr, "to_zero" ) == 0 ) ) { 237 roundingMode = ROUND_TO_ZERO; 238 } 239 else if ( strcmp( argPtr, "down" ) == 0 ) { 240 roundingMode = ROUND_DOWN; 241 } 242 else if ( strcmp( argPtr, "up" ) == 0 ) { 243 roundingMode = ROUND_UP; 244 } 245 else if ( strcmp( argPtr, "tininessbefore" ) == 0 ) { 246 float_detect_tininess = float_tininess_before_rounding; 247 } 248 else if ( strcmp( argPtr, "tininessafter" ) == 0 ) { 249 float_detect_tininess = float_tininess_after_rounding; 250 } 251 else if ( strcmp( argPtr, "all1" ) == 0 ) { 252 functionArgument = TRUE; 253 functionCode = 0; 254 operands = 1; 255 } 256 else if ( strcmp( argPtr, "all2" ) == 0 ) { 257 functionArgument = TRUE; 258 functionCode = 0; 259 operands = 2; 260 } 261 else if ( strcmp( argPtr, "all" ) == 0 ) { 262 functionArgument = TRUE; 263 functionCode = 0; 264 operands = 0; 265 } 266 else { 267 for ( functionCode = 1; 268 functionCode < NUM_FUNCTIONS; 269 ++functionCode 270 ) { 271 if ( strcmp( argPtr, functions[ functionCode ].name ) == 0 ) { 272 break; 273 } 274 } 275 if ( functionCode == NUM_FUNCTIONS ) { 276 fail( "Invalid option or function `%s'", argv[ 0 ] ); 277 } 278 if ( ! functionExists[ functionCode ] ) { 279 fail( 280 "Function `%s' is not supported or cannot be tested", 281 argPtr 282 ); 283 } 284 functionArgument = TRUE; 285 } 286 --argc; 287 ++argv; 288 } 289 if ( ! functionArgument ) fail( "Function argument required" ); 290 (void) signal( SIGINT, catchSIGINT ); 291 (void) signal( SIGTERM, catchSIGINT ); 292 if ( functionCode ) { 293 if ( forever ) { 294 if ( ! roundingPrecision ) roundingPrecision = 80; 295 if ( ! roundingMode ) roundingMode = ROUND_NEAREST_EVEN; 296 } 297 testFunction( functionCode, roundingPrecision, roundingMode ); 298 } 299 else { 300 if ( forever ) { 301 fail( "Can only test one function with `-forever' option" ); 302 } 303 if ( operands == 1 ) { 304 for ( functionCode = 1; 305 functionCode < NUM_FUNCTIONS; 306 ++functionCode 307 ) { 308 if ( functionExists[ functionCode ] 309 && ( functions[ functionCode ].numInputs == 1 ) ) { 310 testFunction( 311 functionCode, roundingPrecision, roundingMode ); 312 } 313 } 314 } 315 else if ( operands == 2 ) { 316 for ( functionCode = 1; 317 functionCode < NUM_FUNCTIONS; 318 ++functionCode 319 ) { 320 if ( functionExists[ functionCode ] 321 && ( functions[ functionCode ].numInputs == 2 ) ) { 322 testFunction( 323 functionCode, roundingPrecision, roundingMode ); 324 } 325 } 326 } 327 else { 328 for ( functionCode = 1; 329 functionCode < NUM_FUNCTIONS; 330 ++functionCode 331 ) { 332 if ( functionExists[ functionCode ] ) { 333 testFunction( 334 functionCode, roundingPrecision, roundingMode ); 335 } 336 } 337 } 338 } 339 exitWithStatus(); 340 return 0; 341 } 342 343