1 /* A C version of Kahan's Floating Point Test "Paranoia" 2 3 Thos Sumner, UCSF, Feb. 1985 4 David Gay, BTL, Jan. 1986 5 6 This is a rewrite from the Pascal version by 7 8 B. A. Wichmann, 18 Jan. 1985 9 10 (and does NOT exhibit good C programming style). 11 12 Adjusted to use Standard C headers 19 Jan. 1992 (dmg); 13 14 (C) Apr 19 1983 in BASIC version by: 15 Professor W. M. Kahan, 16 567 Evans Hall 17 Electrical Engineering & Computer Science Dept. 18 University of California 19 Berkeley, California 94720 20 USA 21 22 converted to Pascal by: 23 B. A. Wichmann 24 National Physical Laboratory 25 Teddington Middx 26 TW11 OLW 27 UK 28 29 converted to C by: 30 31 David M. Gay and Thos Sumner 32 AT&T Bell Labs Computer Center, Rm. U-76 33 600 Mountain Avenue University of California 34 Murray Hill, NJ 07974 San Francisco, CA 94143 35 USA USA 36 37 with simultaneous corrections to the Pascal source (reflected 38 in the Pascal source available over netlib). 39 [A couple of bug fixes from dgh = sun!dhough incorporated 31 July 1986.] 40 41 Reports of results on various systems from all the versions 42 of Paranoia are being collected by Richard Karpinski at the 43 same address as Thos Sumner. This includes sample outputs, 44 bug reports, and criticisms. 45 46 You may copy this program freely if you acknowledge its source. 47 Comments on the Pascal version to NPL, please. 48 49 The following is from the introductory commentary from Wichmann's work: 50 51 The BASIC program of Kahan is written in Microsoft BASIC using many 52 facilities which have no exact analogy in Pascal. The Pascal 53 version below cannot therefore be exactly the same. Rather than be 54 a minimal transcription of the BASIC program, the Pascal coding 55 follows the conventional style of block-structured languages. Hence 56 the Pascal version could be useful in producing versions in other 57 structured languages. 58 59 Rather than use identifiers of minimal length (which therefore have 60 little mnemonic significance), the Pascal version uses meaningful 61 identifiers as follows [Note: A few changes have been made for C]: 62 63 64 BASIC C BASIC C BASIC C 65 66 A J S StickyBit 67 A1 AInverse J0 NoErrors T 68 B Radix [Failure] T0 Underflow 69 B1 BInverse J1 NoErrors T2 ThirtyTwo 70 B2 RadixD2 [SeriousDefect] T5 OneAndHalf 71 B9 BMinusU2 J2 NoErrors T7 TwentySeven 72 C [Defect] T8 TwoForty 73 C1 CInverse J3 NoErrors U OneUlp 74 D [Flaw] U0 UnderflowThreshold 75 D4 FourD K PageNo U1 76 E0 L Milestone U2 77 E1 M V 78 E2 Exp2 N V0 79 E3 N1 V8 80 E5 MinSqEr O Zero V9 81 E6 SqEr O1 One W 82 E7 MaxSqEr O2 Two X 83 E8 O3 Three X1 84 E9 O4 Four X8 85 F1 MinusOne O5 Five X9 Random1 86 F2 Half O8 Eight Y 87 F3 Third O9 Nine Y1 88 F6 P Precision Y2 89 F9 Q Y9 Random2 90 G1 GMult Q8 Z 91 G2 GDiv Q9 Z0 PseudoZero 92 G3 GAddSub R Z1 93 H R1 RMult Z2 94 H1 HInverse R2 RDiv Z9 95 I R3 RAddSub 96 IO NoTrials R4 RSqrt 97 I3 IEEE R9 Random9 98 99 SqRWrng 100 101 All the variables in BASIC are true variables and in consequence, 102 the program is more difficult to follow since the "constants" must 103 be determined (the glossary is very helpful). The Pascal version 104 uses Real constants, but checks are added to ensure that the values 105 are correctly converted by the compiler. 106 107 The major textual change to the Pascal version apart from the 108 identifiersis that named procedures are used, inserting parameters 109 wherehelpful. New procedures are also introduced. The 110 correspondence is as follows: 111 112 113 BASIC Pascal 114 lines 115 116 90- 140 Pause 117 170- 250 Instructions 118 380- 460 Heading 119 480- 670 Characteristics 120 690- 870 History 121 2940-2950 Random 122 3710-3740 NewD 123 4040-4080 DoesYequalX 124 4090-4110 PrintIfNPositive 125 4640-4850 TestPartialUnderflow 126 127 */ 128 129 /* This version of paranoia has been modified to work with GCC's internal 130 software floating point emulation library, as a sanity check of same. 131 132 I'm doing this in C++ so that I can do operator overloading and not 133 have to modify so damned much of the existing code. */ 134 135 extern "C" { 136 #include <stdio.h> 137 #include <stddef.h> 138 #include <limits.h> 139 #include <string.h> 140 #include <stdlib.h> 141 #include <math.h> 142 #include <unistd.h> 143 #include <float.h> 144 145 /* This part is made all the more awful because many gcc headers are 146 not prepared at all to be parsed as C++. The biggest stickler 147 here is const structure members. So we include exactly the pieces 148 that we need. */ 149 150 #define GTY(x) 151 152 #include "ansidecl.h" 153 #include "auto-host.h" 154 #include "hwint.h" 155 156 #undef EXTRA_MODES_FILE 157 158 struct rtx_def; 159 typedef struct rtx_def *rtx; 160 struct rtvec_def; 161 typedef struct rtvec_def *rtvec; 162 union tree_node; 163 typedef union tree_node *tree; 164 165 #define DEFTREECODE(SYM, STRING, TYPE, NARGS) SYM, 166 enum tree_code { 167 #include "tree.def" 168 LAST_AND_UNUSED_TREE_CODE 169 }; 170 #undef DEFTREECODE 171 172 #define ENUM_BITFIELD(X) enum X 173 #define class klass 174 175 #include "real.h" 176 177 #undef class 178 } 179 180 /* We never produce signals from the library. Thus setjmp need do nothing. */ 181 #undef setjmp 182 #define setjmp(x) (0) 183 184 static bool verbose = false; 185 static int verbose_index = 0; 186 187 /* ====================================================================== */ 188 /* The implementation of the abstract floating point class based on gcc's 189 real.c. I.e. the object of this excersize. Templated so that we can 190 all fp sizes. */ 191 192 class real_c_float 193 { 194 public: 195 static const enum machine_mode MODE = SFmode; 196 197 private: 198 static const int external_max = 128 / 32; 199 static const int internal_max 200 = (sizeof (REAL_VALUE_TYPE) + sizeof (long) + 1) / sizeof (long); 201 long image[external_max < internal_max ? internal_max : external_max]; 202 203 void from_long(long); 204 void from_str(const char *); 205 void binop(int code, const real_c_float&); 206 void unop(int code); 207 bool cmp(int code, const real_c_float&) const; 208 209 public: 210 real_c_float() 211 { } 212 real_c_float(long l) 213 { from_long(l); } 214 real_c_float(const char *s) 215 { from_str(s); } 216 real_c_float(const real_c_float &b) 217 { memcpy(image, b.image, sizeof(image)); } 218 219 const real_c_float& operator= (long l) 220 { from_long(l); return *this; } 221 const real_c_float& operator= (const char *s) 222 { from_str(s); return *this; } 223 const real_c_float& operator= (const real_c_float &b) 224 { memcpy(image, b.image, sizeof(image)); return *this; } 225 226 const real_c_float& operator+= (const real_c_float &b) 227 { binop(PLUS_EXPR, b); return *this; } 228 const real_c_float& operator-= (const real_c_float &b) 229 { binop(MINUS_EXPR, b); return *this; } 230 const real_c_float& operator*= (const real_c_float &b) 231 { binop(MULT_EXPR, b); return *this; } 232 const real_c_float& operator/= (const real_c_float &b) 233 { binop(RDIV_EXPR, b); return *this; } 234 235 real_c_float operator- () const 236 { real_c_float r(*this); r.unop(NEGATE_EXPR); return r; } 237 real_c_float abs () const 238 { real_c_float r(*this); r.unop(ABS_EXPR); return r; } 239 240 bool operator < (const real_c_float &b) const { return cmp(LT_EXPR, b); } 241 bool operator <= (const real_c_float &b) const { return cmp(LE_EXPR, b); } 242 bool operator == (const real_c_float &b) const { return cmp(EQ_EXPR, b); } 243 bool operator != (const real_c_float &b) const { return cmp(NE_EXPR, b); } 244 bool operator >= (const real_c_float &b) const { return cmp(GE_EXPR, b); } 245 bool operator > (const real_c_float &b) const { return cmp(GT_EXPR, b); } 246 247 const char * str () const; 248 const char * hex () const; 249 long integer () const; 250 int exp () const; 251 void ldexp (int); 252 }; 253 254 void 255 real_c_float::from_long (long l) 256 { 257 REAL_VALUE_TYPE f; 258 259 real_from_integer (&f, MODE, l, l < 0 ? -1 : 0, 0); 260 real_to_target (image, &f, MODE); 261 } 262 263 void 264 real_c_float::from_str (const char *s) 265 { 266 REAL_VALUE_TYPE f; 267 const char *p = s; 268 269 if (*p == '-' || *p == '+') 270 p++; 271 if (strcasecmp(p, "inf") == 0) 272 { 273 real_inf (&f); 274 if (*s == '-') 275 real_arithmetic (&f, NEGATE_EXPR, &f, NULL); 276 } 277 else if (strcasecmp(p, "nan") == 0) 278 real_nan (&f, "", 1, MODE); 279 else 280 real_from_string (&f, s); 281 282 real_to_target (image, &f, MODE); 283 } 284 285 void 286 real_c_float::binop (int code, const real_c_float &b) 287 { 288 REAL_VALUE_TYPE ai, bi, ri; 289 290 real_from_target (&ai, image, MODE); 291 real_from_target (&bi, b.image, MODE); 292 real_arithmetic (&ri, code, &ai, &bi); 293 real_to_target (image, &ri, MODE); 294 295 if (verbose) 296 { 297 char ab[64], bb[64], rb[64]; 298 const real_format *fmt = real_format_for_mode[MODE - QFmode]; 299 const int digits = (fmt->p * fmt->log2_b + 3) / 4; 300 char symbol_for_code; 301 302 real_from_target (&ri, image, MODE); 303 real_to_hexadecimal (ab, &ai, sizeof(ab), digits, 0); 304 real_to_hexadecimal (bb, &bi, sizeof(bb), digits, 0); 305 real_to_hexadecimal (rb, &ri, sizeof(rb), digits, 0); 306 307 switch (code) 308 { 309 case PLUS_EXPR: 310 symbol_for_code = '+'; 311 break; 312 case MINUS_EXPR: 313 symbol_for_code = '-'; 314 break; 315 case MULT_EXPR: 316 symbol_for_code = '*'; 317 break; 318 case RDIV_EXPR: 319 symbol_for_code = '/'; 320 break; 321 default: 322 abort (); 323 } 324 325 fprintf (stderr, "%6d: %s %c %s = %s\n", verbose_index++, 326 ab, symbol_for_code, bb, rb); 327 } 328 } 329 330 void 331 real_c_float::unop (int code) 332 { 333 REAL_VALUE_TYPE ai, ri; 334 335 real_from_target (&ai, image, MODE); 336 real_arithmetic (&ri, code, &ai, NULL); 337 real_to_target (image, &ri, MODE); 338 339 if (verbose) 340 { 341 char ab[64], rb[64]; 342 const real_format *fmt = real_format_for_mode[MODE - QFmode]; 343 const int digits = (fmt->p * fmt->log2_b + 3) / 4; 344 const char *symbol_for_code; 345 346 real_from_target (&ri, image, MODE); 347 real_to_hexadecimal (ab, &ai, sizeof(ab), digits, 0); 348 real_to_hexadecimal (rb, &ri, sizeof(rb), digits, 0); 349 350 switch (code) 351 { 352 case NEGATE_EXPR: 353 symbol_for_code = "-"; 354 break; 355 case ABS_EXPR: 356 symbol_for_code = "abs "; 357 break; 358 default: 359 abort (); 360 } 361 362 fprintf (stderr, "%6d: %s%s = %s\n", verbose_index++, 363 symbol_for_code, ab, rb); 364 } 365 } 366 367 bool 368 real_c_float::cmp (int code, const real_c_float &b) const 369 { 370 REAL_VALUE_TYPE ai, bi; 371 bool ret; 372 373 real_from_target (&ai, image, MODE); 374 real_from_target (&bi, b.image, MODE); 375 ret = real_compare (code, &ai, &bi); 376 377 if (verbose) 378 { 379 char ab[64], bb[64]; 380 const real_format *fmt = real_format_for_mode[MODE - QFmode]; 381 const int digits = (fmt->p * fmt->log2_b + 3) / 4; 382 const char *symbol_for_code; 383 384 real_to_hexadecimal (ab, &ai, sizeof(ab), digits, 0); 385 real_to_hexadecimal (bb, &bi, sizeof(bb), digits, 0); 386 387 switch (code) 388 { 389 case LT_EXPR: 390 symbol_for_code = "<"; 391 break; 392 case LE_EXPR: 393 symbol_for_code = "<="; 394 break; 395 case EQ_EXPR: 396 symbol_for_code = "=="; 397 break; 398 case NE_EXPR: 399 symbol_for_code = "!="; 400 break; 401 case GE_EXPR: 402 symbol_for_code = ">="; 403 break; 404 case GT_EXPR: 405 symbol_for_code = ">"; 406 break; 407 default: 408 abort (); 409 } 410 411 fprintf (stderr, "%6d: %s %s %s = %s\n", verbose_index++, 412 ab, symbol_for_code, bb, (ret ? "true" : "false")); 413 } 414 415 return ret; 416 } 417 418 const char * 419 real_c_float::str() const 420 { 421 REAL_VALUE_TYPE f; 422 const real_format *fmt = real_format_for_mode[MODE - QFmode]; 423 const int digits = int(fmt->p * fmt->log2_b * .30102999566398119521 + 1); 424 425 real_from_target (&f, image, MODE); 426 char *buf = new char[digits + 10]; 427 real_to_decimal (buf, &f, digits+10, digits, 0); 428 429 return buf; 430 } 431 432 const char * 433 real_c_float::hex() const 434 { 435 REAL_VALUE_TYPE f; 436 const real_format *fmt = real_format_for_mode[MODE - QFmode]; 437 const int digits = (fmt->p * fmt->log2_b + 3) / 4; 438 439 real_from_target (&f, image, MODE); 440 char *buf = new char[digits + 10]; 441 real_to_hexadecimal (buf, &f, digits+10, digits, 0); 442 443 return buf; 444 } 445 446 long 447 real_c_float::integer() const 448 { 449 REAL_VALUE_TYPE f; 450 real_from_target (&f, image, MODE); 451 return real_to_integer (&f); 452 } 453 454 int 455 real_c_float::exp() const 456 { 457 REAL_VALUE_TYPE f; 458 real_from_target (&f, image, MODE); 459 return real_exponent (&f); 460 } 461 462 void 463 real_c_float::ldexp (int exp) 464 { 465 REAL_VALUE_TYPE ai; 466 467 real_from_target (&ai, image, MODE); 468 real_ldexp (&ai, &ai, exp); 469 real_to_target (image, &ai, MODE); 470 } 471 472 /* ====================================================================== */ 473 /* An implementation of the abstract floating point class that uses native 474 arithmetic. Exists for reference and debugging. */ 475 476 template<typename T> 477 class native_float 478 { 479 private: 480 // Force intermediate results back to memory. 481 volatile T image; 482 483 static T from_str (const char *); 484 static T do_abs (T); 485 static T verbose_binop (T, char, T, T); 486 static T verbose_unop (const char *, T, T); 487 static bool verbose_cmp (T, const char *, T, bool); 488 489 public: 490 native_float() 491 { } 492 native_float(long l) 493 { image = l; } 494 native_float(const char *s) 495 { image = from_str(s); } 496 native_float(const native_float &b) 497 { image = b.image; } 498 499 const native_float& operator= (long l) 500 { image = l; return *this; } 501 const native_float& operator= (const char *s) 502 { image = from_str(s); return *this; } 503 const native_float& operator= (const native_float &b) 504 { image = b.image; return *this; } 505 506 const native_float& operator+= (const native_float &b) 507 { 508 image = verbose_binop(image, '+', b.image, image + b.image); 509 return *this; 510 } 511 const native_float& operator-= (const native_float &b) 512 { 513 image = verbose_binop(image, '-', b.image, image - b.image); 514 return *this; 515 } 516 const native_float& operator*= (const native_float &b) 517 { 518 image = verbose_binop(image, '*', b.image, image * b.image); 519 return *this; 520 } 521 const native_float& operator/= (const native_float &b) 522 { 523 image = verbose_binop(image, '/', b.image, image / b.image); 524 return *this; 525 } 526 527 native_float operator- () const 528 { 529 native_float r; 530 r.image = verbose_unop("-", image, -image); 531 return r; 532 } 533 native_float abs () const 534 { 535 native_float r; 536 r.image = verbose_unop("abs ", image, do_abs(image)); 537 return r; 538 } 539 540 bool operator < (const native_float &b) const 541 { return verbose_cmp(image, "<", b.image, image < b.image); } 542 bool operator <= (const native_float &b) const 543 { return verbose_cmp(image, "<=", b.image, image <= b.image); } 544 bool operator == (const native_float &b) const 545 { return verbose_cmp(image, "==", b.image, image == b.image); } 546 bool operator != (const native_float &b) const 547 { return verbose_cmp(image, "!=", b.image, image != b.image); } 548 bool operator >= (const native_float &b) const 549 { return verbose_cmp(image, ">=", b.image, image >= b.image); } 550 bool operator > (const native_float &b) const 551 { return verbose_cmp(image, ">", b.image, image > b.image); } 552 553 const char * str () const; 554 const char * hex () const; 555 long integer () const 556 { return long(image); } 557 int exp () const; 558 void ldexp (int); 559 }; 560 561 template<typename T> 562 inline T 563 native_float<T>::from_str (const char *s) 564 { 565 return strtold (s, NULL); 566 } 567 568 template<> 569 inline float 570 native_float<float>::from_str (const char *s) 571 { 572 return strtof (s, NULL); 573 } 574 575 template<> 576 inline double 577 native_float<double>::from_str (const char *s) 578 { 579 return strtod (s, NULL); 580 } 581 582 template<typename T> 583 inline T 584 native_float<T>::do_abs (T image) 585 { 586 return fabsl (image); 587 } 588 589 template<> 590 inline float 591 native_float<float>::do_abs (float image) 592 { 593 return fabsf (image); 594 } 595 596 template<> 597 inline double 598 native_float<double>::do_abs (double image) 599 { 600 return fabs (image); 601 } 602 603 template<typename T> 604 T 605 native_float<T>::verbose_binop (T a, char symbol, T b, T r) 606 { 607 if (verbose) 608 { 609 const int digits = int(sizeof(T) * CHAR_BIT / 4) - 1; 610 #ifdef NO_LONG_DOUBLE 611 fprintf (stderr, "%6d: %.*a %c %.*a = %.*a\n", verbose_index++, 612 digits, (double)a, symbol, 613 digits, (double)b, digits, (double)r); 614 #else 615 fprintf (stderr, "%6d: %.*La %c %.*La = %.*La\n", verbose_index++, 616 digits, (long double)a, symbol, 617 digits, (long double)b, digits, (long double)r); 618 #endif 619 } 620 return r; 621 } 622 623 template<typename T> 624 T 625 native_float<T>::verbose_unop (const char *symbol, T a, T r) 626 { 627 if (verbose) 628 { 629 const int digits = int(sizeof(T) * CHAR_BIT / 4) - 1; 630 #ifdef NO_LONG_DOUBLE 631 fprintf (stderr, "%6d: %s%.*a = %.*a\n", verbose_index++, 632 symbol, digits, (double)a, digits, (double)r); 633 #else 634 fprintf (stderr, "%6d: %s%.*La = %.*La\n", verbose_index++, 635 symbol, digits, (long double)a, digits, (long double)r); 636 #endif 637 } 638 return r; 639 } 640 641 template<typename T> 642 bool 643 native_float<T>::verbose_cmp (T a, const char *symbol, T b, bool r) 644 { 645 if (verbose) 646 { 647 const int digits = int(sizeof(T) * CHAR_BIT / 4) - 1; 648 #ifndef NO_LONG_DOUBLE 649 fprintf (stderr, "%6d: %.*a %s %.*a = %s\n", verbose_index++, 650 digits, (double)a, symbol, 651 digits, (double)b, (r ? "true" : "false")); 652 #else 653 fprintf (stderr, "%6d: %.*La %s %.*La = %s\n", verbose_index++, 654 digits, (long double)a, symbol, 655 digits, (long double)b, (r ? "true" : "false")); 656 #endif 657 } 658 return r; 659 } 660 661 template<typename T> 662 const char * 663 native_float<T>::str() const 664 { 665 char *buf = new char[50]; 666 const int digits = int(sizeof(T) * CHAR_BIT * .30102999566398119521 + 1); 667 #ifndef NO_LONG_DOUBLE 668 sprintf (buf, "%.*e", digits - 1, (double) image); 669 #else 670 sprintf (buf, "%.*Le", digits - 1, (long double) image); 671 #endif 672 return buf; 673 } 674 675 template<typename T> 676 const char * 677 native_float<T>::hex() const 678 { 679 char *buf = new char[50]; 680 const int digits = int(sizeof(T) * CHAR_BIT / 4); 681 #ifndef NO_LONG_DOUBLE 682 sprintf (buf, "%.*a", digits - 1, (double) image); 683 #else 684 sprintf (buf, "%.*La", digits - 1, (long double) image); 685 #endif 686 return buf; 687 } 688 689 template<typename T> 690 int 691 native_float<T>::exp() const 692 { 693 int e; 694 frexp (image, &e); 695 return e; 696 } 697 698 template<typename T> 699 void 700 native_float<T>::ldexp (int exp) 701 { 702 image = ldexpl (image, exp); 703 } 704 705 template<> 706 void 707 native_float<float>::ldexp (int exp) 708 { 709 image = ldexpf (image, exp); 710 } 711 712 template<> 713 void 714 native_float<double>::ldexp (int exp) 715 { 716 image = ::ldexp (image, exp); 717 } 718 719 /* ====================================================================== */ 720 /* Some libm routines that Paranoia expects to be available. */ 721 722 template<typename FLOAT> 723 inline FLOAT 724 FABS (const FLOAT &f) 725 { 726 return f.abs(); 727 } 728 729 template<typename FLOAT, typename RHS> 730 inline FLOAT 731 operator+ (const FLOAT &a, const RHS &b) 732 { 733 return FLOAT(a) += FLOAT(b); 734 } 735 736 template<typename FLOAT, typename RHS> 737 inline FLOAT 738 operator- (const FLOAT &a, const RHS &b) 739 { 740 return FLOAT(a) -= FLOAT(b); 741 } 742 743 template<typename FLOAT, typename RHS> 744 inline FLOAT 745 operator* (const FLOAT &a, const RHS &b) 746 { 747 return FLOAT(a) *= FLOAT(b); 748 } 749 750 template<typename FLOAT, typename RHS> 751 inline FLOAT 752 operator/ (const FLOAT &a, const RHS &b) 753 { 754 return FLOAT(a) /= FLOAT(b); 755 } 756 757 template<typename FLOAT> 758 FLOAT 759 FLOOR (const FLOAT &f) 760 { 761 /* ??? This is only correct when F is representable as an integer. */ 762 long i = f.integer(); 763 FLOAT r; 764 765 r = i; 766 if (i < 0 && f != r) 767 r = i - 1; 768 769 return r; 770 } 771 772 template<typename FLOAT> 773 FLOAT 774 SQRT (const FLOAT &f) 775 { 776 #if 0 777 FLOAT zero = long(0); 778 FLOAT two = 2; 779 FLOAT one = 1; 780 FLOAT diff, diff2; 781 FLOAT z, t; 782 783 if (f == zero) 784 return zero; 785 if (f < zero) 786 return zero / zero; 787 if (f == one) 788 return f; 789 790 z = f; 791 z.ldexp (-f.exp() / 2); 792 793 diff2 = FABS (z * z - f); 794 if (diff2 > zero) 795 while (1) 796 { 797 t = (f / (two * z)) + (z / two); 798 diff = FABS (t * t - f); 799 if (diff >= diff2) 800 break; 801 z = t; 802 diff2 = diff; 803 } 804 805 return z; 806 #elif defined(NO_LONG_DOUBLE) 807 double d; 808 char buf[64]; 809 810 d = strtod (f.hex(), NULL); 811 d = sqrt (d); 812 sprintf(buf, "%.35a", d); 813 814 return FLOAT(buf); 815 #else 816 long double ld; 817 char buf[64]; 818 819 ld = strtold (f.hex(), NULL); 820 ld = sqrtl (ld); 821 sprintf(buf, "%.35La", ld); 822 823 return FLOAT(buf); 824 #endif 825 } 826 827 template<typename FLOAT> 828 FLOAT 829 LOG (FLOAT x) 830 { 831 #if 0 832 FLOAT zero = long(0); 833 FLOAT one = 1; 834 835 if (x <= zero) 836 return zero / zero; 837 if (x == one) 838 return zero; 839 840 int exp = x.exp() - 1; 841 x.ldexp(-exp); 842 843 FLOAT xm1 = x - one; 844 FLOAT y = xm1; 845 long n = 2; 846 847 FLOAT sum = xm1; 848 while (1) 849 { 850 y *= xm1; 851 FLOAT term = y / FLOAT (n); 852 FLOAT next = sum + term; 853 if (next == sum) 854 break; 855 sum = next; 856 if (++n == 1000) 857 break; 858 } 859 860 if (exp) 861 sum += FLOAT (exp) * FLOAT(".69314718055994530941"); 862 863 return sum; 864 #elif defined (NO_LONG_DOUBLE) 865 double d; 866 char buf[64]; 867 868 d = strtod (x.hex(), NULL); 869 d = log (d); 870 sprintf(buf, "%.35a", d); 871 872 return FLOAT(buf); 873 #else 874 long double ld; 875 char buf[64]; 876 877 ld = strtold (x.hex(), NULL); 878 ld = logl (ld); 879 sprintf(buf, "%.35La", ld); 880 881 return FLOAT(buf); 882 #endif 883 } 884 885 template<typename FLOAT> 886 FLOAT 887 EXP (const FLOAT &x) 888 { 889 /* Cheat. */ 890 #ifdef NO_LONG_DOUBLE 891 double d; 892 char buf[64]; 893 894 d = strtod (x.hex(), NULL); 895 d = exp (d); 896 sprintf(buf, "%.35a", d); 897 898 return FLOAT(buf); 899 #else 900 long double ld; 901 char buf[64]; 902 903 ld = strtold (x.hex(), NULL); 904 ld = expl (ld); 905 sprintf(buf, "%.35La", ld); 906 907 return FLOAT(buf); 908 #endif 909 } 910 911 template<typename FLOAT> 912 FLOAT 913 POW (const FLOAT &base, const FLOAT &exp) 914 { 915 /* Cheat. */ 916 #ifdef NO_LONG_DOUBLE 917 double d1, d2; 918 char buf[64]; 919 920 d1 = strtod (base.hex(), NULL); 921 d2 = strtod (exp.hex(), NULL); 922 d1 = pow (d1, d2); 923 sprintf(buf, "%.35a", d1); 924 925 return FLOAT(buf); 926 #else 927 long double ld1, ld2; 928 char buf[64]; 929 930 ld1 = strtold (base.hex(), NULL); 931 ld2 = strtold (exp.hex(), NULL); 932 ld1 = powl (ld1, ld2); 933 sprintf(buf, "%.35La", ld1); 934 935 return FLOAT(buf); 936 #endif 937 } 938 939 /* ====================================================================== */ 940 /* Real Paranoia begins again here. We wrap the thing in a template so 941 that we can instantiate it for each floating point type we care for. */ 942 943 int NoTrials = 20; /*Number of tests for commutativity. */ 944 bool do_pause = false; 945 946 enum Guard { No, Yes }; 947 enum Rounding { Other, Rounded, Chopped }; 948 enum Class { Failure, Serious, Defect, Flaw }; 949 950 template<typename FLOAT> 951 struct Paranoia 952 { 953 FLOAT Radix, BInvrse, RadixD2, BMinusU2; 954 955 /* Small floating point constants. */ 956 FLOAT Zero; 957 FLOAT Half; 958 FLOAT One; 959 FLOAT Two; 960 FLOAT Three; 961 FLOAT Four; 962 FLOAT Five; 963 FLOAT Eight; 964 FLOAT Nine; 965 FLOAT TwentySeven; 966 FLOAT ThirtyTwo; 967 FLOAT TwoForty; 968 FLOAT MinusOne; 969 FLOAT OneAndHalf; 970 971 /* Declarations of Variables. */ 972 int Indx; 973 char ch[8]; 974 FLOAT AInvrse, A1; 975 FLOAT C, CInvrse; 976 FLOAT D, FourD; 977 FLOAT E0, E1, Exp2, E3, MinSqEr; 978 FLOAT SqEr, MaxSqEr, E9; 979 FLOAT Third; 980 FLOAT F6, F9; 981 FLOAT H, HInvrse; 982 int I; 983 FLOAT StickyBit, J; 984 FLOAT MyZero; 985 FLOAT Precision; 986 FLOAT Q, Q9; 987 FLOAT R, Random9; 988 FLOAT T, Underflow, S; 989 FLOAT OneUlp, UfThold, U1, U2; 990 FLOAT V, V0, V9; 991 FLOAT W; 992 FLOAT X, X1, X2, X8, Random1; 993 FLOAT Y, Y1, Y2, Random2; 994 FLOAT Z, PseudoZero, Z1, Z2, Z9; 995 int ErrCnt[4]; 996 int Milestone; 997 int PageNo; 998 int M, N, N1; 999 Guard GMult, GDiv, GAddSub; 1000 Rounding RMult, RDiv, RAddSub, RSqrt; 1001 int Break, Done, NotMonot, Monot, Anomaly, IEEE, SqRWrng, UfNGrad; 1002 1003 /* Computed constants. */ 1004 /*U1 gap below 1.0, i.e, 1.0-U1 is next number below 1.0 */ 1005 /*U2 gap above 1.0, i.e, 1.0+U2 is next number above 1.0 */ 1006 1007 int main (); 1008 1009 FLOAT Sign (FLOAT); 1010 FLOAT Random (); 1011 void Pause (); 1012 void BadCond (int, const char *); 1013 void SqXMinX (int); 1014 void TstCond (int, int, const char *); 1015 void notify (const char *); 1016 void IsYeqX (); 1017 void NewD (); 1018 void PrintIfNPositive (); 1019 void SR3750 (); 1020 void TstPtUf (); 1021 1022 // Pretend we're bss. 1023 Paranoia() { memset(this, 0, sizeof (*this)); } 1024 }; 1025 1026 template<typename FLOAT> 1027 int 1028 Paranoia<FLOAT>::main() 1029 { 1030 /* First two assignments use integer right-hand sides. */ 1031 Zero = long(0); 1032 One = long(1); 1033 Two = long(2); 1034 Three = long(3); 1035 Four = long(4); 1036 Five = long(5); 1037 Eight = long(8); 1038 Nine = long(9); 1039 TwentySeven = long(27); 1040 ThirtyTwo = long(32); 1041 TwoForty = long(240); 1042 MinusOne = long(-1); 1043 Half = "0x1p-1"; 1044 OneAndHalf = "0x3p-1"; 1045 ErrCnt[Failure] = 0; 1046 ErrCnt[Serious] = 0; 1047 ErrCnt[Defect] = 0; 1048 ErrCnt[Flaw] = 0; 1049 PageNo = 1; 1050 /*=============================================*/ 1051 Milestone = 7; 1052 /*=============================================*/ 1053 printf ("Program is now RUNNING tests on small integers:\n"); 1054 1055 TstCond (Failure, (Zero + Zero == Zero), "0+0 != 0"); 1056 TstCond (Failure, (One - One == Zero), "1-1 != 0"); 1057 TstCond (Failure, (One > Zero), "1 <= 0"); 1058 TstCond (Failure, (One + One == Two), "1+1 != 2"); 1059 1060 Z = -Zero; 1061 if (Z != Zero) 1062 { 1063 ErrCnt[Failure] = ErrCnt[Failure] + 1; 1064 printf ("Comparison alleges that -0.0 is Non-zero!\n"); 1065 U2 = "0.001"; 1066 Radix = 1; 1067 TstPtUf (); 1068 } 1069 1070 TstCond (Failure, (Three == Two + One), "3 != 2+1"); 1071 TstCond (Failure, (Four == Three + One), "4 != 3+1"); 1072 TstCond (Failure, (Four + Two * (-Two) == Zero), "4 + 2*(-2) != 0"); 1073 TstCond (Failure, (Four - Three - One == Zero), "4-3-1 != 0"); 1074 1075 TstCond (Failure, (MinusOne == (Zero - One)), "-1 != 0-1"); 1076 TstCond (Failure, (MinusOne + One == Zero), "-1+1 != 0"); 1077 TstCond (Failure, (One + MinusOne == Zero), "1+(-1) != 0"); 1078 TstCond (Failure, (MinusOne + FABS (One) == Zero), "-1+abs(1) != 0"); 1079 TstCond (Failure, (MinusOne + MinusOne * MinusOne == Zero), 1080 "-1+(-1)*(-1) != 0"); 1081 1082 TstCond (Failure, Half + MinusOne + Half == Zero, "1/2 + (-1) + 1/2 != 0"); 1083 1084 /*=============================================*/ 1085 Milestone = 10; 1086 /*=============================================*/ 1087 1088 TstCond (Failure, (Nine == Three * Three), "9 != 3*3"); 1089 TstCond (Failure, (TwentySeven == Nine * Three), "27 != 9*3"); 1090 TstCond (Failure, (Eight == Four + Four), "8 != 4+4"); 1091 TstCond (Failure, (ThirtyTwo == Eight * Four), "32 != 8*4"); 1092 TstCond (Failure, (ThirtyTwo - TwentySeven - Four - One == Zero), 1093 "32-27-4-1 != 0"); 1094 1095 TstCond (Failure, Five == Four + One, "5 != 4+1"); 1096 TstCond (Failure, TwoForty == Four * Five * Three * Four, "240 != 4*5*3*4"); 1097 TstCond (Failure, TwoForty / Three - Four * Four * Five == Zero, 1098 "240/3 - 4*4*5 != 0"); 1099 TstCond (Failure, TwoForty / Four - Five * Three * Four == Zero, 1100 "240/4 - 5*3*4 != 0"); 1101 TstCond (Failure, TwoForty / Five - Four * Three * Four == Zero, 1102 "240/5 - 4*3*4 != 0"); 1103 1104 if (ErrCnt[Failure] == 0) 1105 { 1106 printf ("-1, 0, 1/2, 1, 2, 3, 4, 5, 9, 27, 32 & 240 are O.K.\n"); 1107 printf ("\n"); 1108 } 1109 printf ("Searching for Radix and Precision.\n"); 1110 W = One; 1111 do 1112 { 1113 W = W + W; 1114 Y = W + One; 1115 Z = Y - W; 1116 Y = Z - One; 1117 } 1118 while (MinusOne + FABS (Y) < Zero); 1119 /*.. now W is just big enough that |((W+1)-W)-1| >= 1 ... */ 1120 Precision = Zero; 1121 Y = One; 1122 do 1123 { 1124 Radix = W + Y; 1125 Y = Y + Y; 1126 Radix = Radix - W; 1127 } 1128 while (Radix == Zero); 1129 if (Radix < Two) 1130 Radix = One; 1131 printf ("Radix = %s .\n", Radix.str()); 1132 if (Radix != One) 1133 { 1134 W = One; 1135 do 1136 { 1137 Precision = Precision + One; 1138 W = W * Radix; 1139 Y = W + One; 1140 } 1141 while ((Y - W) == One); 1142 } 1143 /*... now W == Radix^Precision is barely too big to satisfy (W+1)-W == 1 1144 ... */ 1145 U1 = One / W; 1146 U2 = Radix * U1; 1147 printf ("Closest relative separation found is U1 = %s .\n\n", U1.str()); 1148 printf ("Recalculating radix and precision\n "); 1149 1150 /*save old values */ 1151 E0 = Radix; 1152 E1 = U1; 1153 E9 = U2; 1154 E3 = Precision; 1155 1156 X = Four / Three; 1157 Third = X - One; 1158 F6 = Half - Third; 1159 X = F6 + F6; 1160 X = FABS (X - Third); 1161 if (X < U2) 1162 X = U2; 1163 1164 /*... now X = (unknown no.) ulps of 1+... */ 1165 do 1166 { 1167 U2 = X; 1168 Y = Half * U2 + ThirtyTwo * U2 * U2; 1169 Y = One + Y; 1170 X = Y - One; 1171 } 1172 while (!((U2 <= X) || (X <= Zero))); 1173 1174 /*... now U2 == 1 ulp of 1 + ... */ 1175 X = Two / Three; 1176 F6 = X - Half; 1177 Third = F6 + F6; 1178 X = Third - Half; 1179 X = FABS (X + F6); 1180 if (X < U1) 1181 X = U1; 1182 1183 /*... now X == (unknown no.) ulps of 1 -... */ 1184 do 1185 { 1186 U1 = X; 1187 Y = Half * U1 + ThirtyTwo * U1 * U1; 1188 Y = Half - Y; 1189 X = Half + Y; 1190 Y = Half - X; 1191 X = Half + Y; 1192 } 1193 while (!((U1 <= X) || (X <= Zero))); 1194 /*... now U1 == 1 ulp of 1 - ... */ 1195 if (U1 == E1) 1196 printf ("confirms closest relative separation U1 .\n"); 1197 else 1198 printf ("gets better closest relative separation U1 = %s .\n", U1.str()); 1199 W = One / U1; 1200 F9 = (Half - U1) + Half; 1201 1202 Radix = FLOOR (FLOAT ("0.01") + U2 / U1); 1203 if (Radix == E0) 1204 printf ("Radix confirmed.\n"); 1205 else 1206 printf ("MYSTERY: recalculated Radix = %s .\n", Radix.str()); 1207 TstCond (Defect, Radix <= Eight + Eight, 1208 "Radix is too big: roundoff problems"); 1209 TstCond (Flaw, (Radix == Two) || (Radix == 10) 1210 || (Radix == One), "Radix is not as good as 2 or 10"); 1211 /*=============================================*/ 1212 Milestone = 20; 1213 /*=============================================*/ 1214 TstCond (Failure, F9 - Half < Half, 1215 "(1-U1)-1/2 < 1/2 is FALSE, prog. fails?"); 1216 X = F9; 1217 I = 1; 1218 Y = X - Half; 1219 Z = Y - Half; 1220 TstCond (Failure, (X != One) 1221 || (Z == Zero), "Comparison is fuzzy,X=1 but X-1/2-1/2 != 0"); 1222 X = One + U2; 1223 I = 0; 1224 /*=============================================*/ 1225 Milestone = 25; 1226 /*=============================================*/ 1227 /*... BMinusU2 = nextafter(Radix, 0) */ 1228 BMinusU2 = Radix - One; 1229 BMinusU2 = (BMinusU2 - U2) + One; 1230 /* Purify Integers */ 1231 if (Radix != One) 1232 { 1233 X = -TwoForty * LOG (U1) / LOG (Radix); 1234 Y = FLOOR (Half + X); 1235 if (FABS (X - Y) * Four < One) 1236 X = Y; 1237 Precision = X / TwoForty; 1238 Y = FLOOR (Half + Precision); 1239 if (FABS (Precision - Y) * TwoForty < Half) 1240 Precision = Y; 1241 } 1242 if ((Precision != FLOOR (Precision)) || (Radix == One)) 1243 { 1244 printf ("Precision cannot be characterized by an Integer number\n"); 1245 printf 1246 ("of significant digits but, by itself, this is a minor flaw.\n"); 1247 } 1248 if (Radix == One) 1249 printf 1250 ("logarithmic encoding has precision characterized solely by U1.\n"); 1251 else 1252 printf ("The number of significant digits of the Radix is %s .\n", 1253 Precision.str()); 1254 TstCond (Serious, U2 * Nine * Nine * TwoForty < One, 1255 "Precision worse than 5 decimal figures "); 1256 /*=============================================*/ 1257 Milestone = 30; 1258 /*=============================================*/ 1259 /* Test for extra-precise subexpressions */ 1260 X = FABS (((Four / Three - One) - One / Four) * Three - One / Four); 1261 do 1262 { 1263 Z2 = X; 1264 X = (One + (Half * Z2 + ThirtyTwo * Z2 * Z2)) - One; 1265 } 1266 while (!((Z2 <= X) || (X <= Zero))); 1267 X = Y = Z = FABS ((Three / Four - Two / Three) * Three - One / Four); 1268 do 1269 { 1270 Z1 = Z; 1271 Z = (One / Two - ((One / Two - (Half * Z1 + ThirtyTwo * Z1 * Z1)) 1272 + One / Two)) + One / Two; 1273 } 1274 while (!((Z1 <= Z) || (Z <= Zero))); 1275 do 1276 { 1277 do 1278 { 1279 Y1 = Y; 1280 Y = 1281 (Half - ((Half - (Half * Y1 + ThirtyTwo * Y1 * Y1)) + Half)) + 1282 Half; 1283 } 1284 while (!((Y1 <= Y) || (Y <= Zero))); 1285 X1 = X; 1286 X = ((Half * X1 + ThirtyTwo * X1 * X1) - F9) + F9; 1287 } 1288 while (!((X1 <= X) || (X <= Zero))); 1289 if ((X1 != Y1) || (X1 != Z1)) 1290 { 1291 BadCond (Serious, "Disagreements among the values X1, Y1, Z1,\n"); 1292 printf ("respectively %s, %s, %s,\n", X1.str(), Y1.str(), Z1.str()); 1293 printf ("are symptoms of inconsistencies introduced\n"); 1294 printf ("by extra-precise evaluation of arithmetic subexpressions.\n"); 1295 notify ("Possibly some part of this"); 1296 if ((X1 == U1) || (Y1 == U1) || (Z1 == U1)) 1297 printf ("That feature is not tested further by this program.\n"); 1298 } 1299 else 1300 { 1301 if ((Z1 != U1) || (Z2 != U2)) 1302 { 1303 if ((Z1 >= U1) || (Z2 >= U2)) 1304 { 1305 BadCond (Failure, ""); 1306 notify ("Precision"); 1307 printf ("\tU1 = %s, Z1 - U1 = %s\n", U1.str(), (Z1 - U1).str()); 1308 printf ("\tU2 = %s, Z2 - U2 = %s\n", U2.str(), (Z2 - U2).str()); 1309 } 1310 else 1311 { 1312 if ((Z1 <= Zero) || (Z2 <= Zero)) 1313 { 1314 printf ("Because of unusual Radix = %s", Radix.str()); 1315 printf (", or exact rational arithmetic a result\n"); 1316 printf ("Z1 = %s, or Z2 = %s ", Z1.str(), Z2.str()); 1317 notify ("of an\nextra-precision"); 1318 } 1319 if (Z1 != Z2 || Z1 > Zero) 1320 { 1321 X = Z1 / U1; 1322 Y = Z2 / U2; 1323 if (Y > X) 1324 X = Y; 1325 Q = -LOG (X); 1326 printf ("Some subexpressions appear to be calculated " 1327 "extra precisely\n"); 1328 printf ("with about %s extra B-digits, i.e.\n", 1329 (Q / LOG (Radix)).str()); 1330 printf ("roughly %s extra significant decimals.\n", 1331 (Q / LOG (FLOAT (10))).str()); 1332 } 1333 printf 1334 ("That feature is not tested further by this program.\n"); 1335 } 1336 } 1337 } 1338 Pause (); 1339 /*=============================================*/ 1340 Milestone = 35; 1341 /*=============================================*/ 1342 if (Radix >= Two) 1343 { 1344 X = W / (Radix * Radix); 1345 Y = X + One; 1346 Z = Y - X; 1347 T = Z + U2; 1348 X = T - Z; 1349 TstCond (Failure, X == U2, 1350 "Subtraction is not normalized X=Y,X+Z != Y+Z!"); 1351 if (X == U2) 1352 printf ("Subtraction appears to be normalized, as it should be."); 1353 } 1354 printf ("\nChecking for guard digit in *, /, and -.\n"); 1355 Y = F9 * One; 1356 Z = One * F9; 1357 X = F9 - Half; 1358 Y = (Y - Half) - X; 1359 Z = (Z - Half) - X; 1360 X = One + U2; 1361 T = X * Radix; 1362 R = Radix * X; 1363 X = T - Radix; 1364 X = X - Radix * U2; 1365 T = R - Radix; 1366 T = T - Radix * U2; 1367 X = X * (Radix - One); 1368 T = T * (Radix - One); 1369 if ((X == Zero) && (Y == Zero) && (Z == Zero) && (T == Zero)) 1370 GMult = Yes; 1371 else 1372 { 1373 GMult = No; 1374 TstCond (Serious, false, "* lacks a Guard Digit, so 1*X != X"); 1375 } 1376 Z = Radix * U2; 1377 X = One + Z; 1378 Y = FABS ((X + Z) - X * X) - U2; 1379 X = One - U2; 1380 Z = FABS ((X - U2) - X * X) - U1; 1381 TstCond (Failure, (Y <= Zero) 1382 && (Z <= Zero), "* gets too many final digits wrong.\n"); 1383 Y = One - U2; 1384 X = One + U2; 1385 Z = One / Y; 1386 Y = Z - X; 1387 X = One / Three; 1388 Z = Three / Nine; 1389 X = X - Z; 1390 T = Nine / TwentySeven; 1391 Z = Z - T; 1392 TstCond (Defect, X == Zero && Y == Zero && Z == Zero, 1393 "Division lacks a Guard Digit, so error can exceed 1 ulp\n" 1394 "or 1/3 and 3/9 and 9/27 may disagree"); 1395 Y = F9 / One; 1396 X = F9 - Half; 1397 Y = (Y - Half) - X; 1398 X = One + U2; 1399 T = X / One; 1400 X = T - X; 1401 if ((X == Zero) && (Y == Zero) && (Z == Zero)) 1402 GDiv = Yes; 1403 else 1404 { 1405 GDiv = No; 1406 TstCond (Serious, false, "Division lacks a Guard Digit, so X/1 != X"); 1407 } 1408 X = One / (One + U2); 1409 Y = X - Half - Half; 1410 TstCond (Serious, Y < Zero, "Computed value of 1/1.000..1 >= 1"); 1411 X = One - U2; 1412 Y = One + Radix * U2; 1413 Z = X * Radix; 1414 T = Y * Radix; 1415 R = Z / Radix; 1416 StickyBit = T / Radix; 1417 X = R - X; 1418 Y = StickyBit - Y; 1419 TstCond (Failure, X == Zero && Y == Zero, 1420 "* and/or / gets too many last digits wrong"); 1421 Y = One - U1; 1422 X = One - F9; 1423 Y = One - Y; 1424 T = Radix - U2; 1425 Z = Radix - BMinusU2; 1426 T = Radix - T; 1427 if ((X == U1) && (Y == U1) && (Z == U2) && (T == U2)) 1428 GAddSub = Yes; 1429 else 1430 { 1431 GAddSub = No; 1432 TstCond (Serious, false, 1433 "- lacks Guard Digit, so cancellation is obscured"); 1434 } 1435 if (F9 != One && F9 - One >= Zero) 1436 { 1437 BadCond (Serious, "comparison alleges (1-U1) < 1 although\n"); 1438 printf (" subtraction yields (1-U1) - 1 = 0 , thereby vitiating\n"); 1439 printf (" such precautions against division by zero as\n"); 1440 printf (" ... if (X == 1.0) {.....} else {.../(X-1.0)...}\n"); 1441 } 1442 if (GMult == Yes && GDiv == Yes && GAddSub == Yes) 1443 printf 1444 (" *, /, and - appear to have guard digits, as they should.\n"); 1445 /*=============================================*/ 1446 Milestone = 40; 1447 /*=============================================*/ 1448 Pause (); 1449 printf ("Checking rounding on multiply, divide and add/subtract.\n"); 1450 RMult = Other; 1451 RDiv = Other; 1452 RAddSub = Other; 1453 RadixD2 = Radix / Two; 1454 A1 = Two; 1455 Done = false; 1456 do 1457 { 1458 AInvrse = Radix; 1459 do 1460 { 1461 X = AInvrse; 1462 AInvrse = AInvrse / A1; 1463 } 1464 while (!(FLOOR (AInvrse) != AInvrse)); 1465 Done = (X == One) || (A1 > Three); 1466 if (!Done) 1467 A1 = Nine + One; 1468 } 1469 while (!(Done)); 1470 if (X == One) 1471 A1 = Radix; 1472 AInvrse = One / A1; 1473 X = A1; 1474 Y = AInvrse; 1475 Done = false; 1476 do 1477 { 1478 Z = X * Y - Half; 1479 TstCond (Failure, Z == Half, "X * (1/X) differs from 1"); 1480 Done = X == Radix; 1481 X = Radix; 1482 Y = One / X; 1483 } 1484 while (!(Done)); 1485 Y2 = One + U2; 1486 Y1 = One - U2; 1487 X = OneAndHalf - U2; 1488 Y = OneAndHalf + U2; 1489 Z = (X - U2) * Y2; 1490 T = Y * Y1; 1491 Z = Z - X; 1492 T = T - X; 1493 X = X * Y2; 1494 Y = (Y + U2) * Y1; 1495 X = X - OneAndHalf; 1496 Y = Y - OneAndHalf; 1497 if ((X == Zero) && (Y == Zero) && (Z == Zero) && (T <= Zero)) 1498 { 1499 X = (OneAndHalf + U2) * Y2; 1500 Y = OneAndHalf - U2 - U2; 1501 Z = OneAndHalf + U2 + U2; 1502 T = (OneAndHalf - U2) * Y1; 1503 X = X - (Z + U2); 1504 StickyBit = Y * Y1; 1505 S = Z * Y2; 1506 T = T - Y; 1507 Y = (U2 - Y) + StickyBit; 1508 Z = S - (Z + U2 + U2); 1509 StickyBit = (Y2 + U2) * Y1; 1510 Y1 = Y2 * Y1; 1511 StickyBit = StickyBit - Y2; 1512 Y1 = Y1 - Half; 1513 if ((X == Zero) && (Y == Zero) && (Z == Zero) && (T == Zero) 1514 && (StickyBit == Zero) && (Y1 == Half)) 1515 { 1516 RMult = Rounded; 1517 printf ("Multiplication appears to round correctly.\n"); 1518 } 1519 else if ((X + U2 == Zero) && (Y < Zero) && (Z + U2 == Zero) 1520 && (T < Zero) && (StickyBit + U2 == Zero) && (Y1 < Half)) 1521 { 1522 RMult = Chopped; 1523 printf ("Multiplication appears to chop.\n"); 1524 } 1525 else 1526 printf ("* is neither chopped nor correctly rounded.\n"); 1527 if ((RMult == Rounded) && (GMult == No)) 1528 notify ("Multiplication"); 1529 } 1530 else 1531 printf ("* is neither chopped nor correctly rounded.\n"); 1532 /*=============================================*/ 1533 Milestone = 45; 1534 /*=============================================*/ 1535 Y2 = One + U2; 1536 Y1 = One - U2; 1537 Z = OneAndHalf + U2 + U2; 1538 X = Z / Y2; 1539 T = OneAndHalf - U2 - U2; 1540 Y = (T - U2) / Y1; 1541 Z = (Z + U2) / Y2; 1542 X = X - OneAndHalf; 1543 Y = Y - T; 1544 T = T / Y1; 1545 Z = Z - (OneAndHalf + U2); 1546 T = (U2 - OneAndHalf) + T; 1547 if (!((X > Zero) || (Y > Zero) || (Z > Zero) || (T > Zero))) 1548 { 1549 X = OneAndHalf / Y2; 1550 Y = OneAndHalf - U2; 1551 Z = OneAndHalf + U2; 1552 X = X - Y; 1553 T = OneAndHalf / Y1; 1554 Y = Y / Y1; 1555 T = T - (Z + U2); 1556 Y = Y - Z; 1557 Z = Z / Y2; 1558 Y1 = (Y2 + U2) / Y2; 1559 Z = Z - OneAndHalf; 1560 Y2 = Y1 - Y2; 1561 Y1 = (F9 - U1) / F9; 1562 if ((X == Zero) && (Y == Zero) && (Z == Zero) && (T == Zero) 1563 && (Y2 == Zero) && (Y2 == Zero) && (Y1 - Half == F9 - Half)) 1564 { 1565 RDiv = Rounded; 1566 printf ("Division appears to round correctly.\n"); 1567 if (GDiv == No) 1568 notify ("Division"); 1569 } 1570 else if ((X < Zero) && (Y < Zero) && (Z < Zero) && (T < Zero) 1571 && (Y2 < Zero) && (Y1 - Half < F9 - Half)) 1572 { 1573 RDiv = Chopped; 1574 printf ("Division appears to chop.\n"); 1575 } 1576 } 1577 if (RDiv == Other) 1578 printf ("/ is neither chopped nor correctly rounded.\n"); 1579 BInvrse = One / Radix; 1580 TstCond (Failure, (BInvrse * Radix - Half == Half), 1581 "Radix * ( 1 / Radix ) differs from 1"); 1582 /*=============================================*/ 1583 Milestone = 50; 1584 /*=============================================*/ 1585 TstCond (Failure, ((F9 + U1) - Half == Half) 1586 && ((BMinusU2 + U2) - One == Radix - One), 1587 "Incomplete carry-propagation in Addition"); 1588 X = One - U1 * U1; 1589 Y = One + U2 * (One - U2); 1590 Z = F9 - Half; 1591 X = (X - Half) - Z; 1592 Y = Y - One; 1593 if ((X == Zero) && (Y == Zero)) 1594 { 1595 RAddSub = Chopped; 1596 printf ("Add/Subtract appears to be chopped.\n"); 1597 } 1598 if (GAddSub == Yes) 1599 { 1600 X = (Half + U2) * U2; 1601 Y = (Half - U2) * U2; 1602 X = One + X; 1603 Y = One + Y; 1604 X = (One + U2) - X; 1605 Y = One - Y; 1606 if ((X == Zero) && (Y == Zero)) 1607 { 1608 X = (Half + U2) * U1; 1609 Y = (Half - U2) * U1; 1610 X = One - X; 1611 Y = One - Y; 1612 X = F9 - X; 1613 Y = One - Y; 1614 if ((X == Zero) && (Y == Zero)) 1615 { 1616 RAddSub = Rounded; 1617 printf ("Addition/Subtraction appears to round correctly.\n"); 1618 if (GAddSub == No) 1619 notify ("Add/Subtract"); 1620 } 1621 else 1622 printf ("Addition/Subtraction neither rounds nor chops.\n"); 1623 } 1624 else 1625 printf ("Addition/Subtraction neither rounds nor chops.\n"); 1626 } 1627 else 1628 printf ("Addition/Subtraction neither rounds nor chops.\n"); 1629 S = One; 1630 X = One + Half * (One + Half); 1631 Y = (One + U2) * Half; 1632 Z = X - Y; 1633 T = Y - X; 1634 StickyBit = Z + T; 1635 if (StickyBit != Zero) 1636 { 1637 S = Zero; 1638 BadCond (Flaw, "(X - Y) + (Y - X) is non zero!\n"); 1639 } 1640 StickyBit = Zero; 1641 if ((GMult == Yes) && (GDiv == Yes) && (GAddSub == Yes) 1642 && (RMult == Rounded) && (RDiv == Rounded) 1643 && (RAddSub == Rounded) && (FLOOR (RadixD2) == RadixD2)) 1644 { 1645 printf ("Checking for sticky bit.\n"); 1646 X = (Half + U1) * U2; 1647 Y = Half * U2; 1648 Z = One + Y; 1649 T = One + X; 1650 if ((Z - One <= Zero) && (T - One >= U2)) 1651 { 1652 Z = T + Y; 1653 Y = Z - X; 1654 if ((Z - T >= U2) && (Y - T == Zero)) 1655 { 1656 X = (Half + U1) * U1; 1657 Y = Half * U1; 1658 Z = One - Y; 1659 T = One - X; 1660 if ((Z - One == Zero) && (T - F9 == Zero)) 1661 { 1662 Z = (Half - U1) * U1; 1663 T = F9 - Z; 1664 Q = F9 - Y; 1665 if ((T - F9 == Zero) && (F9 - U1 - Q == Zero)) 1666 { 1667 Z = (One + U2) * OneAndHalf; 1668 T = (OneAndHalf + U2) - Z + U2; 1669 X = One + Half / Radix; 1670 Y = One + Radix * U2; 1671 Z = X * Y; 1672 if (T == Zero && X + Radix * U2 - Z == Zero) 1673 { 1674 if (Radix != Two) 1675 { 1676 X = Two + U2; 1677 Y = X / Two; 1678 if ((Y - One == Zero)) 1679 StickyBit = S; 1680 } 1681 else 1682 StickyBit = S; 1683 } 1684 } 1685 } 1686 } 1687 } 1688 } 1689 if (StickyBit == One) 1690 printf ("Sticky bit apparently used correctly.\n"); 1691 else 1692 printf ("Sticky bit used incorrectly or not at all.\n"); 1693 TstCond (Flaw, !(GMult == No || GDiv == No || GAddSub == No || 1694 RMult == Other || RDiv == Other || RAddSub == Other), 1695 "lack(s) of guard digits or failure(s) to correctly round or chop\n\ 1696 (noted above) count as one flaw in the final tally below"); 1697 /*=============================================*/ 1698 Milestone = 60; 1699 /*=============================================*/ 1700 printf ("\n"); 1701 printf ("Does Multiplication commute? "); 1702 printf ("Testing on %d random pairs.\n", NoTrials); 1703 Random9 = SQRT (FLOAT (3)); 1704 Random1 = Third; 1705 I = 1; 1706 do 1707 { 1708 X = Random (); 1709 Y = Random (); 1710 Z9 = Y * X; 1711 Z = X * Y; 1712 Z9 = Z - Z9; 1713 I = I + 1; 1714 } 1715 while (!((I > NoTrials) || (Z9 != Zero))); 1716 if (I == NoTrials) 1717 { 1718 Random1 = One + Half / Three; 1719 Random2 = (U2 + U1) + One; 1720 Z = Random1 * Random2; 1721 Y = Random2 * Random1; 1722 Z9 = (One + Half / Three) * ((U2 + U1) + One) - (One + Half / 1723 Three) * ((U2 + U1) + 1724 One); 1725 } 1726 if (!((I == NoTrials) || (Z9 == Zero))) 1727 BadCond (Defect, "X * Y == Y * X trial fails.\n"); 1728 else 1729 printf (" No failures found in %d integer pairs.\n", NoTrials); 1730 /*=============================================*/ 1731 Milestone = 70; 1732 /*=============================================*/ 1733 printf ("\nRunning test of square root(x).\n"); 1734 TstCond (Failure, (Zero == SQRT (Zero)) 1735 && (-Zero == SQRT (-Zero)) 1736 && (One == SQRT (One)), "Square root of 0.0, -0.0 or 1.0 wrong"); 1737 MinSqEr = Zero; 1738 MaxSqEr = Zero; 1739 J = Zero; 1740 X = Radix; 1741 OneUlp = U2; 1742 SqXMinX (Serious); 1743 X = BInvrse; 1744 OneUlp = BInvrse * U1; 1745 SqXMinX (Serious); 1746 X = U1; 1747 OneUlp = U1 * U1; 1748 SqXMinX (Serious); 1749 if (J != Zero) 1750 Pause (); 1751 printf ("Testing if sqrt(X * X) == X for %d Integers X.\n", NoTrials); 1752 J = Zero; 1753 X = Two; 1754 Y = Radix; 1755 if ((Radix != One)) 1756 do 1757 { 1758 X = Y; 1759 Y = Radix * Y; 1760 } 1761 while (!((Y - X >= NoTrials))); 1762 OneUlp = X * U2; 1763 I = 1; 1764 while (I <= NoTrials) 1765 { 1766 X = X + One; 1767 SqXMinX (Defect); 1768 if (J > Zero) 1769 break; 1770 I = I + 1; 1771 } 1772 printf ("Test for sqrt monotonicity.\n"); 1773 I = -1; 1774 X = BMinusU2; 1775 Y = Radix; 1776 Z = Radix + Radix * U2; 1777 NotMonot = false; 1778 Monot = false; 1779 while (!(NotMonot || Monot)) 1780 { 1781 I = I + 1; 1782 X = SQRT (X); 1783 Q = SQRT (Y); 1784 Z = SQRT (Z); 1785 if ((X > Q) || (Q > Z)) 1786 NotMonot = true; 1787 else 1788 { 1789 Q = FLOOR (Q + Half); 1790 if (!(I > 0 || Radix == Q * Q)) 1791 Monot = true; 1792 else if (I > 0) 1793 { 1794 if (I > 1) 1795 Monot = true; 1796 else 1797 { 1798 Y = Y * BInvrse; 1799 X = Y - U1; 1800 Z = Y + U1; 1801 } 1802 } 1803 else 1804 { 1805 Y = Q; 1806 X = Y - U2; 1807 Z = Y + U2; 1808 } 1809 } 1810 } 1811 if (Monot) 1812 printf ("sqrt has passed a test for Monotonicity.\n"); 1813 else 1814 { 1815 BadCond (Defect, ""); 1816 printf ("sqrt(X) is non-monotonic for X near %s .\n", Y.str()); 1817 } 1818 /*=============================================*/ 1819 Milestone = 110; 1820 /*=============================================*/ 1821 printf ("Seeking Underflow thresholds UfThold and E0.\n"); 1822 D = U1; 1823 if (Precision != FLOOR (Precision)) 1824 { 1825 D = BInvrse; 1826 X = Precision; 1827 do 1828 { 1829 D = D * BInvrse; 1830 X = X - One; 1831 } 1832 while (X > Zero); 1833 } 1834 Y = One; 1835 Z = D; 1836 /* ... D is power of 1/Radix < 1. */ 1837 do 1838 { 1839 C = Y; 1840 Y = Z; 1841 Z = Y * Y; 1842 } 1843 while ((Y > Z) && (Z + Z > Z)); 1844 Y = C; 1845 Z = Y * D; 1846 do 1847 { 1848 C = Y; 1849 Y = Z; 1850 Z = Y * D; 1851 } 1852 while ((Y > Z) && (Z + Z > Z)); 1853 if (Radix < Two) 1854 HInvrse = Two; 1855 else 1856 HInvrse = Radix; 1857 H = One / HInvrse; 1858 /* ... 1/HInvrse == H == Min(1/Radix, 1/2) */ 1859 CInvrse = One / C; 1860 E0 = C; 1861 Z = E0 * H; 1862 /* ...1/Radix^(BIG Integer) << 1 << CInvrse == 1/C */ 1863 do 1864 { 1865 Y = E0; 1866 E0 = Z; 1867 Z = E0 * H; 1868 } 1869 while ((E0 > Z) && (Z + Z > Z)); 1870 UfThold = E0; 1871 E1 = Zero; 1872 Q = Zero; 1873 E9 = U2; 1874 S = One + E9; 1875 D = C * S; 1876 if (D <= C) 1877 { 1878 E9 = Radix * U2; 1879 S = One + E9; 1880 D = C * S; 1881 if (D <= C) 1882 { 1883 BadCond (Failure, 1884 "multiplication gets too many last digits wrong.\n"); 1885 Underflow = E0; 1886 Y1 = Zero; 1887 PseudoZero = Z; 1888 Pause (); 1889 } 1890 } 1891 else 1892 { 1893 Underflow = D; 1894 PseudoZero = Underflow * H; 1895 UfThold = Zero; 1896 do 1897 { 1898 Y1 = Underflow; 1899 Underflow = PseudoZero; 1900 if (E1 + E1 <= E1) 1901 { 1902 Y2 = Underflow * HInvrse; 1903 E1 = FABS (Y1 - Y2); 1904 Q = Y1; 1905 if ((UfThold == Zero) && (Y1 != Y2)) 1906 UfThold = Y1; 1907 } 1908 PseudoZero = PseudoZero * H; 1909 } 1910 while ((Underflow > PseudoZero) 1911 && (PseudoZero + PseudoZero > PseudoZero)); 1912 } 1913 /* Comment line 4530 .. 4560 */ 1914 if (PseudoZero != Zero) 1915 { 1916 printf ("\n"); 1917 Z = PseudoZero; 1918 /* ... Test PseudoZero for "phoney- zero" violates */ 1919 /* ... PseudoZero < Underflow or PseudoZero < PseudoZero + PseudoZero 1920 ... */ 1921 if (PseudoZero <= Zero) 1922 { 1923 BadCond (Failure, "Positive expressions can underflow to an\n"); 1924 printf ("allegedly negative value\n"); 1925 printf ("PseudoZero that prints out as: %s .\n", PseudoZero.str()); 1926 X = -PseudoZero; 1927 if (X <= Zero) 1928 { 1929 printf ("But -PseudoZero, which should be\n"); 1930 printf ("positive, isn't; it prints out as %s .\n", X.str()); 1931 } 1932 } 1933 else 1934 { 1935 BadCond (Flaw, "Underflow can stick at an allegedly positive\n"); 1936 printf ("value PseudoZero that prints out as %s .\n", 1937 PseudoZero.str()); 1938 } 1939 TstPtUf (); 1940 } 1941 /*=============================================*/ 1942 Milestone = 120; 1943 /*=============================================*/ 1944 if (CInvrse * Y > CInvrse * Y1) 1945 { 1946 S = H * S; 1947 E0 = Underflow; 1948 } 1949 if (!((E1 == Zero) || (E1 == E0))) 1950 { 1951 BadCond (Defect, ""); 1952 if (E1 < E0) 1953 { 1954 printf ("Products underflow at a higher"); 1955 printf (" threshold than differences.\n"); 1956 if (PseudoZero == Zero) 1957 E0 = E1; 1958 } 1959 else 1960 { 1961 printf ("Difference underflows at a higher"); 1962 printf (" threshold than products.\n"); 1963 } 1964 } 1965 printf ("Smallest strictly positive number found is E0 = %s .\n", E0.str()); 1966 Z = E0; 1967 TstPtUf (); 1968 Underflow = E0; 1969 if (N == 1) 1970 Underflow = Y; 1971 I = 4; 1972 if (E1 == Zero) 1973 I = 3; 1974 if (UfThold == Zero) 1975 I = I - 2; 1976 UfNGrad = true; 1977 switch (I) 1978 { 1979 case 1: 1980 UfThold = Underflow; 1981 if ((CInvrse * Q) != ((CInvrse * Y) * S)) 1982 { 1983 UfThold = Y; 1984 BadCond (Failure, "Either accuracy deteriorates as numbers\n"); 1985 printf ("approach a threshold = %s\n", UfThold.str()); 1986 printf (" coming down from %s\n", C.str()); 1987 printf 1988 (" or else multiplication gets too many last digits wrong.\n"); 1989 } 1990 Pause (); 1991 break; 1992 1993 case 2: 1994 BadCond (Failure, 1995 "Underflow confuses Comparison, which alleges that\n"); 1996 printf ("Q == Y while denying that |Q - Y| == 0; these values\n"); 1997 printf ("print out as Q = %s, Y = %s .\n", Q.str(), Y2.str()); 1998 printf ("|Q - Y| = %s .\n", FABS (Q - Y2).str()); 1999 UfThold = Q; 2000 break; 2001 2002 case 3: 2003 X = X; 2004 break; 2005 2006 case 4: 2007 if ((Q == UfThold) && (E1 == E0) && (FABS (UfThold - E1 / E9) <= E1)) 2008 { 2009 UfNGrad = false; 2010 printf ("Underflow is gradual; it incurs Absolute Error =\n"); 2011 printf ("(roundoff in UfThold) < E0.\n"); 2012 Y = E0 * CInvrse; 2013 Y = Y * (OneAndHalf + U2); 2014 X = CInvrse * (One + U2); 2015 Y = Y / X; 2016 IEEE = (Y == E0); 2017 } 2018 } 2019 if (UfNGrad) 2020 { 2021 printf ("\n"); 2022 if (setjmp (ovfl_buf)) 2023 { 2024 printf ("Underflow / UfThold failed!\n"); 2025 R = H + H; 2026 } 2027 else 2028 R = SQRT (Underflow / UfThold); 2029 if (R <= H) 2030 { 2031 Z = R * UfThold; 2032 X = Z * (One + R * H * (One + H)); 2033 } 2034 else 2035 { 2036 Z = UfThold; 2037 X = Z * (One + H * H * (One + H)); 2038 } 2039 if (!((X == Z) || (X - Z != Zero))) 2040 { 2041 BadCond (Flaw, ""); 2042 printf ("X = %s\n\tis not equal to Z = %s .\n", X.str(), Z.str()); 2043 Z9 = X - Z; 2044 printf ("yet X - Z yields %s .\n", Z9.str()); 2045 printf (" Should this NOT signal Underflow, "); 2046 printf ("this is a SERIOUS DEFECT\nthat causes "); 2047 printf ("confusion when innocent statements like\n");; 2048 printf (" if (X == Z) ... else"); 2049 printf (" ... (f(X) - f(Z)) / (X - Z) ...\n"); 2050 printf ("encounter Division by Zero although actually\n"); 2051 if (setjmp (ovfl_buf)) 2052 printf ("X / Z fails!\n"); 2053 else 2054 printf ("X / Z = 1 + %s .\n", ((X / Z - Half) - Half).str()); 2055 } 2056 } 2057 printf ("The Underflow threshold is %s, below which\n", UfThold.str()); 2058 printf ("calculation may suffer larger Relative error than "); 2059 printf ("merely roundoff.\n"); 2060 Y2 = U1 * U1; 2061 Y = Y2 * Y2; 2062 Y2 = Y * U1; 2063 if (Y2 <= UfThold) 2064 { 2065 if (Y > E0) 2066 { 2067 BadCond (Defect, ""); 2068 I = 5; 2069 } 2070 else 2071 { 2072 BadCond (Serious, ""); 2073 I = 4; 2074 } 2075 printf ("Range is too narrow; U1^%d Underflows.\n", I); 2076 } 2077 /*=============================================*/ 2078 Milestone = 130; 2079 /*=============================================*/ 2080 Y = -FLOOR (Half - TwoForty * LOG (UfThold) / LOG (HInvrse)) / TwoForty; 2081 Y2 = Y + Y; 2082 printf ("Since underflow occurs below the threshold\n"); 2083 printf ("UfThold = (%s) ^ (%s)\nonly underflow ", HInvrse.str(), Y.str()); 2084 printf ("should afflict the expression\n\t(%s) ^ (%s);\n", 2085 HInvrse.str(), Y2.str()); 2086 printf ("actually calculating yields:"); 2087 if (setjmp (ovfl_buf)) 2088 { 2089 BadCond (Serious, "trap on underflow.\n"); 2090 } 2091 else 2092 { 2093 V9 = POW (HInvrse, Y2); 2094 printf (" %s .\n", V9.str()); 2095 if (!((V9 >= Zero) && (V9 <= (Radix + Radix + E9) * UfThold))) 2096 { 2097 BadCond (Serious, "this is not between 0 and underflow\n"); 2098 printf (" threshold = %s .\n", UfThold.str()); 2099 } 2100 else if (!(V9 > UfThold * (One + E9))) 2101 printf ("This computed value is O.K.\n"); 2102 else 2103 { 2104 BadCond (Defect, "this is not between 0 and underflow\n"); 2105 printf (" threshold = %s .\n", UfThold.str()); 2106 } 2107 } 2108 /*=============================================*/ 2109 Milestone = 160; 2110 /*=============================================*/ 2111 Pause (); 2112 printf ("Searching for Overflow threshold:\n"); 2113 printf ("This may generate an error.\n"); 2114 Y = -CInvrse; 2115 V9 = HInvrse * Y; 2116 if (setjmp (ovfl_buf)) 2117 { 2118 I = 0; 2119 V9 = Y; 2120 goto overflow; 2121 } 2122 do 2123 { 2124 V = Y; 2125 Y = V9; 2126 V9 = HInvrse * Y; 2127 } 2128 while (V9 < Y); 2129 I = 1; 2130 overflow: 2131 Z = V9; 2132 printf ("Can `Z = -Y' overflow?\n"); 2133 printf ("Trying it on Y = %s .\n", Y.str()); 2134 V9 = -Y; 2135 V0 = V9; 2136 if (V - Y == V + V0) 2137 printf ("Seems O.K.\n"); 2138 else 2139 { 2140 printf ("finds a "); 2141 BadCond (Flaw, "-(-Y) differs from Y.\n"); 2142 } 2143 if (Z != Y) 2144 { 2145 BadCond (Serious, ""); 2146 printf ("overflow past %s\n\tshrinks to %s .\n", Y.str(), Z.str()); 2147 } 2148 if (I) 2149 { 2150 Y = V * (HInvrse * U2 - HInvrse); 2151 Z = Y + ((One - HInvrse) * U2) * V; 2152 if (Z < V0) 2153 Y = Z; 2154 if (Y < V0) 2155 V = Y; 2156 if (V0 - V < V0) 2157 V = V0; 2158 } 2159 else 2160 { 2161 V = Y * (HInvrse * U2 - HInvrse); 2162 V = V + ((One - HInvrse) * U2) * Y; 2163 } 2164 printf ("Overflow threshold is V = %s .\n", V.str()); 2165 if (I) 2166 printf ("Overflow saturates at V0 = %s .\n", V0.str()); 2167 else 2168 printf ("There is no saturation value because " 2169 "the system traps on overflow.\n"); 2170 V9 = V * One; 2171 printf ("No Overflow should be signaled for V * 1 = %s\n", V9.str()); 2172 V9 = V / One; 2173 printf (" nor for V / 1 = %s.\n", V9.str()); 2174 printf ("Any overflow signal separating this * from the one\n"); 2175 printf ("above is a DEFECT.\n"); 2176 /*=============================================*/ 2177 Milestone = 170; 2178 /*=============================================*/ 2179 if (!(-V < V && -V0 < V0 && -UfThold < V && UfThold < V)) 2180 { 2181 BadCond (Failure, "Comparisons involving "); 2182 printf ("+-%s, +-%s\nand +-%s are confused by Overflow.", 2183 V.str(), V0.str(), UfThold.str()); 2184 } 2185 /*=============================================*/ 2186 Milestone = 175; 2187 /*=============================================*/ 2188 printf ("\n"); 2189 for (Indx = 1; Indx <= 3; ++Indx) 2190 { 2191 switch (Indx) 2192 { 2193 case 1: 2194 Z = UfThold; 2195 break; 2196 case 2: 2197 Z = E0; 2198 break; 2199 case 3: 2200 Z = PseudoZero; 2201 break; 2202 } 2203 if (Z != Zero) 2204 { 2205 V9 = SQRT (Z); 2206 Y = V9 * V9; 2207 if (Y / (One - Radix * E9) < Z || Y > (One + Radix * E9) * Z) 2208 { /* dgh: + E9 --> * E9 */ 2209 if (V9 > U1) 2210 BadCond (Serious, ""); 2211 else 2212 BadCond (Defect, ""); 2213 printf ("Comparison alleges that what prints as Z = %s\n", 2214 Z.str()); 2215 printf (" is too far from sqrt(Z) ^ 2 = %s .\n", Y.str()); 2216 } 2217 } 2218 } 2219 /*=============================================*/ 2220 Milestone = 180; 2221 /*=============================================*/ 2222 for (Indx = 1; Indx <= 2; ++Indx) 2223 { 2224 if (Indx == 1) 2225 Z = V; 2226 else 2227 Z = V0; 2228 V9 = SQRT (Z); 2229 X = (One - Radix * E9) * V9; 2230 V9 = V9 * X; 2231 if (((V9 < (One - Two * Radix * E9) * Z) || (V9 > Z))) 2232 { 2233 Y = V9; 2234 if (X < W) 2235 BadCond (Serious, ""); 2236 else 2237 BadCond (Defect, ""); 2238 printf ("Comparison alleges that Z = %s\n", Z.str()); 2239 printf (" is too far from sqrt(Z) ^ 2 (%s) .\n", Y.str()); 2240 } 2241 } 2242 /*=============================================*/ 2243 Milestone = 190; 2244 /*=============================================*/ 2245 Pause (); 2246 X = UfThold * V; 2247 Y = Radix * Radix; 2248 if (X * Y < One || X > Y) 2249 { 2250 if (X * Y < U1 || X > Y / U1) 2251 BadCond (Defect, "Badly"); 2252 else 2253 BadCond (Flaw, ""); 2254 2255 printf (" unbalanced range; UfThold * V = %s\n\t%s\n", 2256 X.str(), "is too far from 1.\n"); 2257 } 2258 /*=============================================*/ 2259 Milestone = 200; 2260 /*=============================================*/ 2261 for (Indx = 1; Indx <= 5; ++Indx) 2262 { 2263 X = F9; 2264 switch (Indx) 2265 { 2266 case 2: 2267 X = One + U2; 2268 break; 2269 case 3: 2270 X = V; 2271 break; 2272 case 4: 2273 X = UfThold; 2274 break; 2275 case 5: 2276 X = Radix; 2277 } 2278 Y = X; 2279 if (setjmp (ovfl_buf)) 2280 printf (" X / X traps when X = %s\n", X.str()); 2281 else 2282 { 2283 V9 = (Y / X - Half) - Half; 2284 if (V9 == Zero) 2285 continue; 2286 if (V9 == -U1 && Indx < 5) 2287 BadCond (Flaw, ""); 2288 else 2289 BadCond (Serious, ""); 2290 printf (" X / X differs from 1 when X = %s\n", X.str()); 2291 printf (" instead, X / X - 1/2 - 1/2 = %s .\n", V9.str()); 2292 } 2293 } 2294 /*=============================================*/ 2295 Milestone = 210; 2296 /*=============================================*/ 2297 MyZero = Zero; 2298 printf ("\n"); 2299 printf ("What message and/or values does Division by Zero produce?\n"); 2300 printf (" Trying to compute 1 / 0 produces ..."); 2301 if (!setjmp (ovfl_buf)) 2302 printf (" %s .\n", (One / MyZero).str()); 2303 printf ("\n Trying to compute 0 / 0 produces ..."); 2304 if (!setjmp (ovfl_buf)) 2305 printf (" %s .\n", (Zero / MyZero).str()); 2306 /*=============================================*/ 2307 Milestone = 220; 2308 /*=============================================*/ 2309 Pause (); 2310 printf ("\n"); 2311 { 2312 static const char *msg[] = { 2313 "FAILUREs encountered =", 2314 "SERIOUS DEFECTs discovered =", 2315 "DEFECTs discovered =", 2316 "FLAWs discovered =" 2317 }; 2318 int i; 2319 for (i = 0; i < 4; i++) 2320 if (ErrCnt[i]) 2321 printf ("The number of %-29s %d.\n", msg[i], ErrCnt[i]); 2322 } 2323 printf ("\n"); 2324 if ((ErrCnt[Failure] + ErrCnt[Serious] + ErrCnt[Defect] + ErrCnt[Flaw]) > 0) 2325 { 2326 if ((ErrCnt[Failure] + ErrCnt[Serious] + ErrCnt[Defect] == 0) 2327 && (ErrCnt[Flaw] > 0)) 2328 { 2329 printf ("The arithmetic diagnosed seems "); 2330 printf ("Satisfactory though flawed.\n"); 2331 } 2332 if ((ErrCnt[Failure] + ErrCnt[Serious] == 0) && (ErrCnt[Defect] > 0)) 2333 { 2334 printf ("The arithmetic diagnosed may be Acceptable\n"); 2335 printf ("despite inconvenient Defects.\n"); 2336 } 2337 if ((ErrCnt[Failure] + ErrCnt[Serious]) > 0) 2338 { 2339 printf ("The arithmetic diagnosed has "); 2340 printf ("unacceptable Serious Defects.\n"); 2341 } 2342 if (ErrCnt[Failure] > 0) 2343 { 2344 printf ("Potentially fatal FAILURE may have spoiled this"); 2345 printf (" program's subsequent diagnoses.\n"); 2346 } 2347 } 2348 else 2349 { 2350 printf ("No failures, defects nor flaws have been discovered.\n"); 2351 if (!((RMult == Rounded) && (RDiv == Rounded) 2352 && (RAddSub == Rounded) && (RSqrt == Rounded))) 2353 printf ("The arithmetic diagnosed seems Satisfactory.\n"); 2354 else 2355 { 2356 if (StickyBit >= One && 2357 (Radix - Two) * (Radix - Nine - One) == Zero) 2358 { 2359 printf ("Rounding appears to conform to "); 2360 printf ("the proposed IEEE standard P"); 2361 if ((Radix == Two) && 2362 ((Precision - Four * Three * Two) * 2363 (Precision - TwentySeven - TwentySeven + One) == Zero)) 2364 printf ("754"); 2365 else 2366 printf ("854"); 2367 if (IEEE) 2368 printf (".\n"); 2369 else 2370 { 2371 printf (",\nexcept for possibly Double Rounding"); 2372 printf (" during Gradual Underflow.\n"); 2373 } 2374 } 2375 printf ("The arithmetic diagnosed appears to be Excellent!\n"); 2376 } 2377 } 2378 printf ("END OF TEST.\n"); 2379 return 0; 2380 } 2381 2382 template<typename FLOAT> 2383 FLOAT 2384 Paranoia<FLOAT>::Sign (FLOAT X) 2385 { 2386 return X >= FLOAT (long (0)) ? 1 : -1; 2387 } 2388 2389 template<typename FLOAT> 2390 void 2391 Paranoia<FLOAT>::Pause () 2392 { 2393 if (do_pause) 2394 { 2395 fputs ("Press return...", stdout); 2396 fflush (stdout); 2397 getchar(); 2398 } 2399 printf ("\nDiagnosis resumes after milestone Number %d", Milestone); 2400 printf (" Page: %d\n\n", PageNo); 2401 ++Milestone; 2402 ++PageNo; 2403 } 2404 2405 template<typename FLOAT> 2406 void 2407 Paranoia<FLOAT>::TstCond (int K, int Valid, const char *T) 2408 { 2409 if (!Valid) 2410 { 2411 BadCond (K, T); 2412 printf (".\n"); 2413 } 2414 } 2415 2416 template<typename FLOAT> 2417 void 2418 Paranoia<FLOAT>::BadCond (int K, const char *T) 2419 { 2420 static const char *msg[] = { "FAILURE", "SERIOUS DEFECT", "DEFECT", "FLAW" }; 2421 2422 ErrCnt[K] = ErrCnt[K] + 1; 2423 printf ("%s: %s", msg[K], T); 2424 } 2425 2426 /* Random computes 2427 X = (Random1 + Random9)^5 2428 Random1 = X - FLOOR(X) + 0.000005 * X; 2429 and returns the new value of Random1. */ 2430 2431 template<typename FLOAT> 2432 FLOAT 2433 Paranoia<FLOAT>::Random () 2434 { 2435 FLOAT X, Y; 2436 2437 X = Random1 + Random9; 2438 Y = X * X; 2439 Y = Y * Y; 2440 X = X * Y; 2441 Y = X - FLOOR (X); 2442 Random1 = Y + X * FLOAT ("0.000005"); 2443 return (Random1); 2444 } 2445 2446 template<typename FLOAT> 2447 void 2448 Paranoia<FLOAT>::SqXMinX (int ErrKind) 2449 { 2450 FLOAT XA, XB; 2451 2452 XB = X * BInvrse; 2453 XA = X - XB; 2454 SqEr = ((SQRT (X * X) - XB) - XA) / OneUlp; 2455 if (SqEr != Zero) 2456 { 2457 if (SqEr < MinSqEr) 2458 MinSqEr = SqEr; 2459 if (SqEr > MaxSqEr) 2460 MaxSqEr = SqEr; 2461 J = J + 1; 2462 BadCond (ErrKind, "\n"); 2463 printf ("sqrt(%s) - %s = %s\n", (X * X).str(), X.str(), 2464 (OneUlp * SqEr).str()); 2465 printf ("\tinstead of correct value 0 .\n"); 2466 } 2467 } 2468 2469 template<typename FLOAT> 2470 void 2471 Paranoia<FLOAT>::NewD () 2472 { 2473 X = Z1 * Q; 2474 X = FLOOR (Half - X / Radix) * Radix + X; 2475 Q = (Q - X * Z) / Radix + X * X * (D / Radix); 2476 Z = Z - Two * X * D; 2477 if (Z <= Zero) 2478 { 2479 Z = -Z; 2480 Z1 = -Z1; 2481 } 2482 D = Radix * D; 2483 } 2484 2485 template<typename FLOAT> 2486 void 2487 Paranoia<FLOAT>::SR3750 () 2488 { 2489 if (!((X - Radix < Z2 - Radix) || (X - Z2 > W - Z2))) 2490 { 2491 I = I + 1; 2492 X2 = SQRT (X * D); 2493 Y2 = (X2 - Z2) - (Y - Z2); 2494 X2 = X8 / (Y - Half); 2495 X2 = X2 - Half * X2 * X2; 2496 SqEr = (Y2 + Half) + (Half - X2); 2497 if (SqEr < MinSqEr) 2498 MinSqEr = SqEr; 2499 SqEr = Y2 - X2; 2500 if (SqEr > MaxSqEr) 2501 MaxSqEr = SqEr; 2502 } 2503 } 2504 2505 template<typename FLOAT> 2506 void 2507 Paranoia<FLOAT>::IsYeqX () 2508 { 2509 if (Y != X) 2510 { 2511 if (N <= 0) 2512 { 2513 if (Z == Zero && Q <= Zero) 2514 printf ("WARNING: computing\n"); 2515 else 2516 BadCond (Defect, "computing\n"); 2517 printf ("\t(%s) ^ (%s)\n", Z.str(), Q.str()); 2518 printf ("\tyielded %s;\n", Y.str()); 2519 printf ("\twhich compared unequal to correct %s ;\n", X.str()); 2520 printf ("\t\tthey differ by %s .\n", (Y - X).str()); 2521 } 2522 N = N + 1; /* ... count discrepancies. */ 2523 } 2524 } 2525 2526 template<typename FLOAT> 2527 void 2528 Paranoia<FLOAT>::PrintIfNPositive () 2529 { 2530 if (N > 0) 2531 printf ("Similar discrepancies have occurred %d times.\n", N); 2532 } 2533 2534 template<typename FLOAT> 2535 void 2536 Paranoia<FLOAT>::TstPtUf () 2537 { 2538 N = 0; 2539 if (Z != Zero) 2540 { 2541 printf ("Since comparison denies Z = 0, evaluating "); 2542 printf ("(Z + Z) / Z should be safe.\n"); 2543 if (setjmp (ovfl_buf)) 2544 goto very_serious; 2545 Q9 = (Z + Z) / Z; 2546 printf ("What the machine gets for (Z + Z) / Z is %s .\n", Q9.str()); 2547 if (FABS (Q9 - Two) < Radix * U2) 2548 { 2549 printf ("This is O.K., provided Over/Underflow"); 2550 printf (" has NOT just been signaled.\n"); 2551 } 2552 else 2553 { 2554 if ((Q9 < One) || (Q9 > Two)) 2555 { 2556 very_serious: 2557 N = 1; 2558 ErrCnt[Serious] = ErrCnt[Serious] + 1; 2559 printf ("This is a VERY SERIOUS DEFECT!\n"); 2560 } 2561 else 2562 { 2563 N = 1; 2564 ErrCnt[Defect] = ErrCnt[Defect] + 1; 2565 printf ("This is a DEFECT!\n"); 2566 } 2567 } 2568 V9 = Z * One; 2569 Random1 = V9; 2570 V9 = One * Z; 2571 Random2 = V9; 2572 V9 = Z / One; 2573 if ((Z == Random1) && (Z == Random2) && (Z == V9)) 2574 { 2575 if (N > 0) 2576 Pause (); 2577 } 2578 else 2579 { 2580 N = 1; 2581 BadCond (Defect, "What prints as Z = "); 2582 printf ("%s\n\tcompares different from ", Z.str()); 2583 if (Z != Random1) 2584 printf ("Z * 1 = %s ", Random1.str()); 2585 if (!((Z == Random2) || (Random2 == Random1))) 2586 printf ("1 * Z == %s\n", Random2.str()); 2587 if (!(Z == V9)) 2588 printf ("Z / 1 = %s\n", V9.str()); 2589 if (Random2 != Random1) 2590 { 2591 ErrCnt[Defect] = ErrCnt[Defect] + 1; 2592 BadCond (Defect, "Multiplication does not commute!\n"); 2593 printf ("\tComparison alleges that 1 * Z = %s\n", Random2.str()); 2594 printf ("\tdiffers from Z * 1 = %s\n", Random1.str()); 2595 } 2596 Pause (); 2597 } 2598 } 2599 } 2600 2601 template<typename FLOAT> 2602 void 2603 Paranoia<FLOAT>::notify (const char *s) 2604 { 2605 printf ("%s test appears to be inconsistent...\n", s); 2606 printf (" PLEASE NOTIFY KARPINKSI!\n"); 2607 } 2608 2609 /* ====================================================================== */ 2610 2611 int main(int ac, char **av) 2612 { 2613 setbuf(stdout, NULL); 2614 setbuf(stderr, NULL); 2615 2616 while (1) 2617 switch (getopt (ac, av, "pvg:fdl")) 2618 { 2619 case -1: 2620 return 0; 2621 case 'p': 2622 do_pause = true; 2623 break; 2624 case 'v': 2625 verbose = true; 2626 break; 2627 case 'g': 2628 { 2629 static const struct { 2630 const char *name; 2631 const struct real_format *fmt; 2632 } fmts[] = { 2633 #define F(x) { #x, &x##_format } 2634 F(ieee_single), 2635 F(ieee_double), 2636 F(ieee_extended_motorola), 2637 F(ieee_extended_intel_96), 2638 F(ieee_extended_intel_128), 2639 F(ibm_extended), 2640 F(ieee_quad), 2641 F(vax_f), 2642 F(vax_d), 2643 F(vax_g), 2644 F(i370_single), 2645 F(i370_double), 2646 F(c4x_single), 2647 F(c4x_extended), 2648 F(real_internal), 2649 #undef F 2650 }; 2651 2652 int i, n = sizeof (fmts)/sizeof(*fmts); 2653 2654 for (i = 0; i < n; ++i) 2655 if (strcmp (fmts[i].name, optarg) == 0) 2656 break; 2657 2658 if (i == n) 2659 { 2660 printf ("Unknown implementation \"%s\"; " 2661 "available implementations:\n", optarg); 2662 for (i = 0; i < n; ++i) 2663 printf ("\t%s\n", fmts[i].name); 2664 return 1; 2665 } 2666 2667 // We cheat and use the same mode all the time, but vary 2668 // the format used for that mode. 2669 real_format_for_mode[int(real_c_float::MODE) - int(QFmode)] 2670 = fmts[i].fmt; 2671 2672 Paranoia<real_c_float>().main(); 2673 break; 2674 } 2675 2676 case 'f': 2677 Paranoia < native_float<float> >().main(); 2678 break; 2679 case 'd': 2680 Paranoia < native_float<double> >().main(); 2681 break; 2682 case 'l': 2683 #ifndef NO_LONG_DOUBLE 2684 Paranoia < native_float<long double> >().main(); 2685 #endif 2686 break; 2687 2688 case '?': 2689 puts ("-p\tpause between pages"); 2690 puts ("-g<FMT>\treal.c implementation FMT"); 2691 puts ("-f\tnative float"); 2692 puts ("-d\tnative double"); 2693 puts ("-l\tnative long double"); 2694 return 0; 2695 } 2696 } 2697 2698 /* GCC stuff referenced by real.o. */ 2699 2700 extern "C" void 2701 fancy_abort () 2702 { 2703 abort (); 2704 } 2705 2706 int target_flags = 0; 2707 2708 extern "C" int 2709 floor_log2_wide (unsigned HOST_WIDE_INT x) 2710 { 2711 int log = -1; 2712 while (x != 0) 2713 log++, 2714 x >>= 1; 2715 return log; 2716 } 2717