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