1 2/* 3=============================================================================== 4 5This C source file is part of TestFloat, Release 2a, a package of programs 6for testing the correctness of floating-point arithmetic complying to the 7IEC/IEEE Standard for Floating-Point. 8 9Written by John R. Hauser. More information is available through the Web 10page `http://HTTP.CS.Berkeley.EDU/~jhauser/arithmetic/TestFloat.html'. 11 12THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort 13has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT 14TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO 15PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY 16AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE. 17 18Derivative works are acceptable, even for commercial purposes, so long as 19(1) they include prominent notice that the work is derivative, and (2) they 20include prominent notice akin to these four paragraphs for those parts of 21this code that are retained. 22 23=============================================================================== 24*/ 25 26#include <sys/cdefs.h> 27__FBSDID("$FreeBSD: releng/11.0/tools/test/testfloat/testfloat.c 207151 2010-04-24 12:11:41Z marius $"); 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 40static void catchSIGINT( int signalCode ) 41{ 42 43 if ( stop ) exit( EXIT_FAILURE ); 44 stop = TRUE; 45 46} 47 48int 49main( 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 300