/* $Id: floatnum_test.c 1892 2007-07-13 20:56:28Z peter $ * * Copyright (C) 2001-2007 Peter Johnson * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS'' * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include "libyasm/floatnum.c" /* constants describing parameters of internal floating point format. * (these should match those in src/floatnum.c !) */ #define MANT_BITS 80 #define MANT_BYTES 10 typedef struct Init_Entry_s { /* input ASCII value */ const char *ascii; /* correct output from ASCII conversion */ unsigned char mantissa[MANT_BYTES]; /* little endian mantissa - first byte is not checked for correctness. */ unsigned short exponent; /* bias 32767 exponent */ unsigned char sign; unsigned char flags; /* correct output conversions - these should be *exact* matches */ int ret32; unsigned char result32[4]; int ret64; unsigned char result64[8]; int ret80; unsigned char result80[10]; } Init_Entry; /* Values used for normalized tests */ static Init_Entry normalized_vals[] = { { "3.141592653589793", {0xc6,0x0d,0xe9,0xbd,0x68,0x21,0xa2,0xda,0x0f,0xc9},0x8000,0,0, 0, {0xdb,0x0f,0x49,0x40}, 0, {0x18,0x2d,0x44,0x54,0xfb,0x21,0x09,0x40}, 0, {0xe9,0xbd,0x68,0x21,0xa2,0xda,0x0f,0xc9,0x00,0x40} }, { "-3.141592653589793", {0xc6,0x0d,0xe9,0xbd,0x68,0x21,0xa2,0xda,0x0f,0xc9},0x8000,1,0, 0, {0xdb,0x0f,0x49,0xc0}, 0, {0x18,0x2d,0x44,0x54,0xfb,0x21,0x09,0xc0}, 0, {0xe9,0xbd,0x68,0x21,0xa2,0xda,0x0f,0xc9,0x00,0xc0} }, { "1.e16", {0x00,0x00,0x00,0x00,0x00,0x04,0xbf,0xc9,0x1b,0x8e},0x8034,0,0, 0, {0xca,0x1b,0x0e,0x5a}, 0, {0x00,0x80,0xe0,0x37,0x79,0xc3,0x41,0x43}, 0, {0x00,0x00,0x00,0x04,0xbf,0xc9,0x1b,0x8e,0x34,0x40} }, { "1.6e-20", {0xf6,0xd3,0xee,0x7b,0xda,0x74,0x50,0xa0,0x1d,0x97},0x7fbd,0,0, 0, {0xa0,0x1d,0x97,0x1e}, 0, {0x4f,0x9b,0x0e,0x0a,0xb4,0xe3,0xd2,0x3b}, 0, {0xef,0x7b,0xda,0x74,0x50,0xa0,0x1d,0x97,0xbd,0x3f} }, { "-5876.", {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0xb7},0x800b,1,0, 0, {0x00,0xa0,0xb7,0xc5}, 0, {0x00,0x00,0x00,0x00,0x00,0xf4,0xb6,0xc0}, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0xb7,0x0b,0xc0} }, /* Edge cases for rounding wrap. */ { "1.00000", {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff},0x7ffe,0,0, 0, {0x00,0x00,0x80,0x3f}, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0x3f}, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff,0x3f} }, { "1.000000", {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff},0x7ffe,0,0, 0, {0x00,0x00,0x80,0x3f}, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0x3f}, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff,0x3f} }, }; /* Still normalized values, but edge cases of various sizes, testing underflow/ * overflow checks as well. */ static Init_Entry normalized_edgecase_vals[] = { /* 32-bit edges */ { "1.1754943508222875e-38", {0xd5,0xf2,0x82,0xff,0xff,0xff,0xff,0xff,0xff,0xff},0x7f80,0,0, 0, {0x00,0x00,0x80,0x00}, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x38}, 0, {0x83,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x80,0x3f} }, { "3.4028234663852886e+38", {0x21,0x35,0x0a,0x00,0x00,0x00,0x00,0xff,0xff,0xff},0x807e,0,0, 0, {0xff,0xff,0x7f,0x7f}, 0, {0x00,0x00,0x00,0xe0,0xff,0xff,0xef,0x47}, 0, {0x0a,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0x7e,0x40} }, /* 64-bit edges */ { "2.2250738585072014E-308", {0x26,0x18,0x46,0x00,0x00,0x00,0x00,0x00,0x00,0x80},0x7c01,0,0, -1, {0x00,0x00,0x00,0x00}, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00}, 0, {0x46,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x01,0x3c} }, { "1.7976931348623157E+308", {0x26,0x6b,0xac,0xf7,0xff,0xff,0xff,0xff,0xff,0xff},0x83fe,0,0, 1, {0x00,0x00,0x80,0x7f}, 0, {0xff,0xff,0xff,0xff,0xff,0xff,0xef,0x7f}, 0, {0xac,0xf7,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0x43} }, /* 80-bit edges */ /* { "3.3621E-4932", {},,0,0, -1, {0x00,0x00,0x00,0x00}, -1, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 0, {} }, { "1.1897E+4932", {},,0,0, 1, {0x00,0x00,0x80,0x7f}, 1, {}, 0, {} },*/ /* internal format edges */ /* { }, { },*/ }; static yasm_floatnum *flt; /* failure messages */ static char ret_msg[1024], result_msg[1024]; static void new_setup(Init_Entry *vals, int i) { flt = yasm_floatnum_create(vals[i].ascii); strcpy(result_msg, vals[i].ascii); strcat(result_msg, ": incorrect "); } static int new_check_flt(Init_Entry *val) { unsigned char *mantissa; int i, result = 0; unsigned int len; mantissa = BitVector_Block_Read(flt->mantissa, &len); for (i=1;imantissa[i]) result = 1; free(mantissa); if (result) { strcat(result_msg, "mantissa"); return 1; } if (flt->exponent != val->exponent) { strcat(result_msg, "exponent"); return 1; } if (flt->sign != val->sign) { strcat(result_msg, "sign"); return 1; } if (flt->flags != val->flags) { strcat(result_msg, "flags"); return 1; } return 0; } static int test_new_normalized(void) { Init_Entry *vals = normalized_vals; int i, num = sizeof(normalized_vals)/sizeof(Init_Entry); for (i=0; imantissa = BitVector_Create(MANT_BITS, TRUE); } static void get_family_teardown(void) { BitVector_Destroy(flt->mantissa); free(flt); } static void get_common_setup(Init_Entry *vals, int i) { /* set up flt */ BitVector_Block_Store(flt->mantissa, vals[i].mantissa, MANT_BYTES); flt->sign = vals[i].sign; flt->exponent = vals[i].exponent; flt->flags = vals[i].flags; /* set failure messages */ strcpy(ret_msg, vals[i].ascii); strcat(ret_msg, ": incorrect return value"); strcpy(result_msg, vals[i].ascii); strcat(result_msg, ": incorrect result generated"); } #if 0 static void append_get_return_value(int val) { char str[64]; sprintf(str, ": %d", val); strcat(ret_msg, str); } #endif static int get_common_check_result(int len, const unsigned char *val, const unsigned char *correct) { char str[64]; int i; int result = 0; for (i=0;i0 ? 'F':'.'); fflush(stdout); if (nf > 0) sprintf(failed, "%s ** F: %s failed: %s!\n", failed, testname, result_msg); return nf; } #define runtest(x,y,z) runtest_(#x,test_##x,y,z) int main(void) { int nf = 0; if (BitVector_Boot() != ErrCode_Ok) return EXIT_FAILURE; yasm_floatnum_initialize(); failed[0] = '\0'; printf("Test floatnum_test: "); nf += runtest(new_normalized, NULL, NULL); nf += runtest(new_normalized_edgecase, NULL, NULL); nf += runtest(get_single_normalized, get_family_setup, get_family_teardown); nf += runtest(get_single_normalized_edgecase, get_family_setup, get_family_teardown); nf += runtest(get_double_normalized, get_family_setup, get_family_teardown); nf += runtest(get_double_normalized_edgecase, get_family_setup, get_family_teardown); nf += runtest(get_extended_normalized, get_family_setup, get_family_teardown); nf += runtest(get_extended_normalized_edgecase, get_family_setup, get_family_teardown); printf(" +%d-%d/8 %d%%\n%s", 8-nf, nf, 100*(8-nf)/8, failed); return (nf == 0) ? EXIT_SUCCESS : EXIT_FAILURE; }