Home | History | Annotate | Download | only in tests
      1 /*
      2  *
      3  *  Copyright (C) 2001-2007  Peter Johnson
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions
      7  * are met:
      8  * 1. Redistributions of source code must retain the above copyright
      9  *    notice, this list of conditions and the following disclaimer.
     10  * 2. Redistributions in binary form must reproduce the above copyright
     11  *    notice, this list of conditions and the following disclaimer in the
     12  *    documentation and/or other materials provided with the distribution.
     13  *
     14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
     15  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
     18  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     19  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     20  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     21  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     22  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     23  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     24  * POSSIBILITY OF SUCH DAMAGE.
     25  */
     26 #include <stdio.h>
     27 #include <stdlib.h>
     28 #include <string.h>
     29 
     30 #include "libyasm/floatnum.c"
     31 
     32 /* constants describing parameters of internal floating point format.
     33  *  (these should match those in src/floatnum.c !)
     34  */
     35 #define MANT_BITS       80
     36 #define MANT_BYTES      10
     37 
     38 typedef struct Init_Entry_s {
     39     /* input ASCII value */
     40     const char *ascii;
     41 
     42     /* correct output from ASCII conversion */
     43     unsigned char mantissa[MANT_BYTES];     /* little endian mantissa - first
     44                                                byte is not checked for
     45                                                correctness. */
     46     unsigned short exponent;        /* bias 32767 exponent */
     47     unsigned char sign;
     48     unsigned char flags;
     49 
     50     /* correct output conversions - these should be *exact* matches */
     51     int ret32;
     52     unsigned char result32[4];
     53     int ret64;
     54     unsigned char result64[8];
     55     int ret80;
     56     unsigned char result80[10];
     57 } Init_Entry;
     58 
     59 /* Values used for normalized tests */
     60 static Init_Entry normalized_vals[] = {
     61     {   "3.141592653589793",
     62         {0xc6,0x0d,0xe9,0xbd,0x68,0x21,0xa2,0xda,0x0f,0xc9},0x8000,0,0,
     63          0, {0xdb,0x0f,0x49,0x40},
     64          0, {0x18,0x2d,0x44,0x54,0xfb,0x21,0x09,0x40},
     65          0, {0xe9,0xbd,0x68,0x21,0xa2,0xda,0x0f,0xc9,0x00,0x40}
     66     },
     67     {   "-3.141592653589793",
     68         {0xc6,0x0d,0xe9,0xbd,0x68,0x21,0xa2,0xda,0x0f,0xc9},0x8000,1,0,
     69          0, {0xdb,0x0f,0x49,0xc0},
     70          0, {0x18,0x2d,0x44,0x54,0xfb,0x21,0x09,0xc0},
     71          0, {0xe9,0xbd,0x68,0x21,0xa2,0xda,0x0f,0xc9,0x00,0xc0}
     72     },
     73     {   "1.e16",
     74         {0x00,0x00,0x00,0x00,0x00,0x04,0xbf,0xc9,0x1b,0x8e},0x8034,0,0,
     75          0, {0xca,0x1b,0x0e,0x5a},
     76          0, {0x00,0x80,0xe0,0x37,0x79,0xc3,0x41,0x43},
     77          0, {0x00,0x00,0x00,0x04,0xbf,0xc9,0x1b,0x8e,0x34,0x40}
     78     },
     79     {   "1.6e-20",
     80         {0xf6,0xd3,0xee,0x7b,0xda,0x74,0x50,0xa0,0x1d,0x97},0x7fbd,0,0,
     81          0, {0xa0,0x1d,0x97,0x1e},
     82          0, {0x4f,0x9b,0x0e,0x0a,0xb4,0xe3,0xd2,0x3b},
     83          0, {0xef,0x7b,0xda,0x74,0x50,0xa0,0x1d,0x97,0xbd,0x3f}
     84     },
     85     {   "-5876.",
     86         {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0xb7},0x800b,1,0,
     87          0, {0x00,0xa0,0xb7,0xc5},
     88          0, {0x00,0x00,0x00,0x00,0x00,0xf4,0xb6,0xc0},
     89          0, {0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0xb7,0x0b,0xc0}
     90     },
     91     /* Edge cases for rounding wrap. */
     92     {   "1.00000",
     93         {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff},0x7ffe,0,0,
     94          0, {0x00,0x00,0x80,0x3f},
     95          0, {0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0x3f},
     96          0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff,0x3f}
     97     },
     98     {   "1.000000",
     99         {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff},0x7ffe,0,0,
    100          0, {0x00,0x00,0x80,0x3f},
    101          0, {0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0x3f},
    102          0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff,0x3f}
    103     },
    104 };
    105 
    106 /* Still normalized values, but edge cases of various sizes, testing underflow/
    107  * overflow checks as well.
    108  */
    109 static Init_Entry normalized_edgecase_vals[] = {
    110     /* 32-bit edges */
    111     {   "1.1754943508222875e-38",
    112         {0xd5,0xf2,0x82,0xff,0xff,0xff,0xff,0xff,0xff,0xff},0x7f80,0,0,
    113          0, {0x00,0x00,0x80,0x00},
    114          0, {0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x38},
    115          0, {0x83,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x80,0x3f}
    116     },
    117     {   "3.4028234663852886e+38",
    118         {0x21,0x35,0x0a,0x00,0x00,0x00,0x00,0xff,0xff,0xff},0x807e,0,0,
    119          0, {0xff,0xff,0x7f,0x7f},
    120          0, {0x00,0x00,0x00,0xe0,0xff,0xff,0xef,0x47},
    121          0, {0x0a,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0x7e,0x40}
    122     },
    123     /* 64-bit edges */
    124     {   "2.2250738585072014E-308",
    125         {0x26,0x18,0x46,0x00,0x00,0x00,0x00,0x00,0x00,0x80},0x7c01,0,0,
    126         -1, {0x00,0x00,0x00,0x00},
    127          0, {0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00},
    128          0, {0x46,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x01,0x3c}
    129     },
    130     {   "1.7976931348623157E+308",
    131         {0x26,0x6b,0xac,0xf7,0xff,0xff,0xff,0xff,0xff,0xff},0x83fe,0,0,
    132          1, {0x00,0x00,0x80,0x7f},
    133          0, {0xff,0xff,0xff,0xff,0xff,0xff,0xef,0x7f},
    134          0, {0xac,0xf7,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0x43}
    135     },
    136     /* 80-bit edges */
    137 /*    { "3.3621E-4932",
    138         {},,0,0,
    139         -1, {0x00,0x00,0x00,0x00},
    140         -1, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
    141          0, {}
    142     },
    143     {   "1.1897E+4932",
    144         {},,0,0,
    145          1, {0x00,0x00,0x80,0x7f},
    146          1, {},
    147          0, {}
    148     },*/
    149     /* internal format edges */
    150 /*    {
    151     },
    152     {
    153     },*/
    154 };
    155 
    156 static yasm_floatnum *flt;
    157 
    158 /* failure messages */
    159 static char ret_msg[1024], result_msg[1024];
    160 
    161 static void
    162 new_setup(Init_Entry *vals, int i)
    163 {
    164     flt = yasm_floatnum_create(vals[i].ascii);
    165     strcpy(result_msg, vals[i].ascii);
    166     strcat(result_msg, ": incorrect ");
    167 }
    168 
    169 static int
    170 new_check_flt(Init_Entry *val)
    171 {
    172     unsigned char *mantissa;
    173     int i, result = 0;
    174     unsigned int len;
    175 
    176     mantissa = BitVector_Block_Read(flt->mantissa, &len);
    177     for (i=1;i<MANT_BYTES;i++)      /* don't compare first byte */
    178         if (mantissa[i] != val->mantissa[i])
    179             result = 1;
    180     free(mantissa);
    181     if (result) {
    182         strcat(result_msg, "mantissa");
    183         return 1;
    184     }
    185 
    186     if (flt->exponent != val->exponent) {
    187         strcat(result_msg, "exponent");
    188         return 1;
    189     }
    190     if (flt->sign != val->sign) {
    191         strcat(result_msg, "sign");
    192         return 1;
    193     }
    194     if (flt->flags != val->flags) {
    195         strcat(result_msg, "flags");
    196         return 1;
    197     }
    198     return 0;
    199 }
    200 
    201 static int
    202 test_new_normalized(void)
    203 {
    204     Init_Entry *vals = normalized_vals;
    205     int i, num = sizeof(normalized_vals)/sizeof(Init_Entry);
    206 
    207     for (i=0; i<num; i++) {
    208         new_setup(vals, i);
    209         if (new_check_flt(&vals[i]) != 0)
    210             return 1;
    211         yasm_floatnum_destroy(flt);
    212     }
    213     return 0;
    214 }
    215 
    216 static int
    217 test_new_normalized_edgecase(void)
    218 {
    219     Init_Entry *vals = normalized_edgecase_vals;
    220     int i, num = sizeof(normalized_edgecase_vals)/sizeof(Init_Entry);
    221 
    222     for (i=0; i<num; i++) {
    223         new_setup(vals, i);
    224         if (new_check_flt(&vals[i]) != 0)
    225             return 1;
    226         yasm_floatnum_destroy(flt);
    227     }
    228     return 0;
    229 }
    230 
    231 static void
    232 get_family_setup(void)
    233 {
    234     flt = malloc(sizeof(yasm_floatnum));
    235     flt->mantissa = BitVector_Create(MANT_BITS, TRUE);
    236 }
    237 
    238 static void
    239 get_family_teardown(void)
    240 {
    241     BitVector_Destroy(flt->mantissa);
    242     free(flt);
    243 }
    244 
    245 static void
    246 get_common_setup(Init_Entry *vals, int i)
    247 {
    248     /* set up flt */
    249     BitVector_Block_Store(flt->mantissa, vals[i].mantissa, MANT_BYTES);
    250     flt->sign = vals[i].sign;
    251     flt->exponent = vals[i].exponent;
    252     flt->flags = vals[i].flags;
    253 
    254     /* set failure messages */
    255     strcpy(ret_msg, vals[i].ascii);
    256     strcat(ret_msg, ": incorrect return value");
    257     strcpy(result_msg, vals[i].ascii);
    258     strcat(result_msg, ": incorrect result generated");
    259 }
    260 #if 0
    261 static void
    262 append_get_return_value(int val)
    263 {
    264     char str[64];
    265     sprintf(str, ": %d", val);
    266     strcat(ret_msg, str);
    267 }
    268 #endif
    269 static int
    270 get_common_check_result(int len, const unsigned char *val,
    271                         const unsigned char *correct)
    272 {
    273     char str[64];
    274     int i;
    275     int result = 0;
    276 
    277     for (i=0;i<len;i++)
    278         if (val[i] != correct[i])
    279             result = 1;
    280 
    281     if (result) {
    282         for (i=0; i<len; i++)
    283             sprintf(str+3*i, "%02x ", val[i]);
    284         strcat(result_msg, ": ");
    285         strcat(result_msg, str);
    286     }
    287 
    288     return result;
    289 }
    290 
    291 /*
    292  * get_single tests
    293  */
    294 
    295 static int
    296 test_get_single_normalized(void)
    297 {
    298     unsigned char outval[4];
    299     Init_Entry *vals = normalized_vals;
    300     int i, num = sizeof(normalized_vals)/sizeof(Init_Entry);
    301 
    302     for (i=0; i<num; i++) {
    303         get_common_setup(vals, i);
    304         if (yasm_floatnum_get_sized(flt, outval, 4, 32, 0, 0, 0) !=
    305             vals[i].ret32)
    306             return 1;
    307         if (get_common_check_result(4, outval, vals[i].result32) != 0)
    308             return 1;
    309     }
    310     return 0;
    311 }
    312 
    313 static int
    314 test_get_single_normalized_edgecase(void)
    315 {
    316     unsigned char outval[4];
    317     Init_Entry *vals = normalized_edgecase_vals;
    318     int i, num = sizeof(normalized_edgecase_vals)/sizeof(Init_Entry);
    319 
    320     for (i=0; i<num; i++) {
    321         get_common_setup(vals, i);
    322         if (yasm_floatnum_get_sized(flt, outval, 4, 32, 0, 0, 0) !=
    323             vals[i].ret32)
    324             return 1;
    325         if (get_common_check_result(4, outval, vals[i].result32) != 0)
    326             return 1;
    327     }
    328     return 0;
    329 }
    330 
    331 /*
    332  * get_double tests
    333  */
    334 
    335 static int
    336 test_get_double_normalized(void)
    337 {
    338     unsigned char outval[8];
    339     Init_Entry *vals = normalized_vals;
    340     int i, num = sizeof(normalized_vals)/sizeof(Init_Entry);
    341 
    342     for (i=0; i<num; i++) {
    343         get_common_setup(vals, i);
    344         if (yasm_floatnum_get_sized(flt, outval, 8, 64, 0, 0, 0) !=
    345             vals[i].ret64)
    346             return 1;
    347         if (get_common_check_result(8, outval, vals[i].result64) != 0)
    348             return 1;
    349     }
    350     return 0;
    351 }
    352 
    353 static int
    354 test_get_double_normalized_edgecase(void)
    355 {
    356     unsigned char outval[8];
    357     Init_Entry *vals = normalized_edgecase_vals;
    358     int i, num = sizeof(normalized_edgecase_vals)/sizeof(Init_Entry);
    359 
    360     for (i=0; i<num; i++) {
    361         get_common_setup(vals, i);
    362         if (yasm_floatnum_get_sized(flt, outval, 8, 64, 0, 0, 0) !=
    363             vals[i].ret64)
    364             return 1;
    365         if (get_common_check_result(8, outval, vals[i].result64) != 0)
    366             return 1;
    367     }
    368     return 0;
    369 }
    370 
    371 /*
    372  * get_extended tests
    373  */
    374 
    375 static int
    376 test_get_extended_normalized(void)
    377 {
    378     unsigned char outval[10];
    379     Init_Entry *vals = normalized_vals;
    380     int i, num = sizeof(normalized_vals)/sizeof(Init_Entry);
    381 
    382     for (i=0; i<num; i++) {
    383         get_common_setup(vals, i);
    384         if (yasm_floatnum_get_sized(flt, outval, 10, 80, 0, 0, 0) !=
    385             vals[i].ret80)
    386             return 1;
    387         if (get_common_check_result(10, outval, vals[i].result80) != 0)
    388             return 1;
    389     }
    390     return 0;
    391 }
    392 
    393 static int
    394 test_get_extended_normalized_edgecase(void)
    395 {
    396     unsigned char outval[10];
    397     Init_Entry *vals = normalized_edgecase_vals;
    398     int i, num = sizeof(normalized_edgecase_vals)/sizeof(Init_Entry);
    399 
    400     for (i=0; i<num; i++) {
    401         get_common_setup(vals, i);
    402         if (yasm_floatnum_get_sized(flt, outval, 10, 80, 0, 0, 0) !=
    403             vals[i].ret80)
    404             return 1;
    405         if (get_common_check_result(10, outval, vals[i].result80) != 0)
    406             return 1;
    407     }
    408     return 0;
    409 }
    410 
    411 char failed[1000];
    412 
    413 static int
    414 runtest_(const char *testname, int (*testfunc)(void), void (*setup)(void),
    415          void (*teardown)(void))
    416 {
    417     int nf;
    418     if (setup)
    419         setup();
    420     nf = testfunc();
    421     if (teardown)
    422         teardown();
    423     printf("%c", nf>0 ? 'F':'.');
    424     fflush(stdout);
    425     if (nf > 0)
    426         sprintf(failed, "%s ** F: %s failed: %s!\n", failed, testname,
    427                 result_msg);
    428     return nf;
    429 }
    430 #define runtest(x,y,z)  runtest_(#x,test_##x,y,z)
    431 
    432 int
    433 main(void)
    434 {
    435     int nf = 0;
    436     if (BitVector_Boot() != ErrCode_Ok)
    437         return EXIT_FAILURE;
    438     yasm_floatnum_initialize();
    439 
    440     failed[0] = '\0';
    441     printf("Test floatnum_test: ");
    442     nf += runtest(new_normalized, NULL, NULL);
    443     nf += runtest(new_normalized_edgecase, NULL, NULL);
    444     nf += runtest(get_single_normalized, get_family_setup, get_family_teardown);
    445     nf += runtest(get_single_normalized_edgecase, get_family_setup, get_family_teardown);
    446     nf += runtest(get_double_normalized, get_family_setup, get_family_teardown);
    447     nf += runtest(get_double_normalized_edgecase, get_family_setup, get_family_teardown);
    448     nf += runtest(get_extended_normalized, get_family_setup, get_family_teardown);
    449     nf += runtest(get_extended_normalized_edgecase, get_family_setup, get_family_teardown);
    450     printf(" +%d-%d/8 %d%%\n%s",
    451            8-nf, nf, 100*(8-nf)/8, failed);
    452     return (nf == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
    453 }
    454