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 38typedef 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 */ 60static 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 */ 109static 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 156static yasm_floatnum *flt; 157 158/* failure messages */ 159static char ret_msg[1024], result_msg[1024]; 160 161static void 162new_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 169static int 170new_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 201static int 202test_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 216static int 217test_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 231static void 232get_family_setup(void) 233{ 234 flt = malloc(sizeof(yasm_floatnum)); 235 flt->mantissa = BitVector_Create(MANT_BITS, TRUE); 236} 237 238static void 239get_family_teardown(void) 240{ 241 BitVector_Destroy(flt->mantissa); 242 free(flt); 243} 244 245static void 246get_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 261static void 262append_get_return_value(int val) 263{ 264 char str[64]; 265 sprintf(str, ": %d", val); 266 strcat(ret_msg, str); 267} 268#endif 269static int 270get_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 295static int 296test_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 313static int 314test_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 335static int 336test_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 353static int 354test_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 375static int 376test_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 393static int 394test_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 411char failed[1000]; 412 413static int 414runtest_(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 432int 433main(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