1206917Smarius 2206917Smarius/* 3206917Smarius=============================================================================== 4206917Smarius 5206917SmariusThis C source file is part of TestFloat, Release 2a, a package of programs 6206917Smariusfor testing the correctness of floating-point arithmetic complying to the 7206917SmariusIEC/IEEE Standard for Floating-Point. 8206917Smarius 9206917SmariusWritten by John R. Hauser. More information is available through the Web 10206917Smariuspage `http://HTTP.CS.Berkeley.EDU/~jhauser/arithmetic/TestFloat.html'. 11206917Smarius 12206917SmariusTHIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort 13206917Smariushas been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT 14206917SmariusTIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO 15206917SmariusPERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY 16206917SmariusAND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE. 17206917Smarius 18206917SmariusDerivative works are acceptable, even for commercial purposes, so long as 19206917Smarius(1) they include prominent notice that the work is derivative, and (2) they 20206917Smariusinclude prominent notice akin to these four paragraphs for those parts of 21206917Smariusthis code that are retained. 22206917Smarius 23206917Smarius=============================================================================== 24206917Smarius*/ 25206917Smarius 26207151Smarius#include <sys/cdefs.h> 27207151Smarius__FBSDID("$FreeBSD: releng/11.0/tools/test/testfloat/testfloat.c 207151 2010-04-24 12:11:41Z marius $"); 28207151Smarius 29206917Smarius#include <stdlib.h> 30206917Smarius#include <signal.h> 31206917Smarius#include <string.h> 32206917Smarius#include "milieu.h" 33206917Smarius#include "fail.h" 34206917Smarius#include "softfloat.h" 35206917Smarius#include "testCases.h" 36206917Smarius#include "testLoops.h" 37206917Smarius#include "systflags.h" 38206917Smarius#include "testFunction.h" 39206917Smarius 40206917Smariusstatic void catchSIGINT( int signalCode ) 41206917Smarius{ 42206917Smarius 43206917Smarius if ( stop ) exit( EXIT_FAILURE ); 44206917Smarius stop = TRUE; 45206917Smarius 46206917Smarius} 47206917Smarius 48207151Smariusint 49206917Smariusmain( int argc, char **argv ) 50206917Smarius{ 51206917Smarius char *argPtr; 52206917Smarius flag functionArgument; 53206917Smarius uint8 functionCode; 54206917Smarius int8 operands, roundingPrecision, roundingMode; 55206917Smarius 56206917Smarius fail_programName = "testfloat"; 57206917Smarius if ( argc <= 1 ) goto writeHelpMessage; 58206917Smarius testCases_setLevel( 1 ); 59206917Smarius trueName = "soft"; 60206917Smarius testName = "syst"; 61206917Smarius errorStop = FALSE; 62206917Smarius forever = FALSE; 63206917Smarius maxErrorCount = 20; 64206917Smarius trueFlagsPtr = &float_exception_flags; 65206917Smarius testFlagsFunctionPtr = syst_float_flags_clear; 66206917Smarius tininessModeName = 0; 67206917Smarius functionArgument = FALSE; 68206917Smarius functionCode = 0; 69206917Smarius operands = 0; 70206917Smarius roundingPrecision = 0; 71206917Smarius roundingMode = 0; 72206917Smarius --argc; 73206917Smarius ++argv; 74206917Smarius while ( argc && ( argPtr = argv[ 0 ] ) ) { 75206917Smarius if ( argPtr[ 0 ] == '-' ) ++argPtr; 76206917Smarius if ( strcmp( argPtr, "help" ) == 0 ) { 77206917Smarius writeHelpMessage: 78206917Smarius fputs( 79206917Smarius"testfloat [<option>...] <function>\n" 80206917Smarius" <option>: (* is default)\n" 81206917Smarius" -help --Write this message and exit.\n" 82206917Smarius" -list --List all testable functions and exit.\n" 83206917Smarius" -level <num> --Testing level <num> (1 or 2).\n" 84206917Smarius" * -level 1\n" 85206917Smarius" -errors <num> --Stop each function test after <num> errors.\n" 86206917Smarius" * -errors 20\n" 87206917Smarius" -errorstop --Exit after first function with any error.\n" 88206917Smarius" -forever --Test one function repeatedly (implies `-level 2').\n" 89206917Smarius" -checkNaNs --Check for bitwise correctness of NaN results.\n" 90206917Smarius#ifdef FLOATX80 91206917Smarius" -precision32 --Only test rounding precision equivalent to float32.\n" 92206917Smarius" -precision64 --Only test rounding precision equivalent to float64.\n" 93206917Smarius" -precision80 --Only test maximum rounding precision.\n" 94206917Smarius#endif 95206917Smarius" -nearesteven --Only test rounding to nearest/even.\n" 96206917Smarius" -tozero --Only test rounding to zero.\n" 97206917Smarius" -down --Only test rounding down.\n" 98206917Smarius" -up --Only test rounding up.\n" 99206917Smarius" -tininessbefore --Underflow tininess detected before rounding.\n" 100206917Smarius" -tininessafter --Underflow tininess detected after rounding.\n" 101206917Smarius" <function>:\n" 102206917Smarius" int32_to_<float> <float>_add <float>_eq\n" 103206917Smarius" <float>_to_int32 <float>_sub <float>_le\n" 104206917Smarius" <float>_to_int32_round_to_zero <float>_mul <float>_lt\n" 105206917Smarius#ifdef BITS64 106206917Smarius" int64_to_<float> <float>_div <float>_eq_signaling\n" 107206917Smarius" <float>_to_int64 <float>_rem <float>_le_quiet\n" 108206917Smarius" <float>_to_int64_round_to_zero <float>_lt_quiet\n" 109206917Smarius" <float>_to_<float>\n" 110206917Smarius" <float>_round_to_int\n" 111206917Smarius" <float>_sqrt\n" 112206917Smarius#else 113206917Smarius" <float>_to_<float> <float>_div <float>_eq_signaling\n" 114206917Smarius" <float>_round_to_int <float>_rem <float>_le_quiet\n" 115206917Smarius" <float>_sqrt <float>_lt_quiet\n" 116206917Smarius#endif 117206917Smarius" -all1 --All 1-operand functions.\n" 118206917Smarius" -all2 --All 2-operand functions.\n" 119206917Smarius" -all --All functions.\n" 120206917Smarius" <float>:\n" 121206917Smarius" float32 --Single precision.\n" 122206917Smarius" float64 --Double precision.\n" 123206917Smarius#ifdef FLOATX80 124206917Smarius" floatx80 --Extended double precision.\n" 125206917Smarius#endif 126206917Smarius#ifdef FLOAT128 127206917Smarius" float128 --Quadruple precision.\n" 128206917Smarius#endif 129206917Smarius , 130206917Smarius stdout 131206917Smarius ); 132206917Smarius return EXIT_SUCCESS; 133206917Smarius } 134206917Smarius else if ( strcmp( argPtr, "list" ) == 0 ) { 135206917Smarius for ( functionCode = 1; 136206917Smarius functionCode < NUM_FUNCTIONS; 137206917Smarius ++functionCode 138206917Smarius ) { 139206917Smarius if ( functionExists[ functionCode ] ) { 140206917Smarius puts( functions[ functionCode ].name ); 141206917Smarius } 142206917Smarius } 143206917Smarius return EXIT_SUCCESS; 144206917Smarius } 145206917Smarius else if ( strcmp( argPtr, "level" ) == 0 ) { 146206917Smarius if ( argc < 2 ) goto optionError; 147206917Smarius testCases_setLevel( atoi( argv[ 1 ] ) ); 148206917Smarius --argc; 149206917Smarius ++argv; 150206917Smarius } 151206917Smarius else if ( strcmp( argPtr, "level1" ) == 0 ) { 152206917Smarius testCases_setLevel( 1 ); 153206917Smarius } 154206917Smarius else if ( strcmp( argPtr, "level2" ) == 0 ) { 155206917Smarius testCases_setLevel( 2 ); 156206917Smarius } 157206917Smarius else if ( strcmp( argPtr, "errors" ) == 0 ) { 158206917Smarius if ( argc < 2 ) { 159206917Smarius optionError: 160206917Smarius fail( "`%s' option requires numeric argument", argv[ 0 ] ); 161206917Smarius } 162206917Smarius maxErrorCount = atoi( argv[ 1 ] ); 163206917Smarius --argc; 164206917Smarius ++argv; 165206917Smarius } 166206917Smarius else if ( strcmp( argPtr, "errorstop" ) == 0 ) { 167206917Smarius errorStop = TRUE; 168206917Smarius } 169206917Smarius else if ( strcmp( argPtr, "forever" ) == 0 ) { 170206917Smarius testCases_setLevel( 2 ); 171206917Smarius forever = TRUE; 172206917Smarius } 173206917Smarius else if ( ( strcmp( argPtr, "checkNaNs" ) == 0 ) 174206917Smarius || ( strcmp( argPtr, "checknans" ) == 0 ) ) { 175206917Smarius checkNaNs = TRUE; 176206917Smarius } 177206917Smarius#ifdef FLOATX80 178206917Smarius else if ( strcmp( argPtr, "precision32" ) == 0 ) { 179206917Smarius roundingPrecision = 32; 180206917Smarius } 181206917Smarius else if ( strcmp( argPtr, "precision64" ) == 0 ) { 182206917Smarius roundingPrecision = 64; 183206917Smarius } 184206917Smarius else if ( strcmp( argPtr, "precision80" ) == 0 ) { 185206917Smarius roundingPrecision = 80; 186206917Smarius } 187206917Smarius#endif 188206917Smarius else if ( ( strcmp( argPtr, "nearesteven" ) == 0 ) 189206917Smarius || ( strcmp( argPtr, "nearest_even" ) == 0 ) ) { 190206917Smarius roundingMode = ROUND_NEAREST_EVEN; 191206917Smarius } 192206917Smarius else if ( ( strcmp( argPtr, "tozero" ) == 0 ) 193206917Smarius || ( strcmp( argPtr, "to_zero" ) == 0 ) ) { 194206917Smarius roundingMode = ROUND_TO_ZERO; 195206917Smarius } 196206917Smarius else if ( strcmp( argPtr, "down" ) == 0 ) { 197206917Smarius roundingMode = ROUND_DOWN; 198206917Smarius } 199206917Smarius else if ( strcmp( argPtr, "up" ) == 0 ) { 200206917Smarius roundingMode = ROUND_UP; 201206917Smarius } 202206917Smarius else if ( strcmp( argPtr, "tininessbefore" ) == 0 ) { 203206917Smarius float_detect_tininess = float_tininess_before_rounding; 204206917Smarius } 205206917Smarius else if ( strcmp( argPtr, "tininessafter" ) == 0 ) { 206206917Smarius float_detect_tininess = float_tininess_after_rounding; 207206917Smarius } 208206917Smarius else if ( strcmp( argPtr, "all1" ) == 0 ) { 209206917Smarius functionArgument = TRUE; 210206917Smarius functionCode = 0; 211206917Smarius operands = 1; 212206917Smarius } 213206917Smarius else if ( strcmp( argPtr, "all2" ) == 0 ) { 214206917Smarius functionArgument = TRUE; 215206917Smarius functionCode = 0; 216206917Smarius operands = 2; 217206917Smarius } 218206917Smarius else if ( strcmp( argPtr, "all" ) == 0 ) { 219206917Smarius functionArgument = TRUE; 220206917Smarius functionCode = 0; 221206917Smarius operands = 0; 222206917Smarius } 223206917Smarius else { 224206917Smarius for ( functionCode = 1; 225206917Smarius functionCode < NUM_FUNCTIONS; 226206917Smarius ++functionCode 227206917Smarius ) { 228206917Smarius if ( strcmp( argPtr, functions[ functionCode ].name ) == 0 ) { 229206917Smarius break; 230206917Smarius } 231206917Smarius } 232206917Smarius if ( functionCode == NUM_FUNCTIONS ) { 233206917Smarius fail( "Invalid option or function `%s'", argv[ 0 ] ); 234206917Smarius } 235206917Smarius if ( ! functionExists[ functionCode ] ) { 236206917Smarius fail( 237206917Smarius "Function `%s' is not supported or cannot be tested", 238206917Smarius argPtr 239206917Smarius ); 240206917Smarius } 241206917Smarius functionArgument = TRUE; 242206917Smarius } 243206917Smarius --argc; 244206917Smarius ++argv; 245206917Smarius } 246206917Smarius if ( ! functionArgument ) fail( "Function argument required" ); 247206917Smarius (void) signal( SIGINT, catchSIGINT ); 248206917Smarius (void) signal( SIGTERM, catchSIGINT ); 249206917Smarius if ( functionCode ) { 250206917Smarius if ( forever ) { 251206917Smarius if ( ! roundingPrecision ) roundingPrecision = 80; 252206917Smarius if ( ! roundingMode ) roundingMode = ROUND_NEAREST_EVEN; 253206917Smarius } 254206917Smarius testFunction( functionCode, roundingPrecision, roundingMode ); 255206917Smarius } 256206917Smarius else { 257206917Smarius if ( forever ) { 258206917Smarius fail( "Can only test one function with `-forever' option" ); 259206917Smarius } 260206917Smarius if ( operands == 1 ) { 261206917Smarius for ( functionCode = 1; 262206917Smarius functionCode < NUM_FUNCTIONS; 263206917Smarius ++functionCode 264206917Smarius ) { 265206917Smarius if ( functionExists[ functionCode ] 266206917Smarius && ( functions[ functionCode ].numInputs == 1 ) ) { 267206917Smarius testFunction( 268206917Smarius functionCode, roundingPrecision, roundingMode ); 269206917Smarius } 270206917Smarius } 271206917Smarius } 272206917Smarius else if ( operands == 2 ) { 273206917Smarius for ( functionCode = 1; 274206917Smarius functionCode < NUM_FUNCTIONS; 275206917Smarius ++functionCode 276206917Smarius ) { 277206917Smarius if ( functionExists[ functionCode ] 278206917Smarius && ( functions[ functionCode ].numInputs == 2 ) ) { 279206917Smarius testFunction( 280206917Smarius functionCode, roundingPrecision, roundingMode ); 281206917Smarius } 282206917Smarius } 283206917Smarius } 284206917Smarius else { 285206917Smarius for ( functionCode = 1; 286206917Smarius functionCode < NUM_FUNCTIONS; 287206917Smarius ++functionCode 288206917Smarius ) { 289206917Smarius if ( functionExists[ functionCode ] ) { 290206917Smarius testFunction( 291206917Smarius functionCode, roundingPrecision, roundingMode ); 292206917Smarius } 293206917Smarius } 294206917Smarius } 295206917Smarius } 296206917Smarius exitWithStatus(); 297206917Smarius 298206917Smarius} 299206917Smarius 300