testsoftfloat.c revision 206921
1 2/* 3=============================================================================== 4 5This C source file is part of TestFloat, Release 2a, a package of programs 6for testing the correctness of floating-point arithmetic complying to the 7IEC/IEEE Standard for Floating-Point. 8 9Written by John R. Hauser. More information is available through the Web 10page `http://HTTP.CS.Berkeley.EDU/~jhauser/arithmetic/TestFloat.html'. 11 12THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort 13has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT 14TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO 15PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY 16AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE. 17 18Derivative works are acceptable, even for commercial purposes, so long as 19(1) they include prominent notice that the work is derivative, and (2) they 20include prominent notice akin to these four paragraphs for those parts of 21this code that are retained. 22 23=============================================================================== 24*/ 25 26#include <stdlib.h> 27#include <signal.h> 28#include <string.h> 29#include "milieu.h" 30#include "fail.h" 31#include "softfloat.h" 32#include "slowfloat.h" 33#include "testCases.h" 34#include "testLoops.h" 35 36static void catchSIGINT( int signalCode ) 37{ 38 39 if ( stop ) exit( EXIT_FAILURE ); 40 stop = TRUE; 41 42} 43 44int8 clearFlags( void ) 45{ 46 int8 flags; 47 48 flags = float_exception_flags; 49 float_exception_flags = 0; 50 return flags; 51 52} 53 54enum { 55 INT32_TO_FLOAT32 = 1, 56 INT32_TO_FLOAT64, 57#ifdef FLOATX80 58 INT32_TO_FLOATX80, 59#endif 60#ifdef FLOAT128 61 INT32_TO_FLOAT128, 62#endif 63#ifdef BITS64 64 INT64_TO_FLOAT32, 65 INT64_TO_FLOAT64, 66#ifdef FLOATX80 67 INT64_TO_FLOATX80, 68#endif 69#ifdef FLOAT128 70 INT64_TO_FLOAT128, 71#endif 72#endif 73 FLOAT32_TO_INT32, 74 FLOAT32_TO_INT32_ROUND_TO_ZERO, 75#ifdef BITS64 76 FLOAT32_TO_INT64, 77 FLOAT32_TO_INT64_ROUND_TO_ZERO, 78#endif 79 FLOAT32_TO_FLOAT64, 80#ifdef FLOATX80 81 FLOAT32_TO_FLOATX80, 82#endif 83#ifdef FLOAT128 84 FLOAT32_TO_FLOAT128, 85#endif 86 FLOAT32_ROUND_TO_INT, 87 FLOAT32_ADD, 88 FLOAT32_SUB, 89 FLOAT32_MUL, 90 FLOAT32_DIV, 91 FLOAT32_REM, 92 FLOAT32_SQRT, 93 FLOAT32_EQ, 94 FLOAT32_LE, 95 FLOAT32_LT, 96 FLOAT32_EQ_SIGNALING, 97 FLOAT32_LE_QUIET, 98 FLOAT32_LT_QUIET, 99 FLOAT64_TO_INT32, 100 FLOAT64_TO_INT32_ROUND_TO_ZERO, 101#ifdef BITS64 102 FLOAT64_TO_INT64, 103 FLOAT64_TO_INT64_ROUND_TO_ZERO, 104#endif 105 FLOAT64_TO_FLOAT32, 106#ifdef FLOATX80 107 FLOAT64_TO_FLOATX80, 108#endif 109#ifdef FLOAT128 110 FLOAT64_TO_FLOAT128, 111#endif 112 FLOAT64_ROUND_TO_INT, 113 FLOAT64_ADD, 114 FLOAT64_SUB, 115 FLOAT64_MUL, 116 FLOAT64_DIV, 117 FLOAT64_REM, 118 FLOAT64_SQRT, 119 FLOAT64_EQ, 120 FLOAT64_LE, 121 FLOAT64_LT, 122 FLOAT64_EQ_SIGNALING, 123 FLOAT64_LE_QUIET, 124 FLOAT64_LT_QUIET, 125#ifdef FLOATX80 126 FLOATX80_TO_INT32, 127 FLOATX80_TO_INT32_ROUND_TO_ZERO, 128#ifdef BITS64 129 FLOATX80_TO_INT64, 130 FLOATX80_TO_INT64_ROUND_TO_ZERO, 131#endif 132 FLOATX80_TO_FLOAT32, 133 FLOATX80_TO_FLOAT64, 134#ifdef FLOAT128 135 FLOATX80_TO_FLOAT128, 136#endif 137 FLOATX80_ROUND_TO_INT, 138 FLOATX80_ADD, 139 FLOATX80_SUB, 140 FLOATX80_MUL, 141 FLOATX80_DIV, 142 FLOATX80_REM, 143 FLOATX80_SQRT, 144 FLOATX80_EQ, 145 FLOATX80_LE, 146 FLOATX80_LT, 147 FLOATX80_EQ_SIGNALING, 148 FLOATX80_LE_QUIET, 149 FLOATX80_LT_QUIET, 150#endif 151#ifdef FLOAT128 152 FLOAT128_TO_INT32, 153 FLOAT128_TO_INT32_ROUND_TO_ZERO, 154#ifdef BITS64 155 FLOAT128_TO_INT64, 156 FLOAT128_TO_INT64_ROUND_TO_ZERO, 157#endif 158 FLOAT128_TO_FLOAT32, 159 FLOAT128_TO_FLOAT64, 160#ifdef FLOATX80 161 FLOAT128_TO_FLOATX80, 162#endif 163 FLOAT128_ROUND_TO_INT, 164 FLOAT128_ADD, 165 FLOAT128_SUB, 166 FLOAT128_MUL, 167 FLOAT128_DIV, 168 FLOAT128_REM, 169 FLOAT128_SQRT, 170 FLOAT128_EQ, 171 FLOAT128_LE, 172 FLOAT128_LT, 173 FLOAT128_EQ_SIGNALING, 174 FLOAT128_LE_QUIET, 175 FLOAT128_LT_QUIET, 176#endif 177 NUM_FUNCTIONS 178}; 179static struct { 180 char *name; 181 int8 numInputs; 182 flag roundingPrecision, roundingMode; 183 flag tininessMode, tininessModeAtReducedPrecision; 184} functions[ NUM_FUNCTIONS ] = { 185 { 0, 0, 0, 0, 0, 0 }, 186 { "int32_to_float32", 1, FALSE, TRUE, FALSE, FALSE }, 187 { "int32_to_float64", 1, FALSE, FALSE, FALSE, FALSE }, 188#ifdef FLOATX80 189 { "int32_to_floatx80", 1, FALSE, FALSE, FALSE, FALSE }, 190#endif 191#ifdef FLOAT128 192 { "int32_to_float128", 1, FALSE, FALSE, FALSE, FALSE }, 193#endif 194#ifdef BITS64 195 { "int64_to_float32", 1, FALSE, TRUE, FALSE, FALSE }, 196 { "int64_to_float64", 1, FALSE, TRUE, FALSE, FALSE }, 197#ifdef FLOATX80 198 { "int64_to_floatx80", 1, FALSE, FALSE, FALSE, FALSE }, 199#endif 200#ifdef FLOAT128 201 { "int64_to_float128", 1, FALSE, FALSE, FALSE, FALSE }, 202#endif 203#endif 204 { "float32_to_int32", 1, FALSE, TRUE, FALSE, FALSE }, 205 { "float32_to_int32_round_to_zero", 1, FALSE, FALSE, FALSE, FALSE }, 206#ifdef BITS64 207 { "float32_to_int64", 1, FALSE, TRUE, FALSE, FALSE }, 208 { "float32_to_int64_round_to_zero", 1, FALSE, FALSE, FALSE, FALSE }, 209#endif 210 { "float32_to_float64", 1, FALSE, FALSE, FALSE, FALSE }, 211#ifdef FLOATX80 212 { "float32_to_floatx80", 1, FALSE, FALSE, FALSE, FALSE }, 213#endif 214#ifdef FLOAT128 215 { "float32_to_float128", 1, FALSE, FALSE, FALSE, FALSE }, 216#endif 217 { "float32_round_to_int", 1, FALSE, TRUE, FALSE, FALSE }, 218 { "float32_add", 2, FALSE, TRUE, FALSE, FALSE }, 219 { "float32_sub", 2, FALSE, TRUE, FALSE, FALSE }, 220 { "float32_mul", 2, FALSE, TRUE, TRUE, FALSE }, 221 { "float32_div", 2, FALSE, TRUE, FALSE, FALSE }, 222 { "float32_rem", 2, FALSE, FALSE, FALSE, FALSE }, 223 { "float32_sqrt", 1, FALSE, TRUE, FALSE, FALSE }, 224 { "float32_eq", 2, FALSE, FALSE, FALSE, FALSE }, 225 { "float32_le", 2, FALSE, FALSE, FALSE, FALSE }, 226 { "float32_lt", 2, FALSE, FALSE, FALSE, FALSE }, 227 { "float32_eq_signaling", 2, FALSE, FALSE, FALSE, FALSE }, 228 { "float32_le_quiet", 2, FALSE, FALSE, FALSE, FALSE }, 229 { "float32_lt_quiet", 2, FALSE, FALSE, FALSE, FALSE }, 230 { "float64_to_int32", 1, FALSE, TRUE, FALSE, FALSE }, 231 { "float64_to_int32_round_to_zero", 1, FALSE, FALSE, FALSE, FALSE }, 232#ifdef BITS64 233 { "float64_to_int64", 1, FALSE, TRUE, FALSE, FALSE }, 234 { "float64_to_int64_round_to_zero", 1, FALSE, FALSE, FALSE, FALSE }, 235#endif 236 { "float64_to_float32", 1, FALSE, TRUE, TRUE, FALSE }, 237#ifdef FLOATX80 238 { "float64_to_floatx80", 1, FALSE, FALSE, FALSE, FALSE }, 239#endif 240#ifdef FLOAT128 241 { "float64_to_float128", 1, FALSE, FALSE, FALSE, FALSE }, 242#endif 243 { "float64_round_to_int", 1, FALSE, TRUE, FALSE, FALSE }, 244 { "float64_add", 2, FALSE, TRUE, FALSE, FALSE }, 245 { "float64_sub", 2, FALSE, TRUE, FALSE, FALSE }, 246 { "float64_mul", 2, FALSE, TRUE, TRUE, FALSE }, 247 { "float64_div", 2, FALSE, TRUE, FALSE, FALSE }, 248 { "float64_rem", 2, FALSE, FALSE, FALSE, FALSE }, 249 { "float64_sqrt", 1, FALSE, TRUE, FALSE, FALSE }, 250 { "float64_eq", 2, FALSE, FALSE, FALSE, FALSE }, 251 { "float64_le", 2, FALSE, FALSE, FALSE, FALSE }, 252 { "float64_lt", 2, FALSE, FALSE, FALSE, FALSE }, 253 { "float64_eq_signaling", 2, FALSE, FALSE, FALSE, FALSE }, 254 { "float64_le_quiet", 2, FALSE, FALSE, FALSE, FALSE }, 255 { "float64_lt_quiet", 2, FALSE, FALSE, FALSE, FALSE }, 256#ifdef FLOATX80 257 { "floatx80_to_int32", 1, FALSE, TRUE, FALSE, FALSE }, 258 { "floatx80_to_int32_round_to_zero", 1, FALSE, FALSE, FALSE, FALSE }, 259#ifdef BITS64 260 { "floatx80_to_int64", 1, FALSE, TRUE, FALSE, FALSE }, 261 { "floatx80_to_int64_round_to_zero", 1, FALSE, FALSE, FALSE, FALSE }, 262#endif 263 { "floatx80_to_float32", 1, FALSE, TRUE, TRUE, FALSE }, 264 { "floatx80_to_float64", 1, FALSE, TRUE, TRUE, FALSE }, 265#ifdef FLOAT128 266 { "floatx80_to_float128", 1, FALSE, FALSE, FALSE, FALSE }, 267#endif 268 { "floatx80_round_to_int", 1, FALSE, TRUE, FALSE, FALSE }, 269 { "floatx80_add", 2, TRUE, TRUE, FALSE, TRUE }, 270 { "floatx80_sub", 2, TRUE, TRUE, FALSE, TRUE }, 271 { "floatx80_mul", 2, TRUE, TRUE, TRUE, TRUE }, 272 { "floatx80_div", 2, TRUE, TRUE, FALSE, TRUE }, 273 { "floatx80_rem", 2, FALSE, FALSE, FALSE, FALSE }, 274 { "floatx80_sqrt", 1, TRUE, TRUE, FALSE, FALSE }, 275 { "floatx80_eq", 2, FALSE, FALSE, FALSE, FALSE }, 276 { "floatx80_le", 2, FALSE, FALSE, FALSE, FALSE }, 277 { "floatx80_lt", 2, FALSE, FALSE, FALSE, FALSE }, 278 { "floatx80_eq_signaling", 2, FALSE, FALSE, FALSE, FALSE }, 279 { "floatx80_le_quiet", 2, FALSE, FALSE, FALSE, FALSE }, 280 { "floatx80_lt_quiet", 2, FALSE, FALSE, FALSE, FALSE }, 281#endif 282#ifdef FLOAT128 283 { "float128_to_int32", 1, FALSE, TRUE, FALSE, FALSE }, 284 { "float128_to_int32_round_to_zero", 1, FALSE, FALSE, FALSE, FALSE }, 285#ifdef BITS64 286 { "float128_to_int64", 1, FALSE, TRUE, FALSE, FALSE }, 287 { "float128_to_int64_round_to_zero", 1, FALSE, FALSE, FALSE, FALSE }, 288#endif 289 { "float128_to_float32", 1, FALSE, TRUE, TRUE, FALSE }, 290 { "float128_to_float64", 1, FALSE, TRUE, TRUE, FALSE }, 291#ifdef FLOATX80 292 { "float128_to_floatx80", 1, FALSE, TRUE, TRUE, FALSE }, 293#endif 294 { "float128_round_to_int", 1, FALSE, TRUE, FALSE, FALSE }, 295 { "float128_add", 2, FALSE, TRUE, FALSE, FALSE }, 296 { "float128_sub", 2, FALSE, TRUE, FALSE, FALSE }, 297 { "float128_mul", 2, FALSE, TRUE, TRUE, FALSE }, 298 { "float128_div", 2, FALSE, TRUE, FALSE, FALSE }, 299 { "float128_rem", 2, FALSE, FALSE, FALSE, FALSE }, 300 { "float128_sqrt", 1, FALSE, TRUE, FALSE, FALSE }, 301 { "float128_eq", 2, FALSE, FALSE, FALSE, FALSE }, 302 { "float128_le", 2, FALSE, FALSE, FALSE, FALSE }, 303 { "float128_lt", 2, FALSE, FALSE, FALSE, FALSE }, 304 { "float128_eq_signaling", 2, FALSE, FALSE, FALSE, FALSE }, 305 { "float128_le_quiet", 2, FALSE, FALSE, FALSE, FALSE }, 306 { "float128_lt_quiet", 2, FALSE, FALSE, FALSE, FALSE }, 307#endif 308}; 309 310enum { 311 ROUND_NEAREST_EVEN = 1, 312 ROUND_TO_ZERO, 313 ROUND_DOWN, 314 ROUND_UP, 315 NUM_ROUNDINGMODES 316}; 317enum { 318 TININESS_BEFORE_ROUNDING = 1, 319 TININESS_AFTER_ROUNDING, 320 NUM_TININESSMODES 321}; 322 323static void 324 testFunctionVariety( 325 uint8 functionCode, 326 int8 roundingPrecision, 327 int8 roundingMode, 328 int8 tininessMode 329 ) 330{ 331 uint8 roundingCode; 332 int8 tininessCode; 333 334 functionName = functions[ functionCode ].name; 335 if ( roundingPrecision == 32 ) { 336 roundingPrecisionName = "32"; 337 } 338 else if ( roundingPrecision == 64 ) { 339 roundingPrecisionName = "64"; 340 } 341 else if ( roundingPrecision == 80 ) { 342 roundingPrecisionName = "80"; 343 } 344 else { 345 roundingPrecisionName = 0; 346 } 347#ifdef FLOATX80 348 floatx80_rounding_precision = roundingPrecision; 349 slow_floatx80_rounding_precision = roundingPrecision; 350#endif 351 switch ( roundingMode ) { 352 case 0: 353 roundingModeName = 0; 354 roundingCode = float_round_nearest_even; 355 break; 356 case ROUND_NEAREST_EVEN: 357 roundingModeName = "nearest_even"; 358 roundingCode = float_round_nearest_even; 359 break; 360 case ROUND_TO_ZERO: 361 roundingModeName = "to_zero"; 362 roundingCode = float_round_to_zero; 363 break; 364 case ROUND_DOWN: 365 roundingModeName = "down"; 366 roundingCode = float_round_down; 367 break; 368 case ROUND_UP: 369 roundingModeName = "up"; 370 roundingCode = float_round_up; 371 break; 372 } 373 float_rounding_mode = roundingCode; 374 slow_float_rounding_mode = roundingCode; 375 switch ( tininessMode ) { 376 case 0: 377 tininessModeName = 0; 378 tininessCode = float_tininess_after_rounding; 379 break; 380 case TININESS_BEFORE_ROUNDING: 381 tininessModeName = "before"; 382 tininessCode = float_tininess_before_rounding; 383 break; 384 case TININESS_AFTER_ROUNDING: 385 tininessModeName = "after"; 386 tininessCode = float_tininess_after_rounding; 387 break; 388 } 389 float_detect_tininess = tininessCode; 390 slow_float_detect_tininess = tininessCode; 391 fputs( "Testing ", stderr ); 392 writeFunctionName( stderr ); 393 fputs( ".\n", stderr ); 394 switch ( functionCode ) { 395 case INT32_TO_FLOAT32: 396 test_a_int32_z_float32( slow_int32_to_float32, int32_to_float32 ); 397 break; 398 case INT32_TO_FLOAT64: 399 test_a_int32_z_float64( slow_int32_to_float64, int32_to_float64 ); 400 break; 401#ifdef FLOATX80 402 case INT32_TO_FLOATX80: 403 test_a_int32_z_floatx80( slow_int32_to_floatx80, int32_to_floatx80 ); 404 break; 405#endif 406#ifdef FLOAT128 407 case INT32_TO_FLOAT128: 408 test_a_int32_z_float128( slow_int32_to_float128, int32_to_float128 ); 409 break; 410#endif 411#ifdef BITS64 412 case INT64_TO_FLOAT32: 413 test_a_int64_z_float32( slow_int64_to_float32, int64_to_float32 ); 414 break; 415 case INT64_TO_FLOAT64: 416 test_a_int64_z_float64( slow_int64_to_float64, int64_to_float64 ); 417 break; 418#ifdef FLOATX80 419 case INT64_TO_FLOATX80: 420 test_a_int64_z_floatx80( slow_int64_to_floatx80, int64_to_floatx80 ); 421 break; 422#endif 423#ifdef FLOAT128 424 case INT64_TO_FLOAT128: 425 test_a_int64_z_float128( slow_int64_to_float128, int64_to_float128 ); 426 break; 427#endif 428#endif 429 case FLOAT32_TO_INT32: 430 test_a_float32_z_int32( slow_float32_to_int32, float32_to_int32 ); 431 break; 432 case FLOAT32_TO_INT32_ROUND_TO_ZERO: 433 test_a_float32_z_int32( 434 slow_float32_to_int32_round_to_zero, 435 float32_to_int32_round_to_zero 436 ); 437 break; 438#ifdef BITS64 439 case FLOAT32_TO_INT64: 440 test_a_float32_z_int64( slow_float32_to_int64, float32_to_int64 ); 441 break; 442 case FLOAT32_TO_INT64_ROUND_TO_ZERO: 443 test_a_float32_z_int64( 444 slow_float32_to_int64_round_to_zero, 445 float32_to_int64_round_to_zero 446 ); 447 break; 448#endif 449 case FLOAT32_TO_FLOAT64: 450 test_a_float32_z_float64( 451 slow_float32_to_float64, float32_to_float64 ); 452 break; 453#ifdef FLOATX80 454 case FLOAT32_TO_FLOATX80: 455 test_a_float32_z_floatx80( 456 slow_float32_to_floatx80, float32_to_floatx80 ); 457 break; 458#endif 459#ifdef FLOAT128 460 case FLOAT32_TO_FLOAT128: 461 test_a_float32_z_float128( 462 slow_float32_to_float128, float32_to_float128 ); 463 break; 464#endif 465 case FLOAT32_ROUND_TO_INT: 466 test_az_float32( slow_float32_round_to_int, float32_round_to_int ); 467 break; 468 case FLOAT32_ADD: 469 test_abz_float32( slow_float32_add, float32_add ); 470 break; 471 case FLOAT32_SUB: 472 test_abz_float32( slow_float32_sub, float32_sub ); 473 break; 474 case FLOAT32_MUL: 475 test_abz_float32( slow_float32_mul, float32_mul ); 476 break; 477 case FLOAT32_DIV: 478 test_abz_float32( slow_float32_div, float32_div ); 479 break; 480 case FLOAT32_REM: 481 test_abz_float32( slow_float32_rem, float32_rem ); 482 break; 483 case FLOAT32_SQRT: 484 test_az_float32( slow_float32_sqrt, float32_sqrt ); 485 break; 486 case FLOAT32_EQ: 487 test_ab_float32_z_flag( slow_float32_eq, float32_eq ); 488 break; 489 case FLOAT32_LE: 490 test_ab_float32_z_flag( slow_float32_le, float32_le ); 491 break; 492 case FLOAT32_LT: 493 test_ab_float32_z_flag( slow_float32_lt, float32_lt ); 494 break; 495 case FLOAT32_EQ_SIGNALING: 496 test_ab_float32_z_flag( 497 slow_float32_eq_signaling, float32_eq_signaling ); 498 break; 499 case FLOAT32_LE_QUIET: 500 test_ab_float32_z_flag( slow_float32_le_quiet, float32_le_quiet ); 501 break; 502 case FLOAT32_LT_QUIET: 503 test_ab_float32_z_flag( slow_float32_lt_quiet, float32_lt_quiet ); 504 break; 505 case FLOAT64_TO_INT32: 506 test_a_float64_z_int32( slow_float64_to_int32, float64_to_int32 ); 507 break; 508 case FLOAT64_TO_INT32_ROUND_TO_ZERO: 509 test_a_float64_z_int32( 510 slow_float64_to_int32_round_to_zero, 511 float64_to_int32_round_to_zero 512 ); 513 break; 514#ifdef BITS64 515 case FLOAT64_TO_INT64: 516 test_a_float64_z_int64( slow_float64_to_int64, float64_to_int64 ); 517 break; 518 case FLOAT64_TO_INT64_ROUND_TO_ZERO: 519 test_a_float64_z_int64( 520 slow_float64_to_int64_round_to_zero, 521 float64_to_int64_round_to_zero 522 ); 523 break; 524#endif 525 case FLOAT64_TO_FLOAT32: 526 test_a_float64_z_float32( 527 slow_float64_to_float32, float64_to_float32 ); 528 break; 529#ifdef FLOATX80 530 case FLOAT64_TO_FLOATX80: 531 test_a_float64_z_floatx80( 532 slow_float64_to_floatx80, float64_to_floatx80 ); 533 break; 534#endif 535#ifdef FLOAT128 536 case FLOAT64_TO_FLOAT128: 537 test_a_float64_z_float128( 538 slow_float64_to_float128, float64_to_float128 ); 539 break; 540#endif 541 case FLOAT64_ROUND_TO_INT: 542 test_az_float64( slow_float64_round_to_int, float64_round_to_int ); 543 break; 544 case FLOAT64_ADD: 545 test_abz_float64( slow_float64_add, float64_add ); 546 break; 547 case FLOAT64_SUB: 548 test_abz_float64( slow_float64_sub, float64_sub ); 549 break; 550 case FLOAT64_MUL: 551 test_abz_float64( slow_float64_mul, float64_mul ); 552 break; 553 case FLOAT64_DIV: 554 test_abz_float64( slow_float64_div, float64_div ); 555 break; 556 case FLOAT64_REM: 557 test_abz_float64( slow_float64_rem, float64_rem ); 558 break; 559 case FLOAT64_SQRT: 560 test_az_float64( slow_float64_sqrt, float64_sqrt ); 561 break; 562 case FLOAT64_EQ: 563 test_ab_float64_z_flag( slow_float64_eq, float64_eq ); 564 break; 565 case FLOAT64_LE: 566 test_ab_float64_z_flag( slow_float64_le, float64_le ); 567 break; 568 case FLOAT64_LT: 569 test_ab_float64_z_flag( slow_float64_lt, float64_lt ); 570 break; 571 case FLOAT64_EQ_SIGNALING: 572 test_ab_float64_z_flag( 573 slow_float64_eq_signaling, float64_eq_signaling ); 574 break; 575 case FLOAT64_LE_QUIET: 576 test_ab_float64_z_flag( slow_float64_le_quiet, float64_le_quiet ); 577 break; 578 case FLOAT64_LT_QUIET: 579 test_ab_float64_z_flag( slow_float64_lt_quiet, float64_lt_quiet ); 580 break; 581#ifdef FLOATX80 582 case FLOATX80_TO_INT32: 583 test_a_floatx80_z_int32( slow_floatx80_to_int32, floatx80_to_int32 ); 584 break; 585 case FLOATX80_TO_INT32_ROUND_TO_ZERO: 586 test_a_floatx80_z_int32( 587 slow_floatx80_to_int32_round_to_zero, 588 floatx80_to_int32_round_to_zero 589 ); 590 break; 591#ifdef BITS64 592 case FLOATX80_TO_INT64: 593 test_a_floatx80_z_int64( slow_floatx80_to_int64, floatx80_to_int64 ); 594 break; 595 case FLOATX80_TO_INT64_ROUND_TO_ZERO: 596 test_a_floatx80_z_int64( 597 slow_floatx80_to_int64_round_to_zero, 598 floatx80_to_int64_round_to_zero 599 ); 600 break; 601#endif 602 case FLOATX80_TO_FLOAT32: 603 test_a_floatx80_z_float32( 604 slow_floatx80_to_float32, floatx80_to_float32 ); 605 break; 606 case FLOATX80_TO_FLOAT64: 607 test_a_floatx80_z_float64( 608 slow_floatx80_to_float64, floatx80_to_float64 ); 609 break; 610#ifdef FLOAT128 611 case FLOATX80_TO_FLOAT128: 612 test_a_floatx80_z_float128( 613 slow_floatx80_to_float128, floatx80_to_float128 ); 614 break; 615#endif 616 case FLOATX80_ROUND_TO_INT: 617 test_az_floatx80( slow_floatx80_round_to_int, floatx80_round_to_int ); 618 break; 619 case FLOATX80_ADD: 620 test_abz_floatx80( slow_floatx80_add, floatx80_add ); 621 break; 622 case FLOATX80_SUB: 623 test_abz_floatx80( slow_floatx80_sub, floatx80_sub ); 624 break; 625 case FLOATX80_MUL: 626 test_abz_floatx80( slow_floatx80_mul, floatx80_mul ); 627 break; 628 case FLOATX80_DIV: 629 test_abz_floatx80( slow_floatx80_div, floatx80_div ); 630 break; 631 case FLOATX80_REM: 632 test_abz_floatx80( slow_floatx80_rem, floatx80_rem ); 633 break; 634 case FLOATX80_SQRT: 635 test_az_floatx80( slow_floatx80_sqrt, floatx80_sqrt ); 636 break; 637 case FLOATX80_EQ: 638 test_ab_floatx80_z_flag( slow_floatx80_eq, floatx80_eq ); 639 break; 640 case FLOATX80_LE: 641 test_ab_floatx80_z_flag( slow_floatx80_le, floatx80_le ); 642 break; 643 case FLOATX80_LT: 644 test_ab_floatx80_z_flag( slow_floatx80_lt, floatx80_lt ); 645 break; 646 case FLOATX80_EQ_SIGNALING: 647 test_ab_floatx80_z_flag( 648 slow_floatx80_eq_signaling, floatx80_eq_signaling ); 649 break; 650 case FLOATX80_LE_QUIET: 651 test_ab_floatx80_z_flag( slow_floatx80_le_quiet, floatx80_le_quiet ); 652 break; 653 case FLOATX80_LT_QUIET: 654 test_ab_floatx80_z_flag( slow_floatx80_lt_quiet, floatx80_lt_quiet ); 655 break; 656#endif 657#ifdef FLOAT128 658 case FLOAT128_TO_INT32: 659 test_a_float128_z_int32( slow_float128_to_int32, float128_to_int32 ); 660 break; 661 case FLOAT128_TO_INT32_ROUND_TO_ZERO: 662 test_a_float128_z_int32( 663 slow_float128_to_int32_round_to_zero, 664 float128_to_int32_round_to_zero 665 ); 666 break; 667#ifdef BITS64 668 case FLOAT128_TO_INT64: 669 test_a_float128_z_int64( slow_float128_to_int64, float128_to_int64 ); 670 break; 671 case FLOAT128_TO_INT64_ROUND_TO_ZERO: 672 test_a_float128_z_int64( 673 slow_float128_to_int64_round_to_zero, 674 float128_to_int64_round_to_zero 675 ); 676 break; 677#endif 678 case FLOAT128_TO_FLOAT32: 679 test_a_float128_z_float32( 680 slow_float128_to_float32, float128_to_float32 ); 681 break; 682 case FLOAT128_TO_FLOAT64: 683 test_a_float128_z_float64( 684 slow_float128_to_float64, float128_to_float64 ); 685 break; 686#ifdef FLOATX80 687 case FLOAT128_TO_FLOATX80: 688 test_a_float128_z_floatx80( 689 slow_float128_to_floatx80, float128_to_floatx80 ); 690 break; 691#endif 692 case FLOAT128_ROUND_TO_INT: 693 test_az_float128( slow_float128_round_to_int, float128_round_to_int ); 694 break; 695 case FLOAT128_ADD: 696 test_abz_float128( slow_float128_add, float128_add ); 697 break; 698 case FLOAT128_SUB: 699 test_abz_float128( slow_float128_sub, float128_sub ); 700 break; 701 case FLOAT128_MUL: 702 test_abz_float128( slow_float128_mul, float128_mul ); 703 break; 704 case FLOAT128_DIV: 705 test_abz_float128( slow_float128_div, float128_div ); 706 break; 707 case FLOAT128_REM: 708 test_abz_float128( slow_float128_rem, float128_rem ); 709 break; 710 case FLOAT128_SQRT: 711 test_az_float128( slow_float128_sqrt, float128_sqrt ); 712 break; 713 case FLOAT128_EQ: 714 test_ab_float128_z_flag( slow_float128_eq, float128_eq ); 715 break; 716 case FLOAT128_LE: 717 test_ab_float128_z_flag( slow_float128_le, float128_le ); 718 break; 719 case FLOAT128_LT: 720 test_ab_float128_z_flag( slow_float128_lt, float128_lt ); 721 break; 722 case FLOAT128_EQ_SIGNALING: 723 test_ab_float128_z_flag( 724 slow_float128_eq_signaling, float128_eq_signaling ); 725 break; 726 case FLOAT128_LE_QUIET: 727 test_ab_float128_z_flag( slow_float128_le_quiet, float128_le_quiet ); 728 break; 729 case FLOAT128_LT_QUIET: 730 test_ab_float128_z_flag( slow_float128_lt_quiet, float128_lt_quiet ); 731 break; 732#endif 733 } 734 if ( ( errorStop && anyErrors ) || stop ) exitWithStatus(); 735 736} 737 738static void 739 testFunction( 740 uint8 functionCode, 741 int8 roundingPrecisionIn, 742 int8 roundingModeIn, 743 int8 tininessModeIn 744 ) 745{ 746 int8 roundingPrecision, roundingMode, tininessMode; 747 748 roundingPrecision = 32; 749 for (;;) { 750 if ( ! functions[ functionCode ].roundingPrecision ) { 751 roundingPrecision = 0; 752 } 753 else if ( roundingPrecisionIn ) { 754 roundingPrecision = roundingPrecisionIn; 755 } 756 for ( roundingMode = 1; 757 roundingMode < NUM_ROUNDINGMODES; 758 ++roundingMode 759 ) { 760 if ( ! functions[ functionCode ].roundingMode ) { 761 roundingMode = 0; 762 } 763 else if ( roundingModeIn ) { 764 roundingMode = roundingModeIn; 765 } 766 for ( tininessMode = 1; 767 tininessMode < NUM_TININESSMODES; 768 ++tininessMode 769 ) { 770 if ( ( roundingPrecision == 32 ) 771 || ( roundingPrecision == 64 ) ) { 772 if ( ! functions[ functionCode ] 773 .tininessModeAtReducedPrecision 774 ) { 775 tininessMode = 0; 776 } 777 else if ( tininessModeIn ) { 778 tininessMode = tininessModeIn; 779 } 780 } 781 else { 782 if ( ! functions[ functionCode ].tininessMode ) { 783 tininessMode = 0; 784 } 785 else if ( tininessModeIn ) { 786 tininessMode = tininessModeIn; 787 } 788 } 789 testFunctionVariety( 790 functionCode, roundingPrecision, roundingMode, tininessMode 791 ); 792 if ( tininessModeIn || ! tininessMode ) break; 793 } 794 if ( roundingModeIn || ! roundingMode ) break; 795 } 796 if ( roundingPrecisionIn || ! roundingPrecision ) break; 797 if ( roundingPrecision == 80 ) { 798 break; 799 } 800 else if ( roundingPrecision == 64 ) { 801 roundingPrecision = 80; 802 } 803 else if ( roundingPrecision == 32 ) { 804 roundingPrecision = 64; 805 } 806 } 807 808} 809 810main( int argc, char **argv ) 811{ 812 char *argPtr; 813 flag functionArgument; 814 uint8 functionCode; 815 int8 operands, roundingPrecision, roundingMode, tininessMode; 816 817 fail_programName = "testsoftfloat"; 818 if ( argc <= 1 ) goto writeHelpMessage; 819 testCases_setLevel( 1 ); 820 trueName = "true"; 821 testName = "soft"; 822 errorStop = FALSE; 823 forever = FALSE; 824 maxErrorCount = 20; 825 trueFlagsPtr = &slow_float_exception_flags; 826 testFlagsFunctionPtr = clearFlags; 827 functionArgument = FALSE; 828 functionCode = 0; 829 operands = 0; 830 roundingPrecision = 0; 831 roundingMode = 0; 832 tininessMode = 0; 833 --argc; 834 ++argv; 835 while ( argc && ( argPtr = argv[ 0 ] ) ) { 836 if ( argPtr[ 0 ] == '-' ) ++argPtr; 837 if ( strcmp( argPtr, "help" ) == 0 ) { 838 writeHelpMessage: 839 fputs( 840"testsoftfloat [<option>...] <function>\n" 841" <option>: (* is default)\n" 842" -help --Write this message and exit.\n" 843" -level <num> --Testing level <num> (1 or 2).\n" 844" * -level 1\n" 845" -errors <num> --Stop each function test after <num> errors.\n" 846" * -errors 20\n" 847" -errorstop --Exit after first function with any error.\n" 848" -forever --Test one function repeatedly (implies `-level 2').\n" 849#ifdef FLOATX80 850" -precision32 --Only test rounding precision equivalent to float32.\n" 851" -precision64 --Only test rounding precision equivalent to float64.\n" 852" -precision80 --Only test maximum rounding precision.\n" 853#endif 854" -nearesteven --Only test rounding to nearest/even.\n" 855" -tozero --Only test rounding to zero.\n" 856" -down --Only test rounding down.\n" 857" -up --Only test rounding up.\n" 858" -tininessbefore --Only test underflow tininess before rounding.\n" 859" -tininessafter --Only test underflow tininess after rounding.\n" 860" <function>:\n" 861" int32_to_<float> <float>_add <float>_eq\n" 862" <float>_to_int32 <float>_sub <float>_le\n" 863" <float>_to_int32_round_to_zero <float>_mul <float>_lt\n" 864#ifdef BITS64 865" int64_to_<float> <float>_div <float>_eq_signaling\n" 866" <float>_to_int64 <float>_rem <float>_le_quiet\n" 867" <float>_to_int64_round_to_zero <float>_lt_quiet\n" 868" <float>_to_<float>\n" 869" <float>_round_to_int\n" 870" <float>_sqrt\n" 871#else 872" <float>_to_<float> <float>_div <float>_eq_signaling\n" 873" <float>_round_to_int <float>_rem <float>_le_quiet\n" 874" <float>_sqrt <float>_lt_quiet\n" 875#endif 876" -all1 --All 1-operand functions.\n" 877" -all2 --All 2-operand functions.\n" 878" -all --All functions.\n" 879" <float>:\n" 880" float32 --Single precision.\n" 881" float64 --Double precision.\n" 882#ifdef FLOATX80 883" floatx80 --Extended double precision.\n" 884#endif 885#ifdef FLOAT128 886" float128 --Quadruple precision.\n" 887#endif 888 , 889 stdout 890 ); 891 return EXIT_SUCCESS; 892 } 893 else if ( strcmp( argPtr, "level" ) == 0 ) { 894 if ( argc < 2 ) goto optionError; 895 testCases_setLevel( atoi( argv[ 1 ] ) ); 896 --argc; 897 ++argv; 898 } 899 else if ( strcmp( argPtr, "level1" ) == 0 ) { 900 testCases_setLevel( 1 ); 901 } 902 else if ( strcmp( argPtr, "level2" ) == 0 ) { 903 testCases_setLevel( 2 ); 904 } 905 else if ( strcmp( argPtr, "errors" ) == 0 ) { 906 if ( argc < 2 ) { 907 optionError: 908 fail( "`%s' option requires numeric argument", argv[ 0 ] ); 909 } 910 maxErrorCount = atoi( argv[ 1 ] ); 911 --argc; 912 ++argv; 913 } 914 else if ( strcmp( argPtr, "errorstop" ) == 0 ) { 915 errorStop = TRUE; 916 } 917 else if ( strcmp( argPtr, "forever" ) == 0 ) { 918 testCases_setLevel( 2 ); 919 forever = TRUE; 920 } 921#ifdef FLOATX80 922 else if ( strcmp( argPtr, "precision32" ) == 0 ) { 923 roundingPrecision = 32; 924 } 925 else if ( strcmp( argPtr, "precision64" ) == 0 ) { 926 roundingPrecision = 64; 927 } 928 else if ( strcmp( argPtr, "precision80" ) == 0 ) { 929 roundingPrecision = 80; 930 } 931#endif 932 else if ( ( strcmp( argPtr, "nearesteven" ) == 0 ) 933 || ( strcmp( argPtr, "nearest_even" ) == 0 ) ) { 934 roundingMode = ROUND_NEAREST_EVEN; 935 } 936 else if ( ( strcmp( argPtr, "tozero" ) == 0 ) 937 || ( strcmp( argPtr, "to_zero" ) == 0 ) ) { 938 roundingMode = ROUND_TO_ZERO; 939 } 940 else if ( strcmp( argPtr, "down" ) == 0 ) { 941 roundingMode = ROUND_DOWN; 942 } 943 else if ( strcmp( argPtr, "up" ) == 0 ) { 944 roundingMode = ROUND_UP; 945 } 946 else if ( strcmp( argPtr, "tininessbefore" ) == 0 ) { 947 tininessMode = TININESS_BEFORE_ROUNDING; 948 } 949 else if ( strcmp( argPtr, "tininessafter" ) == 0 ) { 950 tininessMode = TININESS_AFTER_ROUNDING; 951 } 952 else if ( strcmp( argPtr, "all1" ) == 0 ) { 953 functionArgument = TRUE; 954 functionCode = 0; 955 operands = 1; 956 } 957 else if ( strcmp( argPtr, "all2" ) == 0 ) { 958 functionArgument = TRUE; 959 functionCode = 0; 960 operands = 2; 961 } 962 else if ( strcmp( argPtr, "all" ) == 0 ) { 963 functionArgument = TRUE; 964 functionCode = 0; 965 operands = 0; 966 } 967 else { 968 for ( functionCode = 1; 969 functionCode < NUM_FUNCTIONS; 970 ++functionCode 971 ) { 972 if ( strcmp( argPtr, functions[ functionCode ].name ) == 0 ) { 973 break; 974 } 975 } 976 if ( functionCode == NUM_FUNCTIONS ) { 977 fail( "Invalid option or function `%s'", argv[ 0 ] ); 978 } 979 functionArgument = TRUE; 980 } 981 --argc; 982 ++argv; 983 } 984 if ( ! functionArgument ) fail( "Function argument required" ); 985 (void) signal( SIGINT, catchSIGINT ); 986 (void) signal( SIGTERM, catchSIGINT ); 987 if ( functionCode ) { 988 if ( forever ) { 989 if ( ! roundingPrecision ) roundingPrecision = 80; 990 if ( ! roundingMode ) roundingMode = ROUND_NEAREST_EVEN; 991 } 992 testFunction( 993 functionCode, roundingPrecision, roundingMode, tininessMode ); 994 } 995 else { 996 if ( operands == 1 ) { 997 for ( functionCode = 1; 998 functionCode < NUM_FUNCTIONS; 999 ++functionCode 1000 ) { 1001 if ( functions[ functionCode ].numInputs == 1 ) { 1002 testFunction( 1003 functionCode, 1004 roundingPrecision, 1005 roundingMode, 1006 tininessMode 1007 ); 1008 } 1009 } 1010 } 1011 else if ( operands == 2 ) { 1012 for ( functionCode = 1; 1013 functionCode < NUM_FUNCTIONS; 1014 ++functionCode 1015 ) { 1016 if ( functions[ functionCode ].numInputs == 2 ) { 1017 testFunction( 1018 functionCode, 1019 roundingPrecision, 1020 roundingMode, 1021 tininessMode 1022 ); 1023 } 1024 } 1025 } 1026 else { 1027 for ( functionCode = 1; 1028 functionCode < NUM_FUNCTIONS; 1029 ++functionCode 1030 ) { 1031 testFunction( 1032 functionCode, roundingPrecision, roundingMode, tininessMode 1033 ); 1034 } 1035 } 1036 } 1037 exitWithStatus(); 1038 1039} 1040 1041