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