1 /* A C version of Kahan's Floating Point Test "Paranoia"
3 Thos Sumner, UCSF, Feb. 1985
4 David Gay, BTL, Jan. 1986
6 This is a rewrite from the Pascal version by
8 B. A. Wichmann, 18 Jan. 1985
10 (and does NOT exhibit good C programming style).
12 Adjusted to use Standard C headers 19 Jan. 1992 (dmg);
14 (C) Apr 19 1983 in BASIC version by:
15 Professor W. M. Kahan,
17 Electrical Engineering & Computer Science Dept.
18 University of California
19 Berkeley, California 94720
22 converted to Pascal by:
24 National Physical Laboratory
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
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.]
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.
46 You may copy this program freely if you acknowledge its source.
47 Comments on the Pascal version to NPL, please.
49 The following is from the introductory commentary from Wichmann's work:
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
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]:
64 BASIC C BASIC C BASIC C
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
85 F1 MinusOne O5 Five X9 Random1
91 G2 GDiv Q9 Z0 PseudoZero
94 H1 HInverse R2 RDiv Z9
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.
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:
117 170- 250 Instructions
119 480- 670 Characteristics
123 4040-4080 DoesYequalX
124 4090-4110 PrintIfNPositive
125 4640-4850 TestPartialUnderflow
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.
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. */
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
152 #include "ansidecl.h"
153 #include "auto-host.h"
156 #undef EXTRA_MODES_FILE
159 typedef struct rtx_def
*rtx
;
161 typedef struct rtvec_def
*rtvec
;
163 typedef union tree_node
*tree
;
165 #define DEFTREECODE(SYM, STRING, TYPE, NARGS) SYM,
168 LAST_AND_UNUSED_TREE_CODE
172 #define ENUM_BITFIELD(X) enum X
180 /* We never produce signals from the library. Thus setjmp need do nothing. */
182 #define setjmp(x) (0)
184 static bool verbose
= false;
185 static int verbose_index
= 0;
187 /* ====================================================================== */
188 /* The implementation of the abstract floating point class based on gcc's
189 real.c. I.e. the object of this exercise. Templated so that we can
195 static const enum machine_mode MODE
= SFmode
;
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
];
203 void from_long(long);
204 void from_str(const char *);
205 void binop(int code
, const real_c_float
&);
207 bool cmp(int code
, const real_c_float
&) const;
214 real_c_float(const char *s
)
216 real_c_float(const real_c_float
&b
)
217 { memcpy(image
, b
.image
, sizeof(image
)); }
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; }
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; }
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
; }
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
); }
247 const char * str () const;
248 const char * hex () const;
249 long integer () const;
255 real_c_float::from_long (long l
)
259 real_from_integer (&f
, MODE
, l
, l
< 0 ? -1 : 0, 0);
260 real_to_target (image
, &f
, MODE
);
264 real_c_float::from_str (const char *s
)
269 if (*p
== '-' || *p
== '+')
271 if (strcasecmp(p
, "inf") == 0)
275 real_arithmetic (&f
, NEGATE_EXPR
, &f
, NULL
);
277 else if (strcasecmp(p
, "nan") == 0)
278 real_nan (&f
, "", 1, MODE
);
280 real_from_string (&f
, s
);
282 real_to_target (image
, &f
, MODE
);
286 real_c_float::binop (int code
, const real_c_float
&b
)
288 REAL_VALUE_TYPE ai
, bi
, ri
;
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
);
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
;
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);
310 symbol_for_code
= '+';
313 symbol_for_code
= '-';
316 symbol_for_code
= '*';
319 symbol_for_code
= '/';
325 fprintf (stderr
, "%6d: %s %c %s = %s\n", verbose_index
++,
326 ab
, symbol_for_code
, bb
, rb
);
331 real_c_float::unop (int code
)
333 REAL_VALUE_TYPE ai
, ri
;
335 real_from_target (&ai
, image
, MODE
);
336 real_arithmetic (&ri
, code
, &ai
, NULL
);
337 real_to_target (image
, &ri
, MODE
);
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
;
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);
353 symbol_for_code
= "-";
356 symbol_for_code
= "abs ";
362 fprintf (stderr
, "%6d: %s%s = %s\n", verbose_index
++,
363 symbol_for_code
, ab
, rb
);
368 real_c_float::cmp (int code
, const real_c_float
&b
) const
370 REAL_VALUE_TYPE ai
, bi
;
373 real_from_target (&ai
, image
, MODE
);
374 real_from_target (&bi
, b
.image
, MODE
);
375 ret
= real_compare (code
, &ai
, &bi
);
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
;
384 real_to_hexadecimal (ab
, &ai
, sizeof(ab
), digits
, 0);
385 real_to_hexadecimal (bb
, &bi
, sizeof(bb
), digits
, 0);
390 symbol_for_code
= "<";
393 symbol_for_code
= "<=";
396 symbol_for_code
= "==";
399 symbol_for_code
= "!=";
402 symbol_for_code
= ">=";
405 symbol_for_code
= ">";
411 fprintf (stderr
, "%6d: %s %s %s = %s\n", verbose_index
++,
412 ab
, symbol_for_code
, bb
, (ret
? "true" : "false"));
419 real_c_float::str() const
422 const real_format
*fmt
= real_format_for_mode
[MODE
- QFmode
];
423 const int digits
= int(fmt
->p
* fmt
->log2_b
* .30102999566398119521 + 1);
425 real_from_target (&f
, image
, MODE
);
426 char *buf
= new char[digits
+ 10];
427 real_to_decimal (buf
, &f
, digits
+10, digits
, 0);
433 real_c_float::hex() const
436 const real_format
*fmt
= real_format_for_mode
[MODE
- QFmode
];
437 const int digits
= (fmt
->p
* fmt
->log2_b
+ 3) / 4;
439 real_from_target (&f
, image
, MODE
);
440 char *buf
= new char[digits
+ 10];
441 real_to_hexadecimal (buf
, &f
, digits
+10, digits
, 0);
447 real_c_float::integer() const
450 real_from_target (&f
, image
, MODE
);
451 return real_to_integer (&f
);
455 real_c_float::exp() const
458 real_from_target (&f
, image
, MODE
);
459 return real_exponent (&f
);
463 real_c_float::ldexp (int exp
)
467 real_from_target (&ai
, image
, MODE
);
468 real_ldexp (&ai
, &ai
, exp
);
469 real_to_target (image
, &ai
, MODE
);
472 /* ====================================================================== */
473 /* An implementation of the abstract floating point class that uses native
474 arithmetic. Exists for reference and debugging. */
480 // Force intermediate results back to memory.
483 static T
from_str (const char *);
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);
494 native_float(const char *s
)
495 { image
= from_str(s
); }
496 native_float(const native_float
&b
)
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; }
506 const native_float
& operator+= (const native_float
&b
)
508 image
= verbose_binop(image
, '+', b
.image
, image
+ b
.image
);
511 const native_float
& operator-= (const native_float
&b
)
513 image
= verbose_binop(image
, '-', b
.image
, image
- b
.image
);
516 const native_float
& operator*= (const native_float
&b
)
518 image
= verbose_binop(image
, '*', b
.image
, image
* b
.image
);
521 const native_float
& operator/= (const native_float
&b
)
523 image
= verbose_binop(image
, '/', b
.image
, image
/ b
.image
);
527 native_float
operator- () const
530 r
.image
= verbose_unop("-", image
, -image
);
533 native_float
abs () const
536 r
.image
= verbose_unop("abs ", image
, do_abs(image
));
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
); }
553 const char * str () const;
554 const char * hex () const;
555 long integer () const
556 { return long(image
); }
563 native_float
<T
>::from_str (const char *s
)
565 return strtold (s
, NULL
);
570 native_float
<float>::from_str (const char *s
)
572 return strtof (s
, NULL
);
577 native_float
<double>::from_str (const char *s
)
579 return strtod (s
, NULL
);
584 native_float
<T
>::do_abs (T image
)
586 return fabsl (image
);
591 native_float
<float>::do_abs (float image
)
593 return fabsf (image
);
598 native_float
<double>::do_abs (double image
)
605 native_float
<T
>::verbose_binop (T a
, char symbol
, T b
, T r
)
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
);
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
);
625 native_float
<T
>::verbose_unop (const char *symbol
, T a
, T r
)
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
);
634 fprintf (stderr
, "%6d: %s%.*La = %.*La\n", verbose_index
++,
635 symbol
, digits
, (long double)a
, digits
, (long double)r
);
643 native_float
<T
>::verbose_cmp (T a
, const char *symbol
, T b
, bool r
)
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"));
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"));
663 native_float
<T
>::str() const
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
);
670 sprintf (buf
, "%.*Le", digits
- 1, (long double) image
);
677 native_float
<T
>::hex() const
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
);
684 sprintf (buf
, "%.*La", digits
- 1, (long double) image
);
691 native_float
<T
>::exp() const
700 native_float
<T
>::ldexp (int exp
)
702 image
= ldexpl (image
, exp
);
707 native_float
<float>::ldexp (int exp
)
709 image
= ldexpf (image
, exp
);
714 native_float
<double>::ldexp (int exp
)
716 image
= ::ldexp (image
, exp
);
719 /* ====================================================================== */
720 /* Some libm routines that Paranoia expects to be available. */
722 template<typename FLOAT
>
724 FABS (const FLOAT
&f
)
729 template<typename FLOAT
, typename RHS
>
731 operator+ (const FLOAT
&a
, const RHS
&b
)
733 return FLOAT(a
) += FLOAT(b
);
736 template<typename FLOAT
, typename RHS
>
738 operator- (const FLOAT
&a
, const RHS
&b
)
740 return FLOAT(a
) -= FLOAT(b
);
743 template<typename FLOAT
, typename RHS
>
745 operator* (const FLOAT
&a
, const RHS
&b
)
747 return FLOAT(a
) *= FLOAT(b
);
750 template<typename FLOAT
, typename RHS
>
752 operator/ (const FLOAT
&a
, const RHS
&b
)
754 return FLOAT(a
) /= FLOAT(b
);
757 template<typename FLOAT
>
759 FLOOR (const FLOAT
&f
)
761 /* ??? This is only correct when F is representable as an integer. */
762 long i
= f
.integer();
772 template<typename FLOAT
>
774 SQRT (const FLOAT
&f
)
777 FLOAT zero
= long(0);
791 z
.ldexp (-f
.exp() / 2);
793 diff2
= FABS (z
* z
- f
);
797 t
= (f
/ (two
* z
)) + (z
/ two
);
798 diff
= FABS (t
* t
- f
);
806 #elif defined(NO_LONG_DOUBLE)
810 d
= strtod (f
.hex(), NULL
);
812 sprintf(buf
, "%.35a", d
);
819 ld
= strtold (f
.hex(), NULL
);
821 sprintf(buf
, "%.35La", ld
);
827 template<typename FLOAT
>
832 FLOAT zero
= long(0);
840 int exp
= x
.exp() - 1;
851 FLOAT term
= y
/ FLOAT (n
);
852 FLOAT next
= sum
+ term
;
861 sum
+= FLOAT (exp
) * FLOAT(".69314718055994530941");
864 #elif defined (NO_LONG_DOUBLE)
868 d
= strtod (x
.hex(), NULL
);
870 sprintf(buf
, "%.35a", d
);
877 ld
= strtold (x
.hex(), NULL
);
879 sprintf(buf
, "%.35La", ld
);
885 template<typename FLOAT
>
890 #ifdef NO_LONG_DOUBLE
894 d
= strtod (x
.hex(), NULL
);
896 sprintf(buf
, "%.35a", d
);
903 ld
= strtold (x
.hex(), NULL
);
905 sprintf(buf
, "%.35La", ld
);
911 template<typename FLOAT
>
913 POW (const FLOAT
&base
, const FLOAT
&exp
)
916 #ifdef NO_LONG_DOUBLE
920 d1
= strtod (base
.hex(), NULL
);
921 d2
= strtod (exp
.hex(), NULL
);
923 sprintf(buf
, "%.35a", d1
);
927 long double ld1
, ld2
;
930 ld1
= strtold (base
.hex(), NULL
);
931 ld2
= strtold (exp
.hex(), NULL
);
932 ld1
= powl (ld1
, ld2
);
933 sprintf(buf
, "%.35La", ld1
);
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. */
943 int NoTrials
= 20; /*Number of tests for commutativity. */
944 bool do_pause
= false;
946 enum Guard
{ No
, Yes
};
947 enum Rounding
{ Other
, Rounded
, Chopped
};
948 enum Class
{ Failure
, Serious
, Defect
, Flaw
};
950 template<typename FLOAT
>
953 FLOAT Radix
, BInvrse
, RadixD2
, BMinusU2
;
955 /* Small floating point constants. */
971 /* Declarations of Variables. */
977 FLOAT E0
, E1
, Exp2
, E3
, MinSqEr
;
978 FLOAT SqEr
, MaxSqEr
, E9
;
988 FLOAT T
, Underflow
, S
;
989 FLOAT OneUlp
, UfThold
, U1
, U2
;
992 FLOAT X
, X1
, X2
, X8
, Random1
;
993 FLOAT Y
, Y1
, Y2
, Random2
;
994 FLOAT Z
, PseudoZero
, Z1
, Z2
, Z9
;
999 Guard GMult
, GDiv
, GAddSub
;
1000 Rounding RMult
, RDiv
, RAddSub
, RSqrt
;
1001 int Break
, Done
, NotMonot
, Monot
, Anomaly
, IEEE
, SqRWrng
, UfNGrad
;
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 */
1012 void BadCond (int, const char *);
1014 void TstCond (int, int, const char *);
1015 void notify (const char *);
1018 void PrintIfNPositive ();
1022 // Pretend we're bss.
1023 Paranoia() { memset(this, 0, sizeof (*this)); }
1026 template<typename FLOAT
>
1028 Paranoia
<FLOAT
>::main()
1030 /* First two assignments use integer right-hand sides. */
1039 TwentySeven
= long(27);
1040 ThirtyTwo
= long(32);
1041 TwoForty
= long(240);
1042 MinusOne
= long(-1);
1044 OneAndHalf
= "0x3p-1";
1045 ErrCnt
[Failure
] = 0;
1046 ErrCnt
[Serious
] = 0;
1050 /*=============================================*/
1052 /*=============================================*/
1053 printf ("Program is now RUNNING tests on small integers:\n");
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");
1063 ErrCnt
[Failure
] = ErrCnt
[Failure
] + 1;
1064 printf ("Comparison alleges that -0.0 is Non-zero!\n");
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");
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");
1082 TstCond (Failure
, Half
+ MinusOne
+ Half
== Zero
, "1/2 + (-1) + 1/2 != 0");
1084 /*=============================================*/
1086 /*=============================================*/
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
),
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");
1104 if (ErrCnt
[Failure
] == 0)
1106 printf ("-1, 0, 1/2, 1, 2, 3, 4, 5, 9, 27, 32 & 240 are O.K.\n");
1109 printf ("Searching for Radix and Precision.\n");
1118 while (MinusOne
+ FABS (Y
) < Zero
);
1119 /*.. now W is just big enough that |((W+1)-W)-1| >= 1 ... */
1128 while (Radix
== Zero
);
1131 printf ("Radix = %s .\n", Radix
.str());
1137 Precision
= Precision
+ One
;
1141 while ((Y
- W
) == One
);
1143 /*... now W == Radix^Precision is barely too big to satisfy (W+1)-W == 1
1147 printf ("Closest relative separation found is U1 = %s .\n\n", U1
.str());
1148 printf ("Recalculating radix and precision\n ");
1150 /*save old values */
1160 X
= FABS (X
- Third
);
1164 /*... now X = (unknown no.) ulps of 1+... */
1168 Y
= Half
* U2
+ ThirtyTwo
* U2
* U2
;
1172 while (!((U2
<= X
) || (X
<= Zero
)));
1174 /*... now U2 == 1 ulp of 1 + ... */
1183 /*... now X == (unknown no.) ulps of 1 -... */
1187 Y
= Half
* U1
+ ThirtyTwo
* U1
* U1
;
1193 while (!((U1
<= X
) || (X
<= Zero
)));
1194 /*... now U1 == 1 ulp of 1 - ... */
1196 printf ("confirms closest relative separation U1 .\n");
1198 printf ("gets better closest relative separation U1 = %s .\n", U1
.str());
1200 F9
= (Half
- U1
) + Half
;
1202 Radix
= FLOOR (FLOAT ("0.01") + U2
/ U1
);
1204 printf ("Radix confirmed.\n");
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 /*=============================================*/
1213 /*=============================================*/
1214 TstCond (Failure
, F9
- Half
< Half
,
1215 "(1-U1)-1/2 < 1/2 is FALSE, prog. fails?");
1220 TstCond (Failure
, (X
!= One
)
1221 || (Z
== Zero
), "Comparison is fuzzy,X=1 but X-1/2-1/2 != 0");
1224 /*=============================================*/
1226 /*=============================================*/
1227 /*... BMinusU2 = nextafter(Radix, 0) */
1228 BMinusU2
= Radix
- One
;
1229 BMinusU2
= (BMinusU2
- U2
) + One
;
1230 /* Purify Integers */
1233 X
= -TwoForty
* LOG (U1
) / LOG (Radix
);
1234 Y
= FLOOR (Half
+ X
);
1235 if (FABS (X
- Y
) * Four
< One
)
1237 Precision
= X
/ TwoForty
;
1238 Y
= FLOOR (Half
+ Precision
);
1239 if (FABS (Precision
- Y
) * TwoForty
< Half
)
1242 if ((Precision
!= FLOOR (Precision
)) || (Radix
== One
))
1244 printf ("Precision cannot be characterized by an Integer number\n");
1246 ("of significant digits but, by itself, this is a minor flaw.\n");
1250 ("logarithmic encoding has precision characterized solely by U1.\n");
1252 printf ("The number of significant digits of the Radix is %s .\n",
1254 TstCond (Serious
, U2
* Nine
* Nine
* TwoForty
< One
,
1255 "Precision worse than 5 decimal figures ");
1256 /*=============================================*/
1258 /*=============================================*/
1259 /* Test for extra-precise subexpressions */
1260 X
= FABS (((Four
/ Three
- One
) - One
/ Four
) * Three
- One
/ Four
);
1264 X
= (One
+ (Half
* Z2
+ ThirtyTwo
* Z2
* Z2
)) - One
;
1266 while (!((Z2
<= X
) || (X
<= Zero
)));
1267 X
= Y
= Z
= FABS ((Three
/ Four
- Two
/ Three
) * Three
- One
/ Four
);
1271 Z
= (One
/ Two
- ((One
/ Two
- (Half
* Z1
+ ThirtyTwo
* Z1
* Z1
))
1272 + One
/ Two
)) + One
/ Two
;
1274 while (!((Z1
<= Z
) || (Z
<= Zero
)));
1281 (Half
- ((Half
- (Half
* Y1
+ ThirtyTwo
* Y1
* Y1
)) + Half
)) +
1284 while (!((Y1
<= Y
) || (Y
<= Zero
)));
1286 X
= ((Half
* X1
+ ThirtyTwo
* X1
* X1
) - F9
) + F9
;
1288 while (!((X1
<= X
) || (X
<= Zero
)));
1289 if ((X1
!= Y1
) || (X1
!= Z1
))
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");
1301 if ((Z1
!= U1
) || (Z2
!= U2
))
1303 if ((Z1
>= U1
) || (Z2
>= U2
))
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());
1312 if ((Z1
<= Zero
) || (Z2
<= Zero
))
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");
1319 if (Z1
!= Z2
|| Z1
> Zero
)
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());
1334 ("That feature is not tested further by this program.\n");
1339 /*=============================================*/
1341 /*=============================================*/
1344 X
= W
/ (Radix
* Radix
);
1349 TstCond (Failure
, X
== U2
,
1350 "Subtraction is not normalized X=Y,X+Z != Y+Z!");
1352 printf ("Subtraction appears to be normalized, as it should be.");
1354 printf ("\nChecking for guard digit in *, /, and -.\n");
1367 X
= X
* (Radix
- One
);
1368 T
= T
* (Radix
- One
);
1369 if ((X
== Zero
) && (Y
== Zero
) && (Z
== Zero
) && (T
== Zero
))
1374 TstCond (Serious
, false, "* lacks a Guard Digit, so 1*X != X");
1378 Y
= FABS ((X
+ Z
) - X
* X
) - U2
;
1380 Z
= FABS ((X
- U2
) - X
* X
) - U1
;
1381 TstCond (Failure
, (Y
<= Zero
)
1382 && (Z
<= Zero
), "* gets too many final digits wrong.\n");
1390 T
= Nine
/ TwentySeven
;
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");
1401 if ((X
== Zero
) && (Y
== Zero
) && (Z
== Zero
))
1406 TstCond (Serious
, false, "Division lacks a Guard Digit, so X/1 != X");
1408 X
= One
/ (One
+ U2
);
1409 Y
= X
- Half
- Half
;
1410 TstCond (Serious
, Y
< Zero
, "Computed value of 1/1.000..1 >= 1");
1412 Y
= One
+ Radix
* U2
;
1416 StickyBit
= T
/ Radix
;
1419 TstCond (Failure
, X
== Zero
&& Y
== Zero
,
1420 "* and/or / gets too many last digits wrong");
1425 Z
= Radix
- BMinusU2
;
1427 if ((X
== U1
) && (Y
== U1
) && (Z
== U2
) && (T
== U2
))
1432 TstCond (Serious
, false,
1433 "- lacks Guard Digit, so cancellation is obscured");
1435 if (F9
!= One
&& F9
- One
>= Zero
)
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");
1442 if (GMult
== Yes
&& GDiv
== Yes
&& GAddSub
== Yes
)
1444 (" *, /, and - appear to have guard digits, as they should.\n");
1445 /*=============================================*/
1447 /*=============================================*/
1449 printf ("Checking rounding on multiply, divide and add/subtract.\n");
1453 RadixD2
= Radix
/ Two
;
1462 AInvrse
= AInvrse
/ A1
;
1464 while (!(FLOOR (AInvrse
) != AInvrse
));
1465 Done
= (X
== One
) || (A1
> Three
);
1479 TstCond (Failure
, Z
== Half
, "X * (1/X) differs from 1");
1487 X
= OneAndHalf
- U2
;
1488 Y
= OneAndHalf
+ U2
;
1497 if ((X
== Zero
) && (Y
== Zero
) && (Z
== Zero
) && (T
<= Zero
))
1499 X
= (OneAndHalf
+ U2
) * Y2
;
1500 Y
= OneAndHalf
- U2
- U2
;
1501 Z
= OneAndHalf
+ U2
+ U2
;
1502 T
= (OneAndHalf
- U2
) * Y1
;
1507 Y
= (U2
- Y
) + StickyBit
;
1508 Z
= S
- (Z
+ U2
+ U2
);
1509 StickyBit
= (Y2
+ U2
) * Y1
;
1511 StickyBit
= StickyBit
- Y2
;
1513 if ((X
== Zero
) && (Y
== Zero
) && (Z
== Zero
) && (T
== Zero
)
1514 && (StickyBit
== Zero
) && (Y1
== Half
))
1517 printf ("Multiplication appears to round correctly.\n");
1519 else if ((X
+ U2
== Zero
) && (Y
< Zero
) && (Z
+ U2
== Zero
)
1520 && (T
< Zero
) && (StickyBit
+ U2
== Zero
) && (Y1
< Half
))
1523 printf ("Multiplication appears to chop.\n");
1526 printf ("* is neither chopped nor correctly rounded.\n");
1527 if ((RMult
== Rounded
) && (GMult
== No
))
1528 notify ("Multiplication");
1531 printf ("* is neither chopped nor correctly rounded.\n");
1532 /*=============================================*/
1534 /*=============================================*/
1537 Z
= OneAndHalf
+ U2
+ U2
;
1539 T
= OneAndHalf
- U2
- U2
;
1545 Z
= Z
- (OneAndHalf
+ U2
);
1546 T
= (U2
- OneAndHalf
) + T
;
1547 if (!((X
> Zero
) || (Y
> Zero
) || (Z
> Zero
) || (T
> Zero
)))
1549 X
= OneAndHalf
/ Y2
;
1550 Y
= OneAndHalf
- U2
;
1551 Z
= OneAndHalf
+ U2
;
1553 T
= OneAndHalf
/ Y1
;
1558 Y1
= (Y2
+ U2
) / 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
))
1566 printf ("Division appears to round correctly.\n");
1568 notify ("Division");
1570 else if ((X
< Zero
) && (Y
< Zero
) && (Z
< Zero
) && (T
< Zero
)
1571 && (Y2
< Zero
) && (Y1
- Half
< F9
- Half
))
1574 printf ("Division appears to chop.\n");
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 /*=============================================*/
1584 /*=============================================*/
1585 TstCond (Failure
, ((F9
+ U1
) - Half
== Half
)
1586 && ((BMinusU2
+ U2
) - One
== Radix
- One
),
1587 "Incomplete carry-propagation in Addition");
1589 Y
= One
+ U2
* (One
- U2
);
1593 if ((X
== Zero
) && (Y
== Zero
))
1596 printf ("Add/Subtract appears to be chopped.\n");
1600 X
= (Half
+ U2
) * U2
;
1601 Y
= (Half
- U2
) * U2
;
1606 if ((X
== Zero
) && (Y
== Zero
))
1608 X
= (Half
+ U2
) * U1
;
1609 Y
= (Half
- U2
) * U1
;
1614 if ((X
== Zero
) && (Y
== Zero
))
1617 printf ("Addition/Subtraction appears to round correctly.\n");
1619 notify ("Add/Subtract");
1622 printf ("Addition/Subtraction neither rounds nor chops.\n");
1625 printf ("Addition/Subtraction neither rounds nor chops.\n");
1628 printf ("Addition/Subtraction neither rounds nor chops.\n");
1630 X
= One
+ Half
* (One
+ Half
);
1631 Y
= (One
+ U2
) * Half
;
1635 if (StickyBit
!= Zero
)
1638 BadCond (Flaw
, "(X - Y) + (Y - X) is non zero!\n");
1641 if ((GMult
== Yes
) && (GDiv
== Yes
) && (GAddSub
== Yes
)
1642 && (RMult
== Rounded
) && (RDiv
== Rounded
)
1643 && (RAddSub
== Rounded
) && (FLOOR (RadixD2
) == RadixD2
))
1645 printf ("Checking for sticky bit.\n");
1646 X
= (Half
+ U1
) * U2
;
1650 if ((Z
- One
<= Zero
) && (T
- One
>= U2
))
1654 if ((Z
- T
>= U2
) && (Y
- T
== Zero
))
1656 X
= (Half
+ U1
) * U1
;
1660 if ((Z
- One
== Zero
) && (T
- F9
== Zero
))
1662 Z
= (Half
- U1
) * U1
;
1665 if ((T
- F9
== Zero
) && (F9
- U1
- Q
== Zero
))
1667 Z
= (One
+ U2
) * OneAndHalf
;
1668 T
= (OneAndHalf
+ U2
) - Z
+ U2
;
1669 X
= One
+ Half
/ Radix
;
1670 Y
= One
+ Radix
* U2
;
1672 if (T
== Zero
&& X
+ Radix
* U2
- Z
== Zero
)
1678 if ((Y
- One
== Zero
))
1689 if (StickyBit
== One
)
1690 printf ("Sticky bit apparently used correctly.\n");
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 /*=============================================*/
1699 /*=============================================*/
1701 printf ("Does Multiplication commute? ");
1702 printf ("Testing on %d random pairs.\n", NoTrials
);
1703 Random9
= SQRT (FLOAT (3));
1715 while (!((I
> NoTrials
) || (Z9
!= Zero
)));
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
) +
1726 if (!((I
== NoTrials
) || (Z9
== Zero
)))
1727 BadCond (Defect
, "X * Y == Y * X trial fails.\n");
1729 printf (" No failures found in %d integer pairs.\n", NoTrials
);
1730 /*=============================================*/
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");
1744 OneUlp
= BInvrse
* U1
;
1751 printf ("Testing if sqrt(X * X) == X for %d Integers X.\n", NoTrials
);
1761 while (!((Y
- X
>= NoTrials
)));
1764 while (I
<= NoTrials
)
1772 printf ("Test for sqrt monotonicity.\n");
1776 Z
= Radix
+ Radix
* U2
;
1779 while (!(NotMonot
|| Monot
))
1785 if ((X
> Q
) || (Q
> Z
))
1789 Q
= FLOOR (Q
+ Half
);
1790 if (!(I
> 0 || Radix
== Q
* Q
))
1812 printf ("sqrt has passed a test for Monotonicity.\n");
1815 BadCond (Defect
, "");
1816 printf ("sqrt(X) is non-monotonic for X near %s .\n", Y
.str());
1818 /*=============================================*/
1820 /*=============================================*/
1821 printf ("Seeking Underflow thresholds UfThold and E0.\n");
1823 if (Precision
!= FLOOR (Precision
))
1836 /* ... D is power of 1/Radix < 1. */
1843 while ((Y
> Z
) && (Z
+ Z
> Z
));
1852 while ((Y
> Z
) && (Z
+ Z
> Z
));
1858 /* ... 1/HInvrse == H == Min(1/Radix, 1/2) */
1862 /* ...1/Radix^(BIG Integer) << 1 << CInvrse == 1/C */
1869 while ((E0
> Z
) && (Z
+ Z
> Z
));
1884 "multiplication gets too many last digits wrong.\n");
1894 PseudoZero
= Underflow
* H
;
1899 Underflow
= PseudoZero
;
1902 Y2
= Underflow
* HInvrse
;
1903 E1
= FABS (Y1
- Y2
);
1905 if ((UfThold
== Zero
) && (Y1
!= Y2
))
1908 PseudoZero
= PseudoZero
* H
;
1910 while ((Underflow
> PseudoZero
)
1911 && (PseudoZero
+ PseudoZero
> PseudoZero
));
1913 /* Comment line 4530 .. 4560 */
1914 if (PseudoZero
!= Zero
)
1918 /* ... Test PseudoZero for "phoney- zero" violates */
1919 /* ... PseudoZero < Underflow or PseudoZero < PseudoZero + PseudoZero
1921 if (PseudoZero
<= Zero
)
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());
1929 printf ("But -PseudoZero, which should be\n");
1930 printf ("positive, isn't; it prints out as %s .\n", X
.str());
1935 BadCond (Flaw
, "Underflow can stick at an allegedly positive\n");
1936 printf ("value PseudoZero that prints out as %s .\n",
1941 /*=============================================*/
1943 /*=============================================*/
1944 if (CInvrse
* Y
> CInvrse
* Y1
)
1949 if (!((E1
== Zero
) || (E1
== E0
)))
1951 BadCond (Defect
, "");
1954 printf ("Products underflow at a higher");
1955 printf (" threshold than differences.\n");
1956 if (PseudoZero
== Zero
)
1961 printf ("Difference underflows at a higher");
1962 printf (" threshold than products.\n");
1965 printf ("Smallest strictly positive number found is E0 = %s .\n", E0
.str());
1974 if (UfThold
== Zero
)
1980 UfThold
= Underflow
;
1981 if ((CInvrse
* Q
) != ((CInvrse
* Y
) * S
))
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());
1988 (" or else multiplication gets too many last digits wrong.\n");
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());
2007 if ((Q
== UfThold
) && (E1
== E0
) && (FABS (UfThold
- E1
/ E9
) <= E1
))
2010 printf ("Underflow is gradual; it incurs Absolute Error =\n");
2011 printf ("(roundoff in UfThold) < E0.\n");
2013 Y
= Y
* (OneAndHalf
+ U2
);
2014 X
= CInvrse
* (One
+ U2
);
2022 if (setjmp (ovfl_buf
))
2024 printf ("Underflow / UfThold failed!\n");
2028 R
= SQRT (Underflow
/ UfThold
);
2032 X
= Z
* (One
+ R
* H
* (One
+ H
));
2037 X
= Z
* (One
+ H
* H
* (One
+ H
));
2039 if (!((X
== Z
) || (X
- Z
!= Zero
)))
2042 printf ("X = %s\n\tis not equal to Z = %s .\n", X
.str(), Z
.str());
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");
2054 printf ("X / Z = 1 + %s .\n", ((X
/ Z
- Half
) - Half
).str());
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");
2067 BadCond (Defect
, "");
2072 BadCond (Serious
, "");
2075 printf ("Range is too narrow; U1^%d Underflows.\n", I
);
2077 /*=============================================*/
2079 /*=============================================*/
2080 Y
= -FLOOR (Half
- TwoForty
* LOG (UfThold
) / LOG (HInvrse
)) / TwoForty
;
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
))
2089 BadCond (Serious
, "trap on underflow.\n");
2093 V9
= POW (HInvrse
, Y2
);
2094 printf (" %s .\n", V9
.str());
2095 if (!((V9
>= Zero
) && (V9
<= (Radix
+ Radix
+ E9
) * UfThold
)))
2097 BadCond (Serious
, "this is not between 0 and underflow\n");
2098 printf (" threshold = %s .\n", UfThold
.str());
2100 else if (!(V9
> UfThold
* (One
+ E9
)))
2101 printf ("This computed value is O.K.\n");
2104 BadCond (Defect
, "this is not between 0 and underflow\n");
2105 printf (" threshold = %s .\n", UfThold
.str());
2108 /*=============================================*/
2110 /*=============================================*/
2112 printf ("Searching for Overflow threshold:\n");
2113 printf ("This may generate an error.\n");
2116 if (setjmp (ovfl_buf
))
2132 printf ("Can `Z = -Y' overflow?\n");
2133 printf ("Trying it on Y = %s .\n", Y
.str());
2136 if (V
- Y
== V
+ V0
)
2137 printf ("Seems O.K.\n");
2140 printf ("finds a ");
2141 BadCond (Flaw
, "-(-Y) differs from Y.\n");
2145 BadCond (Serious
, "");
2146 printf ("overflow past %s\n\tshrinks to %s .\n", Y
.str(), Z
.str());
2150 Y
= V
* (HInvrse
* U2
- HInvrse
);
2151 Z
= Y
+ ((One
- HInvrse
) * U2
) * V
;
2161 V
= Y
* (HInvrse
* U2
- HInvrse
);
2162 V
= V
+ ((One
- HInvrse
) * U2
) * Y
;
2164 printf ("Overflow threshold is V = %s .\n", V
.str());
2166 printf ("Overflow saturates at V0 = %s .\n", V0
.str());
2168 printf ("There is no saturation value because "
2169 "the system traps on overflow.\n");
2171 printf ("No Overflow should be signaled for V * 1 = %s\n", V9
.str());
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 /*=============================================*/
2178 /*=============================================*/
2179 if (!(-V
< V
&& -V0
< V0
&& -UfThold
< V
&& UfThold
< V
))
2181 BadCond (Failure
, "Comparisons involving ");
2182 printf ("+-%s, +-%s\nand +-%s are confused by Overflow.",
2183 V
.str(), V0
.str(), UfThold
.str());
2185 /*=============================================*/
2187 /*=============================================*/
2189 for (Indx
= 1; Indx
<= 3; ++Indx
)
2207 if (Y
/ (One
- Radix
* E9
) < Z
|| Y
> (One
+ Radix
* E9
) * Z
)
2208 { /* dgh: + E9 --> * E9 */
2210 BadCond (Serious
, "");
2212 BadCond (Defect
, "");
2213 printf ("Comparison alleges that what prints as Z = %s\n",
2215 printf (" is too far from sqrt(Z) ^ 2 = %s .\n", Y
.str());
2219 /*=============================================*/
2221 /*=============================================*/
2222 for (Indx
= 1; Indx
<= 2; ++Indx
)
2229 X
= (One
- Radix
* E9
) * V9
;
2231 if (((V9
< (One
- Two
* Radix
* E9
) * Z
) || (V9
> Z
)))
2235 BadCond (Serious
, "");
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());
2242 /*=============================================*/
2244 /*=============================================*/
2248 if (X
* Y
< One
|| X
> Y
)
2250 if (X
* Y
< U1
|| X
> Y
/ U1
)
2251 BadCond (Defect
, "Badly");
2255 printf (" unbalanced range; UfThold * V = %s\n\t%s\n",
2256 X
.str(), "is too far from 1.\n");
2258 /*=============================================*/
2260 /*=============================================*/
2261 for (Indx
= 1; Indx
<= 5; ++Indx
)
2279 if (setjmp (ovfl_buf
))
2280 printf (" X / X traps when X = %s\n", X
.str());
2283 V9
= (Y
/ X
- Half
) - Half
;
2286 if (V9
== -U1
&& Indx
< 5)
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());
2294 /*=============================================*/
2296 /*=============================================*/
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 /*=============================================*/
2308 /*=============================================*/
2312 static const char *msg
[] = {
2313 "FAILUREs encountered =",
2314 "SERIOUS DEFECTs discovered =",
2315 "DEFECTs discovered =",
2316 "FLAWs discovered ="
2319 for (i
= 0; i
< 4; i
++)
2321 printf ("The number of %-29s %d.\n", msg
[i
], ErrCnt
[i
]);
2324 if ((ErrCnt
[Failure
] + ErrCnt
[Serious
] + ErrCnt
[Defect
] + ErrCnt
[Flaw
]) > 0)
2326 if ((ErrCnt
[Failure
] + ErrCnt
[Serious
] + ErrCnt
[Defect
] == 0)
2327 && (ErrCnt
[Flaw
] > 0))
2329 printf ("The arithmetic diagnosed seems ");
2330 printf ("Satisfactory though flawed.\n");
2332 if ((ErrCnt
[Failure
] + ErrCnt
[Serious
] == 0) && (ErrCnt
[Defect
] > 0))
2334 printf ("The arithmetic diagnosed may be Acceptable\n");
2335 printf ("despite inconvenient Defects.\n");
2337 if ((ErrCnt
[Failure
] + ErrCnt
[Serious
]) > 0)
2339 printf ("The arithmetic diagnosed has ");
2340 printf ("unacceptable Serious Defects.\n");
2342 if (ErrCnt
[Failure
] > 0)
2344 printf ("Potentially fatal FAILURE may have spoiled this");
2345 printf (" program's subsequent diagnoses.\n");
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");
2356 if (StickyBit
>= One
&&
2357 (Radix
- Two
) * (Radix
- Nine
- One
) == Zero
)
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
))
2371 printf (",\nexcept for possibly Double Rounding");
2372 printf (" during Gradual Underflow.\n");
2375 printf ("The arithmetic diagnosed appears to be Excellent!\n");
2378 printf ("END OF TEST.\n");
2382 template<typename FLOAT
>
2384 Paranoia
<FLOAT
>::Sign (FLOAT X
)
2386 return X
>= FLOAT (long (0)) ? 1 : -1;
2389 template<typename FLOAT
>
2391 Paranoia
<FLOAT
>::Pause ()
2395 fputs ("Press return...", stdout
);
2399 printf ("\nDiagnosis resumes after milestone Number %d", Milestone
);
2400 printf (" Page: %d\n\n", PageNo
);
2405 template<typename FLOAT
>
2407 Paranoia
<FLOAT
>::TstCond (int K
, int Valid
, const char *T
)
2416 template<typename FLOAT
>
2418 Paranoia
<FLOAT
>::BadCond (int K
, const char *T
)
2420 static const char *msg
[] = { "FAILURE", "SERIOUS DEFECT", "DEFECT", "FLAW" };
2422 ErrCnt
[K
] = ErrCnt
[K
] + 1;
2423 printf ("%s: %s", msg
[K
], T
);
2427 X = (Random1 + Random9)^5
2428 Random1 = X - FLOOR(X) + 0.000005 * X;
2429 and returns the new value of Random1. */
2431 template<typename FLOAT
>
2433 Paranoia
<FLOAT
>::Random ()
2437 X
= Random1
+ Random9
;
2442 Random1
= Y
+ X
* FLOAT ("0.000005");
2446 template<typename FLOAT
>
2448 Paranoia
<FLOAT
>::SqXMinX (int ErrKind
)
2454 SqEr
= ((SQRT (X
* X
) - XB
) - XA
) / OneUlp
;
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");
2469 template<typename FLOAT
>
2471 Paranoia
<FLOAT
>::NewD ()
2474 X
= FLOOR (Half
- X
/ Radix
) * Radix
+ X
;
2475 Q
= (Q
- X
* Z
) / Radix
+ X
* X
* (D
/ Radix
);
2476 Z
= Z
- Two
* X
* D
;
2485 template<typename FLOAT
>
2487 Paranoia
<FLOAT
>::SR3750 ()
2489 if (!((X
- Radix
< Z2
- Radix
) || (X
- Z2
> W
- Z2
)))
2493 Y2
= (X2
- Z2
) - (Y
- Z2
);
2494 X2
= X8
/ (Y
- Half
);
2495 X2
= X2
- Half
* X2
* X2
;
2496 SqEr
= (Y2
+ Half
) + (Half
- X2
);
2505 template<typename FLOAT
>
2507 Paranoia
<FLOAT
>::IsYeqX ()
2513 if (Z
== Zero
&& Q
<= Zero
)
2514 printf ("WARNING: computing\n");
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());
2522 N
= N
+ 1; /* ... count discrepancies. */
2526 template<typename FLOAT
>
2528 Paranoia
<FLOAT
>::PrintIfNPositive ()
2531 printf ("Similar discrepancies have occurred %d times.\n", N
);
2534 template<typename FLOAT
>
2536 Paranoia
<FLOAT
>::TstPtUf ()
2541 printf ("Since comparison denies Z = 0, evaluating ");
2542 printf ("(Z + Z) / Z should be safe.\n");
2543 if (setjmp (ovfl_buf
))
2546 printf ("What the machine gets for (Z + Z) / Z is %s .\n", Q9
.str());
2547 if (FABS (Q9
- Two
) < Radix
* U2
)
2549 printf ("This is O.K., provided Over/Underflow");
2550 printf (" has NOT just been signaled.\n");
2554 if ((Q9
< One
) || (Q9
> Two
))
2558 ErrCnt
[Serious
] = ErrCnt
[Serious
] + 1;
2559 printf ("This is a VERY SERIOUS DEFECT!\n");
2564 ErrCnt
[Defect
] = ErrCnt
[Defect
] + 1;
2565 printf ("This is a DEFECT!\n");
2573 if ((Z
== Random1
) && (Z
== Random2
) && (Z
== V9
))
2581 BadCond (Defect
, "What prints as Z = ");
2582 printf ("%s\n\tcompares different from ", Z
.str());
2584 printf ("Z * 1 = %s ", Random1
.str());
2585 if (!((Z
== Random2
) || (Random2
== Random1
)))
2586 printf ("1 * Z == %s\n", Random2
.str());
2588 printf ("Z / 1 = %s\n", V9
.str());
2589 if (Random2
!= Random1
)
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());
2601 template<typename FLOAT
>
2603 Paranoia
<FLOAT
>::notify (const char *s
)
2605 printf ("%s test appears to be inconsistent...\n", s
);
2606 printf (" PLEASE NOTIFY KARPINKSI!\n");
2609 /* ====================================================================== */
2611 int main(int ac
, char **av
)
2613 setbuf(stdout
, NULL
);
2614 setbuf(stderr
, NULL
);
2617 switch (getopt (ac
, av
, "pvg:fdl"))
2629 static const struct {
2631 const struct real_format
*fmt
;
2633 #define F(x) { #x, &x##_format }
2636 F(ieee_extended_motorola
),
2637 F(ieee_extended_intel_96
),
2638 F(ieee_extended_intel_128
),
2650 int i
, n
= sizeof (fmts
)/sizeof(*fmts
);
2652 for (i
= 0; i
< n
; ++i
)
2653 if (strcmp (fmts
[i
].name
, optarg
) == 0)
2658 printf ("Unknown implementation \"%s\"; "
2659 "available implementations:\n", optarg
);
2660 for (i
= 0; i
< n
; ++i
)
2661 printf ("\t%s\n", fmts
[i
].name
);
2665 // We cheat and use the same mode all the time, but vary
2666 // the format used for that mode.
2667 real_format_for_mode
[int(real_c_float::MODE
) - int(QFmode
)]
2670 Paranoia
<real_c_float
>().main();
2675 Paranoia
< native_float
<float> >().main();
2678 Paranoia
< native_float
<double> >().main();
2681 #ifndef NO_LONG_DOUBLE
2682 Paranoia
< native_float
<long double> >().main();
2687 puts ("-p\tpause between pages");
2688 puts ("-g<FMT>\treal.c implementation FMT");
2689 puts ("-f\tnative float");
2690 puts ("-d\tnative double");
2691 puts ("-l\tnative long double");
2696 /* GCC stuff referenced by real.o. */
2704 int target_flags
= 0;
2707 floor_log2_wide (unsigned HOST_WIDE_INT x
)