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