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
179 /* We never produce signals from the library. Thus setjmp need do nothing. */
181 #define setjmp(x) (0)
183 static bool verbose
= false;
184 static int verbose_index
= 0;
186 /* ====================================================================== */
187 /* The implementation of the abstract floating point class based on gcc's
188 real.cc. I.e. the object of this exercise. Templated so that we can
194 static const enum machine_mode MODE
= SFmode
;
197 static const int external_max
= 128 / 32;
198 static const int internal_max
199 = (sizeof (REAL_VALUE_TYPE
) + sizeof (long) + 1) / sizeof (long);
200 long image
[external_max
< internal_max
? internal_max
: external_max
];
202 void from_long(long);
203 void from_str(const char *);
204 void binop(int code
, const real_c_float
&);
206 bool cmp(int code
, const real_c_float
&) const;
213 real_c_float(const char *s
)
215 real_c_float(const real_c_float
&b
)
216 { memcpy(image
, b
.image
, sizeof(image
)); }
218 const real_c_float
& operator= (long l
)
219 { from_long(l
); return *this; }
220 const real_c_float
& operator= (const char *s
)
221 { from_str(s
); return *this; }
222 const real_c_float
& operator= (const real_c_float
&b
)
223 { memcpy(image
, b
.image
, sizeof(image
)); return *this; }
225 const real_c_float
& operator+= (const real_c_float
&b
)
226 { binop(PLUS_EXPR
, b
); return *this; }
227 const real_c_float
& operator-= (const real_c_float
&b
)
228 { binop(MINUS_EXPR
, b
); return *this; }
229 const real_c_float
& operator*= (const real_c_float
&b
)
230 { binop(MULT_EXPR
, b
); return *this; }
231 const real_c_float
& operator/= (const real_c_float
&b
)
232 { binop(RDIV_EXPR
, b
); return *this; }
234 real_c_float
operator- () const
235 { real_c_float
r(*this); r
.unop(NEGATE_EXPR
); return r
; }
236 real_c_float
abs () const
237 { real_c_float
r(*this); r
.unop(ABS_EXPR
); return r
; }
239 bool operator < (const real_c_float
&b
) const { return cmp(LT_EXPR
, b
); }
240 bool operator <= (const real_c_float
&b
) const { return cmp(LE_EXPR
, b
); }
241 bool operator == (const real_c_float
&b
) const { return cmp(EQ_EXPR
, b
); }
242 bool operator != (const real_c_float
&b
) const { return cmp(NE_EXPR
, b
); }
243 bool operator >= (const real_c_float
&b
) const { return cmp(GE_EXPR
, b
); }
244 bool operator > (const real_c_float
&b
) const { return cmp(GT_EXPR
, b
); }
246 const char * str () const;
247 const char * hex () const;
248 long integer () const;
254 real_c_float::from_long (long l
)
258 real_from_integer (&f
, MODE
, l
, l
< 0 ? -1 : 0, 0);
259 real_to_target (image
, &f
, MODE
);
263 real_c_float::from_str (const char *s
)
268 if (*p
== '-' || *p
== '+')
270 if (strcasecmp(p
, "inf") == 0)
274 real_arithmetic (&f
, NEGATE_EXPR
, &f
, NULL
);
276 else if (strcasecmp(p
, "nan") == 0)
277 real_nan (&f
, "", 1, MODE
);
279 real_from_string (&f
, s
);
281 real_to_target (image
, &f
, MODE
);
285 real_c_float::binop (int code
, const real_c_float
&b
)
287 REAL_VALUE_TYPE ai
, bi
, ri
;
289 real_from_target (&ai
, image
, MODE
);
290 real_from_target (&bi
, b
.image
, MODE
);
291 real_arithmetic (&ri
, code
, &ai
, &bi
);
292 real_to_target (image
, &ri
, MODE
);
296 char ab
[64], bb
[64], rb
[64];
297 const real_format
*fmt
= real_format_for_mode
[MODE
- QFmode
];
298 const int digits
= (fmt
->p
* fmt
->log2_b
+ 3) / 4;
299 char symbol_for_code
;
301 real_from_target (&ri
, image
, MODE
);
302 real_to_hexadecimal (ab
, &ai
, sizeof(ab
), digits
, 0);
303 real_to_hexadecimal (bb
, &bi
, sizeof(bb
), digits
, 0);
304 real_to_hexadecimal (rb
, &ri
, sizeof(rb
), digits
, 0);
309 symbol_for_code
= '+';
312 symbol_for_code
= '-';
315 symbol_for_code
= '*';
318 symbol_for_code
= '/';
324 fprintf (stderr
, "%6d: %s %c %s = %s\n", verbose_index
++,
325 ab
, symbol_for_code
, bb
, rb
);
330 real_c_float::unop (int code
)
332 REAL_VALUE_TYPE ai
, ri
;
334 real_from_target (&ai
, image
, MODE
);
335 real_arithmetic (&ri
, code
, &ai
, NULL
);
336 real_to_target (image
, &ri
, MODE
);
341 const real_format
*fmt
= real_format_for_mode
[MODE
- QFmode
];
342 const int digits
= (fmt
->p
* fmt
->log2_b
+ 3) / 4;
343 const char *symbol_for_code
;
345 real_from_target (&ri
, image
, MODE
);
346 real_to_hexadecimal (ab
, &ai
, sizeof(ab
), digits
, 0);
347 real_to_hexadecimal (rb
, &ri
, sizeof(rb
), digits
, 0);
352 symbol_for_code
= "-";
355 symbol_for_code
= "abs ";
361 fprintf (stderr
, "%6d: %s%s = %s\n", verbose_index
++,
362 symbol_for_code
, ab
, rb
);
367 real_c_float::cmp (int code
, const real_c_float
&b
) const
369 REAL_VALUE_TYPE ai
, bi
;
372 real_from_target (&ai
, image
, MODE
);
373 real_from_target (&bi
, b
.image
, MODE
);
374 ret
= real_compare (code
, &ai
, &bi
);
379 const real_format
*fmt
= real_format_for_mode
[MODE
- QFmode
];
380 const int digits
= (fmt
->p
* fmt
->log2_b
+ 3) / 4;
381 const char *symbol_for_code
;
383 real_to_hexadecimal (ab
, &ai
, sizeof(ab
), digits
, 0);
384 real_to_hexadecimal (bb
, &bi
, sizeof(bb
), digits
, 0);
389 symbol_for_code
= "<";
392 symbol_for_code
= "<=";
395 symbol_for_code
= "==";
398 symbol_for_code
= "!=";
401 symbol_for_code
= ">=";
404 symbol_for_code
= ">";
410 fprintf (stderr
, "%6d: %s %s %s = %s\n", verbose_index
++,
411 ab
, symbol_for_code
, bb
, (ret
? "true" : "false"));
418 real_c_float::str() const
421 const real_format
*fmt
= real_format_for_mode
[MODE
- QFmode
];
422 const int digits
= int(fmt
->p
* fmt
->log2_b
* .30102999566398119521 + 1);
424 real_from_target (&f
, image
, MODE
);
425 char *buf
= new char[digits
+ 10];
426 real_to_decimal (buf
, &f
, digits
+10, digits
, 0);
432 real_c_float::hex() const
435 const real_format
*fmt
= real_format_for_mode
[MODE
- QFmode
];
436 const int digits
= (fmt
->p
* fmt
->log2_b
+ 3) / 4;
438 real_from_target (&f
, image
, MODE
);
439 char *buf
= new char[digits
+ 10];
440 real_to_hexadecimal (buf
, &f
, digits
+10, digits
, 0);
446 real_c_float::integer() const
449 real_from_target (&f
, image
, MODE
);
450 return real_to_integer (&f
);
454 real_c_float::exp() const
457 real_from_target (&f
, image
, MODE
);
458 return real_exponent (&f
);
462 real_c_float::ldexp (int exp
)
466 real_from_target (&ai
, image
, MODE
);
467 real_ldexp (&ai
, &ai
, exp
);
468 real_to_target (image
, &ai
, MODE
);
471 /* ====================================================================== */
472 /* An implementation of the abstract floating point class that uses native
473 arithmetic. Exists for reference and debugging. */
479 // Force intermediate results back to memory.
482 static T
from_str (const char *);
484 static T
verbose_binop (T
, char, T
, T
);
485 static T
verbose_unop (const char *, T
, T
);
486 static bool verbose_cmp (T
, const char *, T
, bool);
493 native_float(const char *s
)
494 { image
= from_str(s
); }
495 native_float(const native_float
&b
)
498 const native_float
& operator= (long l
)
499 { image
= l
; return *this; }
500 const native_float
& operator= (const char *s
)
501 { image
= from_str(s
); return *this; }
502 const native_float
& operator= (const native_float
&b
)
503 { image
= b
.image
; return *this; }
505 const native_float
& operator+= (const native_float
&b
)
507 image
= verbose_binop(image
, '+', b
.image
, image
+ b
.image
);
510 const native_float
& operator-= (const native_float
&b
)
512 image
= verbose_binop(image
, '-', b
.image
, image
- b
.image
);
515 const native_float
& operator*= (const native_float
&b
)
517 image
= verbose_binop(image
, '*', b
.image
, image
* b
.image
);
520 const native_float
& operator/= (const native_float
&b
)
522 image
= verbose_binop(image
, '/', b
.image
, image
/ b
.image
);
526 native_float
operator- () const
529 r
.image
= verbose_unop("-", image
, -image
);
532 native_float
abs () const
535 r
.image
= verbose_unop("abs ", image
, do_abs(image
));
539 bool operator < (const native_float
&b
) const
540 { return verbose_cmp(image
, "<", b
.image
, image
< b
.image
); }
541 bool operator <= (const native_float
&b
) const
542 { return verbose_cmp(image
, "<=", b
.image
, image
<= b
.image
); }
543 bool operator == (const native_float
&b
) const
544 { return verbose_cmp(image
, "==", b
.image
, image
== b
.image
); }
545 bool operator != (const native_float
&b
) const
546 { return verbose_cmp(image
, "!=", b
.image
, image
!= b
.image
); }
547 bool operator >= (const native_float
&b
) const
548 { return verbose_cmp(image
, ">=", b
.image
, image
>= b
.image
); }
549 bool operator > (const native_float
&b
) const
550 { return verbose_cmp(image
, ">", b
.image
, image
> b
.image
); }
552 const char * str () const;
553 const char * hex () const;
554 long integer () const
555 { return long(image
); }
562 native_float
<T
>::from_str (const char *s
)
564 return strtold (s
, NULL
);
569 native_float
<float>::from_str (const char *s
)
571 return strtof (s
, NULL
);
576 native_float
<double>::from_str (const char *s
)
578 return strtod (s
, NULL
);
583 native_float
<T
>::do_abs (T image
)
585 return fabsl (image
);
590 native_float
<float>::do_abs (float image
)
592 return fabsf (image
);
597 native_float
<double>::do_abs (double image
)
604 native_float
<T
>::verbose_binop (T a
, char symbol
, T b
, T r
)
608 const int digits
= int(sizeof(T
) * CHAR_BIT
/ 4) - 1;
609 #ifdef NO_LONG_DOUBLE
610 fprintf (stderr
, "%6d: %.*a %c %.*a = %.*a\n", verbose_index
++,
611 digits
, (double)a
, symbol
,
612 digits
, (double)b
, digits
, (double)r
);
614 fprintf (stderr
, "%6d: %.*La %c %.*La = %.*La\n", verbose_index
++,
615 digits
, (long double)a
, symbol
,
616 digits
, (long double)b
, digits
, (long double)r
);
624 native_float
<T
>::verbose_unop (const char *symbol
, T a
, T r
)
628 const int digits
= int(sizeof(T
) * CHAR_BIT
/ 4) - 1;
629 #ifdef NO_LONG_DOUBLE
630 fprintf (stderr
, "%6d: %s%.*a = %.*a\n", verbose_index
++,
631 symbol
, digits
, (double)a
, digits
, (double)r
);
633 fprintf (stderr
, "%6d: %s%.*La = %.*La\n", verbose_index
++,
634 symbol
, digits
, (long double)a
, digits
, (long double)r
);
642 native_float
<T
>::verbose_cmp (T a
, const char *symbol
, T b
, bool r
)
646 const int digits
= int(sizeof(T
) * CHAR_BIT
/ 4) - 1;
647 #ifndef NO_LONG_DOUBLE
648 fprintf (stderr
, "%6d: %.*a %s %.*a = %s\n", verbose_index
++,
649 digits
, (double)a
, symbol
,
650 digits
, (double)b
, (r
? "true" : "false"));
652 fprintf (stderr
, "%6d: %.*La %s %.*La = %s\n", verbose_index
++,
653 digits
, (long double)a
, symbol
,
654 digits
, (long double)b
, (r
? "true" : "false"));
662 native_float
<T
>::str() const
664 char *buf
= new char[50];
665 const int digits
= int(sizeof(T
) * CHAR_BIT
* .30102999566398119521 + 1);
666 #ifndef NO_LONG_DOUBLE
667 sprintf (buf
, "%.*e", digits
- 1, (double) image
);
669 sprintf (buf
, "%.*Le", digits
- 1, (long double) image
);
676 native_float
<T
>::hex() const
678 char *buf
= new char[50];
679 const int digits
= int(sizeof(T
) * CHAR_BIT
/ 4);
680 #ifndef NO_LONG_DOUBLE
681 sprintf (buf
, "%.*a", digits
- 1, (double) image
);
683 sprintf (buf
, "%.*La", digits
- 1, (long double) image
);
690 native_float
<T
>::exp() const
699 native_float
<T
>::ldexp (int exp
)
701 image
= ldexpl (image
, exp
);
706 native_float
<float>::ldexp (int exp
)
708 image
= ldexpf (image
, exp
);
713 native_float
<double>::ldexp (int exp
)
715 image
= ::ldexp (image
, exp
);
718 /* ====================================================================== */
719 /* Some libm routines that Paranoia expects to be available. */
721 template<typename FLOAT
>
723 FABS (const FLOAT
&f
)
728 template<typename FLOAT
, typename RHS
>
730 operator+ (const FLOAT
&a
, const RHS
&b
)
732 return FLOAT(a
) += FLOAT(b
);
735 template<typename FLOAT
, typename RHS
>
737 operator- (const FLOAT
&a
, const RHS
&b
)
739 return FLOAT(a
) -= FLOAT(b
);
742 template<typename FLOAT
, typename RHS
>
744 operator* (const FLOAT
&a
, const RHS
&b
)
746 return FLOAT(a
) *= FLOAT(b
);
749 template<typename FLOAT
, typename RHS
>
751 operator/ (const FLOAT
&a
, const RHS
&b
)
753 return FLOAT(a
) /= FLOAT(b
);
756 template<typename FLOAT
>
758 FLOOR (const FLOAT
&f
)
760 /* ??? This is only correct when F is representable as an integer. */
761 long i
= f
.integer();
771 template<typename FLOAT
>
773 SQRT (const FLOAT
&f
)
776 FLOAT zero
= long(0);
790 z
.ldexp (-f
.exp() / 2);
792 diff2
= FABS (z
* z
- f
);
796 t
= (f
/ (two
* z
)) + (z
/ two
);
797 diff
= FABS (t
* t
- f
);
805 #elif defined(NO_LONG_DOUBLE)
809 d
= strtod (f
.hex(), NULL
);
811 sprintf(buf
, "%.35a", d
);
818 ld
= strtold (f
.hex(), NULL
);
820 sprintf(buf
, "%.35La", ld
);
826 template<typename FLOAT
>
831 FLOAT zero
= long(0);
839 int exp
= x
.exp() - 1;
850 FLOAT term
= y
/ FLOAT (n
);
851 FLOAT next
= sum
+ term
;
860 sum
+= FLOAT (exp
) * FLOAT(".69314718055994530941");
863 #elif defined (NO_LONG_DOUBLE)
867 d
= strtod (x
.hex(), NULL
);
869 sprintf(buf
, "%.35a", d
);
876 ld
= strtold (x
.hex(), NULL
);
878 sprintf(buf
, "%.35La", ld
);
884 template<typename FLOAT
>
889 #ifdef NO_LONG_DOUBLE
893 d
= strtod (x
.hex(), NULL
);
895 sprintf(buf
, "%.35a", d
);
902 ld
= strtold (x
.hex(), NULL
);
904 sprintf(buf
, "%.35La", ld
);
910 template<typename FLOAT
>
912 POW (const FLOAT
&base
, const FLOAT
&exp
)
915 #ifdef NO_LONG_DOUBLE
919 d1
= strtod (base
.hex(), NULL
);
920 d2
= strtod (exp
.hex(), NULL
);
922 sprintf(buf
, "%.35a", d1
);
926 long double ld1
, ld2
;
929 ld1
= strtold (base
.hex(), NULL
);
930 ld2
= strtold (exp
.hex(), NULL
);
931 ld1
= powl (ld1
, ld2
);
932 sprintf(buf
, "%.35La", ld1
);
938 /* ====================================================================== */
939 /* Real Paranoia begins again here. We wrap the thing in a template so
940 that we can instantiate it for each floating point type we care for. */
942 int NoTrials
= 20; /*Number of tests for commutativity. */
943 bool do_pause
= false;
945 enum Guard
{ No
, Yes
};
946 enum Rounding
{ Other
, Rounded
, Chopped
};
947 enum Class
{ Failure
, Serious
, Defect
, Flaw
};
949 template<typename FLOAT
>
952 FLOAT Radix
, BInvrse
, RadixD2
, BMinusU2
;
954 /* Small floating point constants. */
970 /* Declarations of Variables. */
976 FLOAT E0
, E1
, Exp2
, E3
, MinSqEr
;
977 FLOAT SqEr
, MaxSqEr
, E9
;
987 FLOAT T
, Underflow
, S
;
988 FLOAT OneUlp
, UfThold
, U1
, U2
;
991 FLOAT X
, X1
, X2
, X8
, Random1
;
992 FLOAT Y
, Y1
, Y2
, Random2
;
993 FLOAT Z
, PseudoZero
, Z1
, Z2
, Z9
;
998 Guard GMult
, GDiv
, GAddSub
;
999 Rounding RMult
, RDiv
, RAddSub
, RSqrt
;
1000 int Break
, Done
, NotMonot
, Monot
, Anomaly
, IEEE
, SqRWrng
, UfNGrad
;
1002 /* Computed constants. */
1003 /*U1 gap below 1.0, i.e, 1.0-U1 is next number below 1.0 */
1004 /*U2 gap above 1.0, i.e, 1.0+U2 is next number above 1.0 */
1011 void BadCond (int, const char *);
1013 void TstCond (int, int, const char *);
1014 void notify (const char *);
1017 void PrintIfNPositive ();
1021 // Pretend we're bss.
1022 Paranoia() { memset(this, 0, sizeof (*this)); }
1025 template<typename FLOAT
>
1027 Paranoia
<FLOAT
>::main()
1029 /* First two assignments use integer right-hand sides. */
1038 TwentySeven
= long(27);
1039 ThirtyTwo
= long(32);
1040 TwoForty
= long(240);
1041 MinusOne
= long(-1);
1043 OneAndHalf
= "0x3p-1";
1044 ErrCnt
[Failure
] = 0;
1045 ErrCnt
[Serious
] = 0;
1049 /*=============================================*/
1051 /*=============================================*/
1052 printf ("Program is now RUNNING tests on small integers:\n");
1054 TstCond (Failure
, (Zero
+ Zero
== Zero
), "0+0 != 0");
1055 TstCond (Failure
, (One
- One
== Zero
), "1-1 != 0");
1056 TstCond (Failure
, (One
> Zero
), "1 <= 0");
1057 TstCond (Failure
, (One
+ One
== Two
), "1+1 != 2");
1062 ErrCnt
[Failure
] = ErrCnt
[Failure
] + 1;
1063 printf ("Comparison alleges that -0.0 is Non-zero!\n");
1069 TstCond (Failure
, (Three
== Two
+ One
), "3 != 2+1");
1070 TstCond (Failure
, (Four
== Three
+ One
), "4 != 3+1");
1071 TstCond (Failure
, (Four
+ Two
* (-Two
) == Zero
), "4 + 2*(-2) != 0");
1072 TstCond (Failure
, (Four
- Three
- One
== Zero
), "4-3-1 != 0");
1074 TstCond (Failure
, (MinusOne
== (Zero
- One
)), "-1 != 0-1");
1075 TstCond (Failure
, (MinusOne
+ One
== Zero
), "-1+1 != 0");
1076 TstCond (Failure
, (One
+ MinusOne
== Zero
), "1+(-1) != 0");
1077 TstCond (Failure
, (MinusOne
+ FABS (One
) == Zero
), "-1+abs(1) != 0");
1078 TstCond (Failure
, (MinusOne
+ MinusOne
* MinusOne
== Zero
),
1079 "-1+(-1)*(-1) != 0");
1081 TstCond (Failure
, Half
+ MinusOne
+ Half
== Zero
, "1/2 + (-1) + 1/2 != 0");
1083 /*=============================================*/
1085 /*=============================================*/
1087 TstCond (Failure
, (Nine
== Three
* Three
), "9 != 3*3");
1088 TstCond (Failure
, (TwentySeven
== Nine
* Three
), "27 != 9*3");
1089 TstCond (Failure
, (Eight
== Four
+ Four
), "8 != 4+4");
1090 TstCond (Failure
, (ThirtyTwo
== Eight
* Four
), "32 != 8*4");
1091 TstCond (Failure
, (ThirtyTwo
- TwentySeven
- Four
- One
== Zero
),
1094 TstCond (Failure
, Five
== Four
+ One
, "5 != 4+1");
1095 TstCond (Failure
, TwoForty
== Four
* Five
* Three
* Four
, "240 != 4*5*3*4");
1096 TstCond (Failure
, TwoForty
/ Three
- Four
* Four
* Five
== Zero
,
1097 "240/3 - 4*4*5 != 0");
1098 TstCond (Failure
, TwoForty
/ Four
- Five
* Three
* Four
== Zero
,
1099 "240/4 - 5*3*4 != 0");
1100 TstCond (Failure
, TwoForty
/ Five
- Four
* Three
* Four
== Zero
,
1101 "240/5 - 4*3*4 != 0");
1103 if (ErrCnt
[Failure
] == 0)
1105 printf ("-1, 0, 1/2, 1, 2, 3, 4, 5, 9, 27, 32 & 240 are O.K.\n");
1108 printf ("Searching for Radix and Precision.\n");
1117 while (MinusOne
+ FABS (Y
) < Zero
);
1118 /*.. now W is just big enough that |((W+1)-W)-1| >= 1 ... */
1127 while (Radix
== Zero
);
1130 printf ("Radix = %s .\n", Radix
.str());
1136 Precision
= Precision
+ One
;
1140 while ((Y
- W
) == One
);
1142 /*... now W == Radix^Precision is barely too big to satisfy (W+1)-W == 1
1146 printf ("Closest relative separation found is U1 = %s .\n\n", U1
.str());
1147 printf ("Recalculating radix and precision\n ");
1149 /*save old values */
1159 X
= FABS (X
- Third
);
1163 /*... now X = (unknown no.) ulps of 1+... */
1167 Y
= Half
* U2
+ ThirtyTwo
* U2
* U2
;
1171 while (!((U2
<= X
) || (X
<= Zero
)));
1173 /*... now U2 == 1 ulp of 1 + ... */
1182 /*... now X == (unknown no.) ulps of 1 -... */
1186 Y
= Half
* U1
+ ThirtyTwo
* U1
* U1
;
1192 while (!((U1
<= X
) || (X
<= Zero
)));
1193 /*... now U1 == 1 ulp of 1 - ... */
1195 printf ("confirms closest relative separation U1 .\n");
1197 printf ("gets better closest relative separation U1 = %s .\n", U1
.str());
1199 F9
= (Half
- U1
) + Half
;
1201 Radix
= FLOOR (FLOAT ("0.01") + U2
/ U1
);
1203 printf ("Radix confirmed.\n");
1205 printf ("MYSTERY: recalculated Radix = %s .\n", Radix
.str());
1206 TstCond (Defect
, Radix
<= Eight
+ Eight
,
1207 "Radix is too big: roundoff problems");
1208 TstCond (Flaw
, (Radix
== Two
) || (Radix
== 10)
1209 || (Radix
== One
), "Radix is not as good as 2 or 10");
1210 /*=============================================*/
1212 /*=============================================*/
1213 TstCond (Failure
, F9
- Half
< Half
,
1214 "(1-U1)-1/2 < 1/2 is FALSE, prog. fails?");
1219 TstCond (Failure
, (X
!= One
)
1220 || (Z
== Zero
), "Comparison is fuzzy,X=1 but X-1/2-1/2 != 0");
1223 /*=============================================*/
1225 /*=============================================*/
1226 /*... BMinusU2 = nextafter(Radix, 0) */
1227 BMinusU2
= Radix
- One
;
1228 BMinusU2
= (BMinusU2
- U2
) + One
;
1229 /* Purify Integers */
1232 X
= -TwoForty
* LOG (U1
) / LOG (Radix
);
1233 Y
= FLOOR (Half
+ X
);
1234 if (FABS (X
- Y
) * Four
< One
)
1236 Precision
= X
/ TwoForty
;
1237 Y
= FLOOR (Half
+ Precision
);
1238 if (FABS (Precision
- Y
) * TwoForty
< Half
)
1241 if ((Precision
!= FLOOR (Precision
)) || (Radix
== One
))
1243 printf ("Precision cannot be characterized by an Integer number\n");
1245 ("of significant digits but, by itself, this is a minor flaw.\n");
1249 ("logarithmic encoding has precision characterized solely by U1.\n");
1251 printf ("The number of significant digits of the Radix is %s .\n",
1253 TstCond (Serious
, U2
* Nine
* Nine
* TwoForty
< One
,
1254 "Precision worse than 5 decimal figures ");
1255 /*=============================================*/
1257 /*=============================================*/
1258 /* Test for extra-precise subexpressions */
1259 X
= FABS (((Four
/ Three
- One
) - One
/ Four
) * Three
- One
/ Four
);
1263 X
= (One
+ (Half
* Z2
+ ThirtyTwo
* Z2
* Z2
)) - One
;
1265 while (!((Z2
<= X
) || (X
<= Zero
)));
1266 X
= Y
= Z
= FABS ((Three
/ Four
- Two
/ Three
) * Three
- One
/ Four
);
1270 Z
= (One
/ Two
- ((One
/ Two
- (Half
* Z1
+ ThirtyTwo
* Z1
* Z1
))
1271 + One
/ Two
)) + One
/ Two
;
1273 while (!((Z1
<= Z
) || (Z
<= Zero
)));
1280 (Half
- ((Half
- (Half
* Y1
+ ThirtyTwo
* Y1
* Y1
)) + Half
)) +
1283 while (!((Y1
<= Y
) || (Y
<= Zero
)));
1285 X
= ((Half
* X1
+ ThirtyTwo
* X1
* X1
) - F9
) + F9
;
1287 while (!((X1
<= X
) || (X
<= Zero
)));
1288 if ((X1
!= Y1
) || (X1
!= Z1
))
1290 BadCond (Serious
, "Disagreements among the values X1, Y1, Z1,\n");
1291 printf ("respectively %s, %s, %s,\n", X1
.str(), Y1
.str(), Z1
.str());
1292 printf ("are symptoms of inconsistencies introduced\n");
1293 printf ("by extra-precise evaluation of arithmetic subexpressions.\n");
1294 notify ("Possibly some part of this");
1295 if ((X1
== U1
) || (Y1
== U1
) || (Z1
== U1
))
1296 printf ("That feature is not tested further by this program.\n");
1300 if ((Z1
!= U1
) || (Z2
!= U2
))
1302 if ((Z1
>= U1
) || (Z2
>= U2
))
1304 BadCond (Failure
, "");
1305 notify ("Precision");
1306 printf ("\tU1 = %s, Z1 - U1 = %s\n", U1
.str(), (Z1
- U1
).str());
1307 printf ("\tU2 = %s, Z2 - U2 = %s\n", U2
.str(), (Z2
- U2
).str());
1311 if ((Z1
<= Zero
) || (Z2
<= Zero
))
1313 printf ("Because of unusual Radix = %s", Radix
.str());
1314 printf (", or exact rational arithmetic a result\n");
1315 printf ("Z1 = %s, or Z2 = %s ", Z1
.str(), Z2
.str());
1316 notify ("of an\nextra-precision");
1318 if (Z1
!= Z2
|| Z1
> Zero
)
1325 printf ("Some subexpressions appear to be calculated "
1326 "extra precisely\n");
1327 printf ("with about %s extra B-digits, i.e.\n",
1328 (Q
/ LOG (Radix
)).str());
1329 printf ("roughly %s extra significant decimals.\n",
1330 (Q
/ LOG (FLOAT (10))).str());
1333 ("That feature is not tested further by this program.\n");
1338 /*=============================================*/
1340 /*=============================================*/
1343 X
= W
/ (Radix
* Radix
);
1348 TstCond (Failure
, X
== U2
,
1349 "Subtraction is not normalized X=Y,X+Z != Y+Z!");
1351 printf ("Subtraction appears to be normalized, as it should be.");
1353 printf ("\nChecking for guard digit in *, /, and -.\n");
1366 X
= X
* (Radix
- One
);
1367 T
= T
* (Radix
- One
);
1368 if ((X
== Zero
) && (Y
== Zero
) && (Z
== Zero
) && (T
== Zero
))
1373 TstCond (Serious
, false, "* lacks a Guard Digit, so 1*X != X");
1377 Y
= FABS ((X
+ Z
) - X
* X
) - U2
;
1379 Z
= FABS ((X
- U2
) - X
* X
) - U1
;
1380 TstCond (Failure
, (Y
<= Zero
)
1381 && (Z
<= Zero
), "* gets too many final digits wrong.\n");
1389 T
= Nine
/ TwentySeven
;
1391 TstCond (Defect
, X
== Zero
&& Y
== Zero
&& Z
== Zero
,
1392 "Division lacks a Guard Digit, so error can exceed 1 ulp\n"
1393 "or 1/3 and 3/9 and 9/27 may disagree");
1400 if ((X
== Zero
) && (Y
== Zero
) && (Z
== Zero
))
1405 TstCond (Serious
, false, "Division lacks a Guard Digit, so X/1 != X");
1407 X
= One
/ (One
+ U2
);
1408 Y
= X
- Half
- Half
;
1409 TstCond (Serious
, Y
< Zero
, "Computed value of 1/1.000..1 >= 1");
1411 Y
= One
+ Radix
* U2
;
1415 StickyBit
= T
/ Radix
;
1418 TstCond (Failure
, X
== Zero
&& Y
== Zero
,
1419 "* and/or / gets too many last digits wrong");
1424 Z
= Radix
- BMinusU2
;
1426 if ((X
== U1
) && (Y
== U1
) && (Z
== U2
) && (T
== U2
))
1431 TstCond (Serious
, false,
1432 "- lacks Guard Digit, so cancellation is obscured");
1434 if (F9
!= One
&& F9
- One
>= Zero
)
1436 BadCond (Serious
, "comparison alleges (1-U1) < 1 although\n");
1437 printf (" subtraction yields (1-U1) - 1 = 0 , thereby vitiating\n");
1438 printf (" such precautions against division by zero as\n");
1439 printf (" ... if (X == 1.0) {.....} else {.../(X-1.0)...}\n");
1441 if (GMult
== Yes
&& GDiv
== Yes
&& GAddSub
== Yes
)
1443 (" *, /, and - appear to have guard digits, as they should.\n");
1444 /*=============================================*/
1446 /*=============================================*/
1448 printf ("Checking rounding on multiply, divide and add/subtract.\n");
1452 RadixD2
= Radix
/ Two
;
1461 AInvrse
= AInvrse
/ A1
;
1463 while (!(FLOOR (AInvrse
) != AInvrse
));
1464 Done
= (X
== One
) || (A1
> Three
);
1478 TstCond (Failure
, Z
== Half
, "X * (1/X) differs from 1");
1486 X
= OneAndHalf
- U2
;
1487 Y
= OneAndHalf
+ U2
;
1496 if ((X
== Zero
) && (Y
== Zero
) && (Z
== Zero
) && (T
<= Zero
))
1498 X
= (OneAndHalf
+ U2
) * Y2
;
1499 Y
= OneAndHalf
- U2
- U2
;
1500 Z
= OneAndHalf
+ U2
+ U2
;
1501 T
= (OneAndHalf
- U2
) * Y1
;
1506 Y
= (U2
- Y
) + StickyBit
;
1507 Z
= S
- (Z
+ U2
+ U2
);
1508 StickyBit
= (Y2
+ U2
) * Y1
;
1510 StickyBit
= StickyBit
- Y2
;
1512 if ((X
== Zero
) && (Y
== Zero
) && (Z
== Zero
) && (T
== Zero
)
1513 && (StickyBit
== Zero
) && (Y1
== Half
))
1516 printf ("Multiplication appears to round correctly.\n");
1518 else if ((X
+ U2
== Zero
) && (Y
< Zero
) && (Z
+ U2
== Zero
)
1519 && (T
< Zero
) && (StickyBit
+ U2
== Zero
) && (Y1
< Half
))
1522 printf ("Multiplication appears to chop.\n");
1525 printf ("* is neither chopped nor correctly rounded.\n");
1526 if ((RMult
== Rounded
) && (GMult
== No
))
1527 notify ("Multiplication");
1530 printf ("* is neither chopped nor correctly rounded.\n");
1531 /*=============================================*/
1533 /*=============================================*/
1536 Z
= OneAndHalf
+ U2
+ U2
;
1538 T
= OneAndHalf
- U2
- U2
;
1544 Z
= Z
- (OneAndHalf
+ U2
);
1545 T
= (U2
- OneAndHalf
) + T
;
1546 if (!((X
> Zero
) || (Y
> Zero
) || (Z
> Zero
) || (T
> Zero
)))
1548 X
= OneAndHalf
/ Y2
;
1549 Y
= OneAndHalf
- U2
;
1550 Z
= OneAndHalf
+ U2
;
1552 T
= OneAndHalf
/ Y1
;
1557 Y1
= (Y2
+ U2
) / Y2
;
1560 Y1
= (F9
- U1
) / F9
;
1561 if ((X
== Zero
) && (Y
== Zero
) && (Z
== Zero
) && (T
== Zero
)
1562 && (Y2
== Zero
) && (Y2
== Zero
) && (Y1
- Half
== F9
- Half
))
1565 printf ("Division appears to round correctly.\n");
1567 notify ("Division");
1569 else if ((X
< Zero
) && (Y
< Zero
) && (Z
< Zero
) && (T
< Zero
)
1570 && (Y2
< Zero
) && (Y1
- Half
< F9
- Half
))
1573 printf ("Division appears to chop.\n");
1577 printf ("/ is neither chopped nor correctly rounded.\n");
1578 BInvrse
= One
/ Radix
;
1579 TstCond (Failure
, (BInvrse
* Radix
- Half
== Half
),
1580 "Radix * ( 1 / Radix ) differs from 1");
1581 /*=============================================*/
1583 /*=============================================*/
1584 TstCond (Failure
, ((F9
+ U1
) - Half
== Half
)
1585 && ((BMinusU2
+ U2
) - One
== Radix
- One
),
1586 "Incomplete carry-propagation in Addition");
1588 Y
= One
+ U2
* (One
- U2
);
1592 if ((X
== Zero
) && (Y
== Zero
))
1595 printf ("Add/Subtract appears to be chopped.\n");
1599 X
= (Half
+ U2
) * U2
;
1600 Y
= (Half
- U2
) * U2
;
1605 if ((X
== Zero
) && (Y
== Zero
))
1607 X
= (Half
+ U2
) * U1
;
1608 Y
= (Half
- U2
) * U1
;
1613 if ((X
== Zero
) && (Y
== Zero
))
1616 printf ("Addition/Subtraction appears to round correctly.\n");
1618 notify ("Add/Subtract");
1621 printf ("Addition/Subtraction neither rounds nor chops.\n");
1624 printf ("Addition/Subtraction neither rounds nor chops.\n");
1627 printf ("Addition/Subtraction neither rounds nor chops.\n");
1629 X
= One
+ Half
* (One
+ Half
);
1630 Y
= (One
+ U2
) * Half
;
1634 if (StickyBit
!= Zero
)
1637 BadCond (Flaw
, "(X - Y) + (Y - X) is non zero!\n");
1640 if ((GMult
== Yes
) && (GDiv
== Yes
) && (GAddSub
== Yes
)
1641 && (RMult
== Rounded
) && (RDiv
== Rounded
)
1642 && (RAddSub
== Rounded
) && (FLOOR (RadixD2
) == RadixD2
))
1644 printf ("Checking for sticky bit.\n");
1645 X
= (Half
+ U1
) * U2
;
1649 if ((Z
- One
<= Zero
) && (T
- One
>= U2
))
1653 if ((Z
- T
>= U2
) && (Y
- T
== Zero
))
1655 X
= (Half
+ U1
) * U1
;
1659 if ((Z
- One
== Zero
) && (T
- F9
== Zero
))
1661 Z
= (Half
- U1
) * U1
;
1664 if ((T
- F9
== Zero
) && (F9
- U1
- Q
== Zero
))
1666 Z
= (One
+ U2
) * OneAndHalf
;
1667 T
= (OneAndHalf
+ U2
) - Z
+ U2
;
1668 X
= One
+ Half
/ Radix
;
1669 Y
= One
+ Radix
* U2
;
1671 if (T
== Zero
&& X
+ Radix
* U2
- Z
== Zero
)
1677 if ((Y
- One
== Zero
))
1688 if (StickyBit
== One
)
1689 printf ("Sticky bit apparently used correctly.\n");
1691 printf ("Sticky bit used incorrectly or not at all.\n");
1692 TstCond (Flaw
, !(GMult
== No
|| GDiv
== No
|| GAddSub
== No
||
1693 RMult
== Other
|| RDiv
== Other
|| RAddSub
== Other
),
1694 "lack(s) of guard digits or failure(s) to correctly round or chop\n\
1695 (noted above) count as one flaw in the final tally below");
1696 /*=============================================*/
1698 /*=============================================*/
1700 printf ("Does Multiplication commute? ");
1701 printf ("Testing on %d random pairs.\n", NoTrials
);
1702 Random9
= SQRT (FLOAT (3));
1714 while (!((I
> NoTrials
) || (Z9
!= Zero
)));
1717 Random1
= One
+ Half
/ Three
;
1718 Random2
= (U2
+ U1
) + One
;
1719 Z
= Random1
* Random2
;
1720 Y
= Random2
* Random1
;
1721 Z9
= (One
+ Half
/ Three
) * ((U2
+ U1
) + One
) - (One
+ Half
/
1722 Three
) * ((U2
+ U1
) +
1725 if (!((I
== NoTrials
) || (Z9
== Zero
)))
1726 BadCond (Defect
, "X * Y == Y * X trial fails.\n");
1728 printf (" No failures found in %d integer pairs.\n", NoTrials
);
1729 /*=============================================*/
1731 /*=============================================*/
1732 printf ("\nRunning test of square root(x).\n");
1733 TstCond (Failure
, (Zero
== SQRT (Zero
))
1734 && (-Zero
== SQRT (-Zero
))
1735 && (One
== SQRT (One
)), "Square root of 0.0, -0.0 or 1.0 wrong");
1743 OneUlp
= BInvrse
* U1
;
1750 printf ("Testing if sqrt(X * X) == X for %d Integers X.\n", NoTrials
);
1760 while (!((Y
- X
>= NoTrials
)));
1763 while (I
<= NoTrials
)
1771 printf ("Test for sqrt monotonicity.\n");
1775 Z
= Radix
+ Radix
* U2
;
1778 while (!(NotMonot
|| Monot
))
1784 if ((X
> Q
) || (Q
> Z
))
1788 Q
= FLOOR (Q
+ Half
);
1789 if (!(I
> 0 || Radix
== Q
* Q
))
1811 printf ("sqrt has passed a test for Monotonicity.\n");
1814 BadCond (Defect
, "");
1815 printf ("sqrt(X) is non-monotonic for X near %s .\n", Y
.str());
1817 /*=============================================*/
1819 /*=============================================*/
1820 printf ("Seeking Underflow thresholds UfThold and E0.\n");
1822 if (Precision
!= FLOOR (Precision
))
1835 /* ... D is power of 1/Radix < 1. */
1842 while ((Y
> Z
) && (Z
+ Z
> Z
));
1851 while ((Y
> Z
) && (Z
+ Z
> Z
));
1857 /* ... 1/HInvrse == H == Min(1/Radix, 1/2) */
1861 /* ...1/Radix^(BIG Integer) << 1 << CInvrse == 1/C */
1868 while ((E0
> Z
) && (Z
+ Z
> Z
));
1883 "multiplication gets too many last digits wrong.\n");
1893 PseudoZero
= Underflow
* H
;
1898 Underflow
= PseudoZero
;
1901 Y2
= Underflow
* HInvrse
;
1902 E1
= FABS (Y1
- Y2
);
1904 if ((UfThold
== Zero
) && (Y1
!= Y2
))
1907 PseudoZero
= PseudoZero
* H
;
1909 while ((Underflow
> PseudoZero
)
1910 && (PseudoZero
+ PseudoZero
> PseudoZero
));
1912 /* Comment line 4530 .. 4560 */
1913 if (PseudoZero
!= Zero
)
1917 /* ... Test PseudoZero for "phoney- zero" violates */
1918 /* ... PseudoZero < Underflow or PseudoZero < PseudoZero + PseudoZero
1920 if (PseudoZero
<= Zero
)
1922 BadCond (Failure
, "Positive expressions can underflow to an\n");
1923 printf ("allegedly negative value\n");
1924 printf ("PseudoZero that prints out as: %s .\n", PseudoZero
.str());
1928 printf ("But -PseudoZero, which should be\n");
1929 printf ("positive, isn't; it prints out as %s .\n", X
.str());
1934 BadCond (Flaw
, "Underflow can stick at an allegedly positive\n");
1935 printf ("value PseudoZero that prints out as %s .\n",
1940 /*=============================================*/
1942 /*=============================================*/
1943 if (CInvrse
* Y
> CInvrse
* Y1
)
1948 if (!((E1
== Zero
) || (E1
== E0
)))
1950 BadCond (Defect
, "");
1953 printf ("Products underflow at a higher");
1954 printf (" threshold than differences.\n");
1955 if (PseudoZero
== Zero
)
1960 printf ("Difference underflows at a higher");
1961 printf (" threshold than products.\n");
1964 printf ("Smallest strictly positive number found is E0 = %s .\n", E0
.str());
1973 if (UfThold
== Zero
)
1979 UfThold
= Underflow
;
1980 if ((CInvrse
* Q
) != ((CInvrse
* Y
) * S
))
1983 BadCond (Failure
, "Either accuracy deteriorates as numbers\n");
1984 printf ("approach a threshold = %s\n", UfThold
.str());
1985 printf (" coming down from %s\n", C
.str());
1987 (" or else multiplication gets too many last digits wrong.\n");
1994 "Underflow confuses Comparison, which alleges that\n");
1995 printf ("Q == Y while denying that |Q - Y| == 0; these values\n");
1996 printf ("print out as Q = %s, Y = %s .\n", Q
.str(), Y2
.str());
1997 printf ("|Q - Y| = %s .\n", FABS (Q
- Y2
).str());
2006 if ((Q
== UfThold
) && (E1
== E0
) && (FABS (UfThold
- E1
/ E9
) <= E1
))
2009 printf ("Underflow is gradual; it incurs Absolute Error =\n");
2010 printf ("(roundoff in UfThold) < E0.\n");
2012 Y
= Y
* (OneAndHalf
+ U2
);
2013 X
= CInvrse
* (One
+ U2
);
2021 if (setjmp (ovfl_buf
))
2023 printf ("Underflow / UfThold failed!\n");
2027 R
= SQRT (Underflow
/ UfThold
);
2031 X
= Z
* (One
+ R
* H
* (One
+ H
));
2036 X
= Z
* (One
+ H
* H
* (One
+ H
));
2038 if (!((X
== Z
) || (X
- Z
!= Zero
)))
2041 printf ("X = %s\n\tis not equal to Z = %s .\n", X
.str(), Z
.str());
2043 printf ("yet X - Z yields %s .\n", Z9
.str());
2044 printf (" Should this NOT signal Underflow, ");
2045 printf ("this is a SERIOUS DEFECT\nthat causes ");
2046 printf ("confusion when innocent statements like\n");;
2047 printf (" if (X == Z) ... else");
2048 printf (" ... (f(X) - f(Z)) / (X - Z) ...\n");
2049 printf ("encounter Division by Zero although actually\n");
2050 if (setjmp (ovfl_buf
))
2051 printf ("X / Z fails!\n");
2053 printf ("X / Z = 1 + %s .\n", ((X
/ Z
- Half
) - Half
).str());
2056 printf ("The Underflow threshold is %s, below which\n", UfThold
.str());
2057 printf ("calculation may suffer larger Relative error than ");
2058 printf ("merely roundoff.\n");
2066 BadCond (Defect
, "");
2071 BadCond (Serious
, "");
2074 printf ("Range is too narrow; U1^%d Underflows.\n", I
);
2076 /*=============================================*/
2078 /*=============================================*/
2079 Y
= -FLOOR (Half
- TwoForty
* LOG (UfThold
) / LOG (HInvrse
)) / TwoForty
;
2081 printf ("Since underflow occurs below the threshold\n");
2082 printf ("UfThold = (%s) ^ (%s)\nonly underflow ", HInvrse
.str(), Y
.str());
2083 printf ("should afflict the expression\n\t(%s) ^ (%s);\n",
2084 HInvrse
.str(), Y2
.str());
2085 printf ("actually calculating yields:");
2086 if (setjmp (ovfl_buf
))
2088 BadCond (Serious
, "trap on underflow.\n");
2092 V9
= POW (HInvrse
, Y2
);
2093 printf (" %s .\n", V9
.str());
2094 if (!((V9
>= Zero
) && (V9
<= (Radix
+ Radix
+ E9
) * UfThold
)))
2096 BadCond (Serious
, "this is not between 0 and underflow\n");
2097 printf (" threshold = %s .\n", UfThold
.str());
2099 else if (!(V9
> UfThold
* (One
+ E9
)))
2100 printf ("This computed value is O.K.\n");
2103 BadCond (Defect
, "this is not between 0 and underflow\n");
2104 printf (" threshold = %s .\n", UfThold
.str());
2107 /*=============================================*/
2109 /*=============================================*/
2111 printf ("Searching for Overflow threshold:\n");
2112 printf ("This may generate an error.\n");
2115 if (setjmp (ovfl_buf
))
2131 printf ("Can `Z = -Y' overflow?\n");
2132 printf ("Trying it on Y = %s .\n", Y
.str());
2135 if (V
- Y
== V
+ V0
)
2136 printf ("Seems O.K.\n");
2139 printf ("finds a ");
2140 BadCond (Flaw
, "-(-Y) differs from Y.\n");
2144 BadCond (Serious
, "");
2145 printf ("overflow past %s\n\tshrinks to %s .\n", Y
.str(), Z
.str());
2149 Y
= V
* (HInvrse
* U2
- HInvrse
);
2150 Z
= Y
+ ((One
- HInvrse
) * U2
) * V
;
2160 V
= Y
* (HInvrse
* U2
- HInvrse
);
2161 V
= V
+ ((One
- HInvrse
) * U2
) * Y
;
2163 printf ("Overflow threshold is V = %s .\n", V
.str());
2165 printf ("Overflow saturates at V0 = %s .\n", V0
.str());
2167 printf ("There is no saturation value because "
2168 "the system traps on overflow.\n");
2170 printf ("No Overflow should be signaled for V * 1 = %s\n", V9
.str());
2172 printf (" nor for V / 1 = %s.\n", V9
.str());
2173 printf ("Any overflow signal separating this * from the one\n");
2174 printf ("above is a DEFECT.\n");
2175 /*=============================================*/
2177 /*=============================================*/
2178 if (!(-V
< V
&& -V0
< V0
&& -UfThold
< V
&& UfThold
< V
))
2180 BadCond (Failure
, "Comparisons involving ");
2181 printf ("+-%s, +-%s\nand +-%s are confused by Overflow.",
2182 V
.str(), V0
.str(), UfThold
.str());
2184 /*=============================================*/
2186 /*=============================================*/
2188 for (Indx
= 1; Indx
<= 3; ++Indx
)
2206 if (Y
/ (One
- Radix
* E9
) < Z
|| Y
> (One
+ Radix
* E9
) * Z
)
2207 { /* dgh: + E9 --> * E9 */
2209 BadCond (Serious
, "");
2211 BadCond (Defect
, "");
2212 printf ("Comparison alleges that what prints as Z = %s\n",
2214 printf (" is too far from sqrt(Z) ^ 2 = %s .\n", Y
.str());
2218 /*=============================================*/
2220 /*=============================================*/
2221 for (Indx
= 1; Indx
<= 2; ++Indx
)
2228 X
= (One
- Radix
* E9
) * V9
;
2230 if (((V9
< (One
- Two
* Radix
* E9
) * Z
) || (V9
> Z
)))
2234 BadCond (Serious
, "");
2236 BadCond (Defect
, "");
2237 printf ("Comparison alleges that Z = %s\n", Z
.str());
2238 printf (" is too far from sqrt(Z) ^ 2 (%s) .\n", Y
.str());
2241 /*=============================================*/
2243 /*=============================================*/
2247 if (X
* Y
< One
|| X
> Y
)
2249 if (X
* Y
< U1
|| X
> Y
/ U1
)
2250 BadCond (Defect
, "Badly");
2254 printf (" unbalanced range; UfThold * V = %s\n\t%s\n",
2255 X
.str(), "is too far from 1.\n");
2257 /*=============================================*/
2259 /*=============================================*/
2260 for (Indx
= 1; Indx
<= 5; ++Indx
)
2278 if (setjmp (ovfl_buf
))
2279 printf (" X / X traps when X = %s\n", X
.str());
2282 V9
= (Y
/ X
- Half
) - Half
;
2285 if (V9
== -U1
&& Indx
< 5)
2288 BadCond (Serious
, "");
2289 printf (" X / X differs from 1 when X = %s\n", X
.str());
2290 printf (" instead, X / X - 1/2 - 1/2 = %s .\n", V9
.str());
2293 /*=============================================*/
2295 /*=============================================*/
2298 printf ("What message and/or values does Division by Zero produce?\n");
2299 printf (" Trying to compute 1 / 0 produces ...");
2300 if (!setjmp (ovfl_buf
))
2301 printf (" %s .\n", (One
/ MyZero
).str());
2302 printf ("\n Trying to compute 0 / 0 produces ...");
2303 if (!setjmp (ovfl_buf
))
2304 printf (" %s .\n", (Zero
/ MyZero
).str());
2305 /*=============================================*/
2307 /*=============================================*/
2311 static const char *msg
[] = {
2312 "FAILUREs encountered =",
2313 "SERIOUS DEFECTs discovered =",
2314 "DEFECTs discovered =",
2315 "FLAWs discovered ="
2318 for (i
= 0; i
< 4; i
++)
2320 printf ("The number of %-29s %d.\n", msg
[i
], ErrCnt
[i
]);
2323 if ((ErrCnt
[Failure
] + ErrCnt
[Serious
] + ErrCnt
[Defect
] + ErrCnt
[Flaw
]) > 0)
2325 if ((ErrCnt
[Failure
] + ErrCnt
[Serious
] + ErrCnt
[Defect
] == 0)
2326 && (ErrCnt
[Flaw
] > 0))
2328 printf ("The arithmetic diagnosed seems ");
2329 printf ("Satisfactory though flawed.\n");
2331 if ((ErrCnt
[Failure
] + ErrCnt
[Serious
] == 0) && (ErrCnt
[Defect
] > 0))
2333 printf ("The arithmetic diagnosed may be Acceptable\n");
2334 printf ("despite inconvenient Defects.\n");
2336 if ((ErrCnt
[Failure
] + ErrCnt
[Serious
]) > 0)
2338 printf ("The arithmetic diagnosed has ");
2339 printf ("unacceptable Serious Defects.\n");
2341 if (ErrCnt
[Failure
] > 0)
2343 printf ("Potentially fatal FAILURE may have spoiled this");
2344 printf (" program's subsequent diagnoses.\n");
2349 printf ("No failures, defects nor flaws have been discovered.\n");
2350 if (!((RMult
== Rounded
) && (RDiv
== Rounded
)
2351 && (RAddSub
== Rounded
) && (RSqrt
== Rounded
)))
2352 printf ("The arithmetic diagnosed seems Satisfactory.\n");
2355 if (StickyBit
>= One
&&
2356 (Radix
- Two
) * (Radix
- Nine
- One
) == Zero
)
2358 printf ("Rounding appears to conform to ");
2359 printf ("the proposed IEEE standard P");
2360 if ((Radix
== Two
) &&
2361 ((Precision
- Four
* Three
* Two
) *
2362 (Precision
- TwentySeven
- TwentySeven
+ One
) == Zero
))
2370 printf (",\nexcept for possibly Double Rounding");
2371 printf (" during Gradual Underflow.\n");
2374 printf ("The arithmetic diagnosed appears to be Excellent!\n");
2377 printf ("END OF TEST.\n");
2381 template<typename FLOAT
>
2383 Paranoia
<FLOAT
>::Sign (FLOAT X
)
2385 return X
>= FLOAT (long (0)) ? 1 : -1;
2388 template<typename FLOAT
>
2390 Paranoia
<FLOAT
>::Pause ()
2394 fputs ("Press return...", stdout
);
2398 printf ("\nDiagnosis resumes after milestone Number %d", Milestone
);
2399 printf (" Page: %d\n\n", PageNo
);
2404 template<typename FLOAT
>
2406 Paranoia
<FLOAT
>::TstCond (int K
, int Valid
, const char *T
)
2415 template<typename FLOAT
>
2417 Paranoia
<FLOAT
>::BadCond (int K
, const char *T
)
2419 static const char *msg
[] = { "FAILURE", "SERIOUS DEFECT", "DEFECT", "FLAW" };
2421 ErrCnt
[K
] = ErrCnt
[K
] + 1;
2422 printf ("%s: %s", msg
[K
], T
);
2426 X = (Random1 + Random9)^5
2427 Random1 = X - FLOOR(X) + 0.000005 * X;
2428 and returns the new value of Random1. */
2430 template<typename FLOAT
>
2432 Paranoia
<FLOAT
>::Random ()
2436 X
= Random1
+ Random9
;
2441 Random1
= Y
+ X
* FLOAT ("0.000005");
2445 template<typename FLOAT
>
2447 Paranoia
<FLOAT
>::SqXMinX (int ErrKind
)
2453 SqEr
= ((SQRT (X
* X
) - XB
) - XA
) / OneUlp
;
2461 BadCond (ErrKind
, "\n");
2462 printf ("sqrt(%s) - %s = %s\n", (X
* X
).str(), X
.str(),
2463 (OneUlp
* SqEr
).str());
2464 printf ("\tinstead of correct value 0 .\n");
2468 template<typename FLOAT
>
2470 Paranoia
<FLOAT
>::NewD ()
2473 X
= FLOOR (Half
- X
/ Radix
) * Radix
+ X
;
2474 Q
= (Q
- X
* Z
) / Radix
+ X
* X
* (D
/ Radix
);
2475 Z
= Z
- Two
* X
* D
;
2484 template<typename FLOAT
>
2486 Paranoia
<FLOAT
>::SR3750 ()
2488 if (!((X
- Radix
< Z2
- Radix
) || (X
- Z2
> W
- Z2
)))
2492 Y2
= (X2
- Z2
) - (Y
- Z2
);
2493 X2
= X8
/ (Y
- Half
);
2494 X2
= X2
- Half
* X2
* X2
;
2495 SqEr
= (Y2
+ Half
) + (Half
- X2
);
2504 template<typename FLOAT
>
2506 Paranoia
<FLOAT
>::IsYeqX ()
2512 if (Z
== Zero
&& Q
<= Zero
)
2513 printf ("WARNING: computing\n");
2515 BadCond (Defect
, "computing\n");
2516 printf ("\t(%s) ^ (%s)\n", Z
.str(), Q
.str());
2517 printf ("\tyielded %s;\n", Y
.str());
2518 printf ("\twhich compared unequal to correct %s ;\n", X
.str());
2519 printf ("\t\tthey differ by %s .\n", (Y
- X
).str());
2521 N
= N
+ 1; /* ... count discrepancies. */
2525 template<typename FLOAT
>
2527 Paranoia
<FLOAT
>::PrintIfNPositive ()
2530 printf ("Similar discrepancies have occurred %d times.\n", N
);
2533 template<typename FLOAT
>
2535 Paranoia
<FLOAT
>::TstPtUf ()
2540 printf ("Since comparison denies Z = 0, evaluating ");
2541 printf ("(Z + Z) / Z should be safe.\n");
2542 if (setjmp (ovfl_buf
))
2545 printf ("What the machine gets for (Z + Z) / Z is %s .\n", Q9
.str());
2546 if (FABS (Q9
- Two
) < Radix
* U2
)
2548 printf ("This is O.K., provided Over/Underflow");
2549 printf (" has NOT just been signaled.\n");
2553 if ((Q9
< One
) || (Q9
> Two
))
2557 ErrCnt
[Serious
] = ErrCnt
[Serious
] + 1;
2558 printf ("This is a VERY SERIOUS DEFECT!\n");
2563 ErrCnt
[Defect
] = ErrCnt
[Defect
] + 1;
2564 printf ("This is a DEFECT!\n");
2572 if ((Z
== Random1
) && (Z
== Random2
) && (Z
== V9
))
2580 BadCond (Defect
, "What prints as Z = ");
2581 printf ("%s\n\tcompares different from ", Z
.str());
2583 printf ("Z * 1 = %s ", Random1
.str());
2584 if (!((Z
== Random2
) || (Random2
== Random1
)))
2585 printf ("1 * Z == %s\n", Random2
.str());
2587 printf ("Z / 1 = %s\n", V9
.str());
2588 if (Random2
!= Random1
)
2590 ErrCnt
[Defect
] = ErrCnt
[Defect
] + 1;
2591 BadCond (Defect
, "Multiplication does not commute!\n");
2592 printf ("\tComparison alleges that 1 * Z = %s\n", Random2
.str());
2593 printf ("\tdiffers from Z * 1 = %s\n", Random1
.str());
2600 template<typename FLOAT
>
2602 Paranoia
<FLOAT
>::notify (const char *s
)
2604 printf ("%s test appears to be inconsistent...\n", s
);
2605 printf (" PLEASE NOTIFY KARPINKSI!\n");
2608 /* ====================================================================== */
2610 int main(int ac
, char **av
)
2612 setbuf(stdout
, NULL
);
2613 setbuf(stderr
, NULL
);
2616 switch (getopt (ac
, av
, "pvg:fdl"))
2628 static const struct {
2630 const struct real_format
*fmt
;
2632 #define F(x) { #x, &x##_format }
2635 F(ieee_extended_motorola
),
2636 F(ieee_extended_intel_96
),
2637 F(ieee_extended_intel_128
),
2649 int i
, n
= sizeof (fmts
)/sizeof(*fmts
);
2651 for (i
= 0; i
< n
; ++i
)
2652 if (strcmp (fmts
[i
].name
, optarg
) == 0)
2657 printf ("Unknown implementation \"%s\"; "
2658 "available implementations:\n", optarg
);
2659 for (i
= 0; i
< n
; ++i
)
2660 printf ("\t%s\n", fmts
[i
].name
);
2664 // We cheat and use the same mode all the time, but vary
2665 // the format used for that mode.
2666 real_format_for_mode
[int(real_c_float::MODE
) - int(QFmode
)]
2669 Paranoia
<real_c_float
>().main();
2674 Paranoia
< native_float
<float> >().main();
2677 Paranoia
< native_float
<double> >().main();
2680 #ifndef NO_LONG_DOUBLE
2681 Paranoia
< native_float
<long double> >().main();
2686 puts ("-p\tpause between pages");
2687 puts ("-g<FMT>\treal.c implementation FMT");
2688 puts ("-f\tnative float");
2689 puts ("-d\tnative double");
2690 puts ("-l\tnative long double");
2695 /* GCC stuff referenced by real.o. */
2703 int target_flags
= 0;
2706 floor_log2_wide (unsigned HOST_WIDE_INT x
)