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
175 /* We never produce signals from the library. Thus setjmp need do nothing. */
177 #define setjmp(x) (0)
179 static bool verbose
= false;
180 static int verbose_index
= 0;
182 /* ====================================================================== */
183 /* The implementation of the abstract floating point class based on gcc's
184 real.c. I.e. the object of this excersize. Templated so that we can
187 template<int SIZE
, enum machine_mode MODE
>
191 long image
[SIZE
/ 32];
193 void from_long(long);
194 void from_str(const char *);
195 void binop(int code
, const real_c_float
&);
197 bool cmp(int code
, const real_c_float
&) const;
204 real_c_float(const char *s
)
206 real_c_float(const real_c_float
&b
)
207 { memcpy(image
, b
.image
, sizeof(image
)); }
209 const real_c_float
& operator= (long l
)
210 { from_long(l
); return *this; }
211 const real_c_float
& operator= (const char *s
)
212 { from_str(s
); return *this; }
213 const real_c_float
& operator= (const real_c_float
&b
)
214 { memcpy(image
, b
.image
, sizeof(image
)); return *this; }
216 const real_c_float
& operator+= (const real_c_float
&b
)
217 { binop(PLUS_EXPR
, b
); return *this; }
218 const real_c_float
& operator-= (const real_c_float
&b
)
219 { binop(MINUS_EXPR
, b
); return *this; }
220 const real_c_float
& operator*= (const real_c_float
&b
)
221 { binop(MULT_EXPR
, b
); return *this; }
222 const real_c_float
& operator/= (const real_c_float
&b
)
223 { binop(RDIV_EXPR
, b
); return *this; }
225 real_c_float
operator- () const
226 { real_c_float
r(*this); r
.unop(NEGATE_EXPR
); return r
; }
227 real_c_float
abs () const
228 { real_c_float
r(*this); r
.unop(ABS_EXPR
); return r
; }
230 bool operator < (const real_c_float
&b
) const { return cmp(LT_EXPR
, b
); }
231 bool operator <= (const real_c_float
&b
) const { return cmp(LE_EXPR
, b
); }
232 bool operator == (const real_c_float
&b
) const { return cmp(EQ_EXPR
, b
); }
233 bool operator != (const real_c_float
&b
) const { return cmp(NE_EXPR
, b
); }
234 bool operator >= (const real_c_float
&b
) const { return cmp(GE_EXPR
, b
); }
235 bool operator > (const real_c_float
&b
) const { return cmp(GT_EXPR
, b
); }
237 const char * str () const;
238 const char * hex () const;
239 long integer () const;
244 template<int SIZE
, enum machine_mode MODE
>
246 real_c_float
<SIZE
, MODE
>::from_long (long l
)
250 real_from_integer (&f
, MODE
, l
, l
< 0 ? -1 : 0, 0);
251 real_to_target (image
, &f
, MODE
);
254 template<int SIZE
, enum machine_mode MODE
>
256 real_c_float
<SIZE
, MODE
>::from_str (const char *s
)
261 if (*p
== '-' || *p
== '+')
263 if (strcasecmp(p
, "inf") == 0)
267 real_arithmetic (&f
, NEGATE_EXPR
, &f
, NULL
);
269 else if (strcasecmp(p
, "nan") == 0)
270 real_nan (&f
, "", 1, MODE
);
272 real_from_string (&f
, s
);
274 real_to_target (image
, &f
, MODE
);
277 template<int SIZE
, enum machine_mode MODE
>
279 real_c_float
<SIZE
, MODE
>::binop (int code
, const real_c_float
&b
)
281 REAL_VALUE_TYPE ai
, bi
, ri
;
283 real_from_target (&ai
, image
, MODE
);
284 real_from_target (&bi
, b
.image
, MODE
);
285 real_arithmetic (&ri
, code
, &ai
, &bi
);
286 real_to_target (image
, &ri
, MODE
);
290 char ab
[64], bb
[64], rb
[64];
291 const int digits
= int(SIZE
/ 4);
292 char symbol_for_code
;
294 real_from_target (&ri
, image
, MODE
);
295 real_to_hexadecimal (ab
, &ai
, digits
);
296 real_to_hexadecimal (bb
, &bi
, digits
);
297 real_to_hexadecimal (rb
, &ri
, digits
);
302 symbol_for_code
= '+';
305 symbol_for_code
= '-';
308 symbol_for_code
= '*';
311 symbol_for_code
= '/';
317 fprintf (stderr
, "%6d: %s %c %s = %s\n", verbose_index
++,
318 ab
, symbol_for_code
, bb
, rb
);
322 template<int SIZE
, enum machine_mode MODE
>
324 real_c_float
<SIZE
, MODE
>::unop (int code
)
326 REAL_VALUE_TYPE ai
, ri
;
328 real_from_target (&ai
, image
, MODE
);
329 real_arithmetic (&ri
, code
, &ai
, NULL
);
330 real_to_target (image
, &ri
, MODE
);
335 const int digits
= int(SIZE
/ 4);
336 const char *symbol_for_code
;
338 real_from_target (&ri
, image
, MODE
);
339 real_to_hexadecimal (ab
, &ai
, digits
);
340 real_to_hexadecimal (rb
, &ri
, digits
);
345 symbol_for_code
= "-";
348 symbol_for_code
= "abs ";
354 fprintf (stderr
, "%6d: %s%s = %s\n", verbose_index
++,
355 symbol_for_code
, ab
, rb
);
359 template<int SIZE
, enum machine_mode MODE
>
361 real_c_float
<SIZE
, MODE
>::cmp (int code
, const real_c_float
&b
) const
363 REAL_VALUE_TYPE ai
, bi
;
366 real_from_target (&ai
, image
, MODE
);
367 real_from_target (&bi
, b
.image
, MODE
);
368 ret
= real_compare (code
, &ai
, &bi
);
373 const int digits
= int(SIZE
/ 4);
374 const char *symbol_for_code
;
376 real_to_hexadecimal (ab
, &ai
, digits
);
377 real_to_hexadecimal (bb
, &bi
, digits
);
382 symbol_for_code
= "<";
385 symbol_for_code
= "<=";
388 symbol_for_code
= "==";
391 symbol_for_code
= "!=";
394 symbol_for_code
= ">=";
397 symbol_for_code
= ">";
403 fprintf (stderr
, "%6d: %s %s %s = %s\n", verbose_index
++,
404 ab
, symbol_for_code
, bb
, (ret
? "true" : "false"));
410 template<int SIZE
, enum machine_mode MODE
>
412 real_c_float
<SIZE
, MODE
>::str() const
415 const int digits
= int(SIZE
* .30102999566398119521 + 1);
417 real_from_target (&f
, image
, MODE
);
418 char *buf
= new char[digits
+ 10];
419 real_to_decimal (buf
, &f
, digits
);
424 template<int SIZE
, enum machine_mode MODE
>
426 real_c_float
<SIZE
, MODE
>::hex() const
429 const int digits
= int(SIZE
/ 4);
431 real_from_target (&f
, image
, MODE
);
432 char *buf
= new char[digits
+ 10];
433 real_to_hexadecimal (buf
, &f
, digits
);
438 template<int SIZE
, enum machine_mode MODE
>
440 real_c_float
<SIZE
, MODE
>::integer() const
443 real_from_target (&f
, image
, MODE
);
444 return real_to_integer (&f
);
447 template<int SIZE
, enum machine_mode MODE
>
449 real_c_float
<SIZE
, MODE
>::exp() const
452 real_from_target (&f
, image
, MODE
);
453 return real_exponent (&f
);
456 template<int SIZE
, enum machine_mode MODE
>
458 real_c_float
<SIZE
, MODE
>::ldexp (int exp
)
462 real_from_target (&ai
, image
, MODE
);
463 real_ldexp (&ai
, &ai
, exp
);
464 real_to_target (image
, &ai
, MODE
);
467 /* ====================================================================== */
468 /* An implementation of the abstract floating point class that uses native
469 arithmetic. Exists for reference and debugging. */
475 // Force intermediate results back to memory.
478 static T
from_str (const char *);
480 static T
verbose_binop (T
, char, T
, T
);
481 static T
verbose_unop (const char *, T
, T
);
482 static bool verbose_cmp (T
, const char *, T
, bool);
489 native_float(const char *s
)
490 { image
= from_str(s
); }
491 native_float(const native_float
&b
)
494 const native_float
& operator= (long l
)
495 { image
= l
; return *this; }
496 const native_float
& operator= (const char *s
)
497 { image
= from_str(s
); return *this; }
498 const native_float
& operator= (const native_float
&b
)
499 { image
= b
.image
; return *this; }
501 const native_float
& operator+= (const native_float
&b
)
503 image
= verbose_binop(image
, '+', b
.image
, image
+ b
.image
);
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
);
522 native_float
operator- () const
525 r
.image
= verbose_unop("-", image
, -image
);
528 native_float
abs () const
531 r
.image
= verbose_unop("abs ", image
, do_abs(image
));
535 bool operator < (const native_float
&b
) const
536 { return verbose_cmp(image
, "<", b
.image
, image
< b
.image
); }
537 bool operator <= (const native_float
&b
) const
538 { return verbose_cmp(image
, "<=", b
.image
, image
<= b
.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
); }
548 const char * str () const;
549 const char * hex () const;
550 long integer () const
551 { return long(image
); }
558 native_float
<T
>::from_str (const char *s
)
560 return strtold (s
, NULL
);
565 native_float
<float>::from_str (const char *s
)
567 return strtof (s
, NULL
);
572 native_float
<double>::from_str (const char *s
)
574 return strtod (s
, NULL
);
579 native_float
<T
>::do_abs (T image
)
581 return fabsl (image
);
586 native_float
<float>::do_abs (float image
)
588 return fabsf (image
);
593 native_float
<double>::do_abs (double image
)
600 native_float
<T
>::verbose_binop (T a
, char symbol
, T b
, T r
)
604 const int digits
= int(sizeof(T
) * CHAR_BIT
/ 4) - 1;
605 #ifdef NO_LONG_DOUBLE
606 fprintf (stderr
, "%6d: %.*a %c %.*a = %.*a\n", verbose_index
++,
607 digits
, (double)a
, symbol
,
608 digits
, (double)b
, digits
, (double)r
);
610 fprintf (stderr
, "%6d: %.*La %c %.*La = %.*La\n", verbose_index
++,
611 digits
, (long double)a
, symbol
,
612 digits
, (long double)b
, digits
, (long double)r
);
620 native_float
<T
>::verbose_unop (const char *symbol
, T a
, T r
)
624 const int digits
= int(sizeof(T
) * CHAR_BIT
/ 4) - 1;
625 #ifdef NO_LONG_DOUBLE
626 fprintf (stderr
, "%6d: %s%.*a = %.*a\n", verbose_index
++,
627 symbol
, digits
, (double)a
, digits
, (double)r
);
629 fprintf (stderr
, "%6d: %s%.*La = %.*La\n", verbose_index
++,
630 symbol
, digits
, (long double)a
, digits
, (long double)r
);
638 native_float
<T
>::verbose_cmp (T a
, const char *symbol
, T b
, bool r
)
642 const int digits
= int(sizeof(T
) * CHAR_BIT
/ 4) - 1;
643 #ifndef NO_LONG_DOUBLE
644 fprintf (stderr
, "%6d: %.*a %s %.*a = %s\n", verbose_index
++,
645 digits
, (double)a
, symbol
,
646 digits
, (double)b
, (r
? "true" : "false"));
648 fprintf (stderr
, "%6d: %.*La %s %.*La = %s\n", verbose_index
++,
649 digits
, (long double)a
, symbol
,
650 digits
, (long double)b
, (r
? "true" : "false"));
658 native_float
<T
>::str() const
660 char *buf
= new char[50];
661 const int digits
= int(sizeof(T
) * CHAR_BIT
* .30102999566398119521 + 1);
662 #ifndef NO_LONG_DOUBLE
663 sprintf (buf
, "%.*e", digits
- 1, (double) image
);
665 sprintf (buf
, "%.*Le", digits
- 1, (long double) image
);
672 native_float
<T
>::hex() const
674 char *buf
= new char[50];
675 const int digits
= int(sizeof(T
) * CHAR_BIT
/ 4);
676 #ifndef NO_LONG_DOUBLE
677 sprintf (buf
, "%.*a", digits
- 1, (double) image
);
679 sprintf (buf
, "%.*La", digits
- 1, (long double) image
);
686 native_float
<T
>::exp() const
695 native_float
<T
>::ldexp (int exp
)
697 image
= ldexpl (image
, exp
);
702 native_float
<float>::ldexp (int exp
)
704 image
= ldexpf (image
, exp
);
709 native_float
<double>::ldexp (int exp
)
711 image
= ::ldexp (image
, exp
);
714 /* ====================================================================== */
715 /* Some libm routines that Paranoia expects to be available. */
717 template<typename FLOAT
>
719 FABS (const FLOAT
&f
)
724 template<typename FLOAT
, typename RHS
>
726 operator+ (const FLOAT
&a
, const RHS
&b
)
728 return FLOAT(a
) += FLOAT(b
);
731 template<typename FLOAT
, typename RHS
>
733 operator- (const FLOAT
&a
, const RHS
&b
)
735 return FLOAT(a
) -= FLOAT(b
);
738 template<typename FLOAT
, typename RHS
>
740 operator* (const FLOAT
&a
, const RHS
&b
)
742 return FLOAT(a
) *= FLOAT(b
);
745 template<typename FLOAT
, typename RHS
>
747 operator/ (const FLOAT
&a
, const RHS
&b
)
749 return FLOAT(a
) /= FLOAT(b
);
752 template<typename FLOAT
>
754 FLOOR (const FLOAT
&f
)
756 /* ??? This is only correct when F is representable as an integer. */
757 long i
= f
.integer();
767 template<typename FLOAT
>
769 SQRT (const FLOAT
&f
)
772 FLOAT zero
= long(0);
786 z
.ldexp (-f
.exp() / 2);
788 diff2
= FABS (z
* z
- f
);
792 t
= (f
/ (two
* z
)) + (z
/ two
);
793 diff
= FABS (t
* t
- f
);
801 #elif defined(NO_LONG_DOUBLE)
805 d
= strtod (f
.hex(), NULL
);
807 sprintf(buf
, "%.35a", d
);
814 ld
= strtold (f
.hex(), NULL
);
816 sprintf(buf
, "%.35La", ld
);
822 template<typename FLOAT
>
827 FLOAT zero
= long(0);
835 int exp
= x
.exp() - 1;
846 FLOAT term
= y
/ FLOAT (n
);
847 FLOAT next
= sum
+ term
;
856 sum
+= FLOAT (exp
) * FLOAT(".69314718055994530941");
859 #elif defined (NO_LONG_DOUBLE)
863 d
= strtod (x
.hex(), NULL
);
865 sprintf(buf
, "%.35a", d
);
872 ld
= strtold (x
.hex(), NULL
);
874 sprintf(buf
, "%.35La", ld
);
880 template<typename FLOAT
>
885 #ifdef NO_LONG_DOUBLE
889 d
= strtod (x
.hex(), NULL
);
891 sprintf(buf
, "%.35a", d
);
898 ld
= strtold (x
.hex(), NULL
);
900 sprintf(buf
, "%.35La", ld
);
906 template<typename FLOAT
>
908 POW (const FLOAT
&base
, const FLOAT
&exp
)
911 #ifdef NO_LONG_DOUBLE
915 d1
= strtod (base
.hex(), NULL
);
916 d2
= strtod (exp
.hex(), NULL
);
918 sprintf(buf
, "%.35a", d1
);
922 long double ld1
, ld2
;
925 ld1
= strtold (base
.hex(), NULL
);
926 ld2
= strtold (exp
.hex(), NULL
);
927 ld1
= powl (ld1
, ld2
);
928 sprintf(buf
, "%.35La", ld1
);
934 /* ====================================================================== */
935 /* Real Paranoia begins again here. We wrap the thing in a template so
936 that we can instantiate it for each floating point type we care for. */
938 int NoTrials
= 20; /*Number of tests for commutativity. */
939 bool do_pause
= false;
941 enum Guard
{ No
, Yes
};
942 enum Rounding
{ Other
, Rounded
, Chopped
};
943 enum Class
{ Failure
, Serious
, Defect
, Flaw
};
945 template<typename FLOAT
>
948 FLOAT Radix
, BInvrse
, RadixD2
, BMinusU2
;
950 /* Small floating point constants. */
966 /* Declarations of Variables. */
972 FLOAT E0
, E1
, Exp2
, E3
, MinSqEr
;
973 FLOAT SqEr
, MaxSqEr
, E9
;
983 FLOAT T
, Underflow
, S
;
984 FLOAT OneUlp
, UfThold
, U1
, U2
;
987 FLOAT X
, X1
, X2
, X8
, Random1
;
988 FLOAT Y
, Y1
, Y2
, Random2
;
989 FLOAT Z
, PseudoZero
, Z1
, Z2
, Z9
;
994 Guard GMult
, GDiv
, GAddSub
;
995 Rounding RMult
, RDiv
, RAddSub
, RSqrt
;
996 int Break
, Done
, NotMonot
, Monot
, Anomaly
, IEEE
, SqRWrng
, UfNGrad
;
998 /* Computed constants. */
999 /*U1 gap below 1.0, i.e, 1.0-U1 is next number below 1.0 */
1000 /*U2 gap above 1.0, i.e, 1.0+U2 is next number above 1.0 */
1007 void BadCond (int, const char *);
1009 void TstCond (int, int, const char *);
1010 void notify (const char *);
1013 void PrintIfNPositive ();
1017 // Pretend we're bss.
1018 Paranoia() { memset(this, 0, sizeof (*this)); }
1021 template<typename FLOAT
>
1023 Paranoia
<FLOAT
>::main()
1025 /* First two assignments use integer right-hand sides. */
1034 TwentySeven
= long(27);
1035 ThirtyTwo
= long(32);
1036 TwoForty
= long(240);
1037 MinusOne
= long(-1);
1039 OneAndHalf
= "0x3p-1";
1040 ErrCnt
[Failure
] = 0;
1041 ErrCnt
[Serious
] = 0;
1045 /*=============================================*/
1047 /*=============================================*/
1048 printf ("Program is now RUNNING tests on small integers:\n");
1050 TstCond (Failure
, (Zero
+ Zero
== Zero
), "0+0 != 0");
1051 TstCond (Failure
, (One
- One
== Zero
), "1-1 != 0");
1052 TstCond (Failure
, (One
> Zero
), "1 <= 0");
1053 TstCond (Failure
, (One
+ One
== Two
), "1+1 != 2");
1058 ErrCnt
[Failure
] = ErrCnt
[Failure
] + 1;
1059 printf ("Comparison alleges that -0.0 is Non-zero!\n");
1065 TstCond (Failure
, (Three
== Two
+ One
), "3 != 2+1");
1066 TstCond (Failure
, (Four
== Three
+ One
), "4 != 3+1");
1067 TstCond (Failure
, (Four
+ Two
* (-Two
) == Zero
), "4 + 2*(-2) != 0");
1068 TstCond (Failure
, (Four
- Three
- One
== Zero
), "4-3-1 != 0");
1070 TstCond (Failure
, (MinusOne
== (Zero
- One
)), "-1 != 0-1");
1071 TstCond (Failure
, (MinusOne
+ One
== Zero
), "-1+1 != 0");
1072 TstCond (Failure
, (One
+ MinusOne
== Zero
), "1+(-1) != 0");
1073 TstCond (Failure
, (MinusOne
+ FABS (One
) == Zero
), "-1+abs(1) != 0");
1074 TstCond (Failure
, (MinusOne
+ MinusOne
* MinusOne
== Zero
),
1075 "-1+(-1)*(-1) != 0");
1077 TstCond (Failure
, Half
+ MinusOne
+ Half
== Zero
, "1/2 + (-1) + 1/2 != 0");
1079 /*=============================================*/
1081 /*=============================================*/
1083 TstCond (Failure
, (Nine
== Three
* Three
), "9 != 3*3");
1084 TstCond (Failure
, (TwentySeven
== Nine
* Three
), "27 != 9*3");
1085 TstCond (Failure
, (Eight
== Four
+ Four
), "8 != 4+4");
1086 TstCond (Failure
, (ThirtyTwo
== Eight
* Four
), "32 != 8*4");
1087 TstCond (Failure
, (ThirtyTwo
- TwentySeven
- Four
- One
== Zero
),
1090 TstCond (Failure
, Five
== Four
+ One
, "5 != 4+1");
1091 TstCond (Failure
, TwoForty
== Four
* Five
* Three
* Four
, "240 != 4*5*3*4");
1092 TstCond (Failure
, TwoForty
/ Three
- Four
* Four
* Five
== Zero
,
1093 "240/3 - 4*4*5 != 0");
1094 TstCond (Failure
, TwoForty
/ Four
- Five
* Three
* Four
== Zero
,
1095 "240/4 - 5*3*4 != 0");
1096 TstCond (Failure
, TwoForty
/ Five
- Four
* Three
* Four
== Zero
,
1097 "240/5 - 4*3*4 != 0");
1099 if (ErrCnt
[Failure
] == 0)
1101 printf ("-1, 0, 1/2, 1, 2, 3, 4, 5, 9, 27, 32 & 240 are O.K.\n");
1104 printf ("Searching for Radix and Precision.\n");
1113 while (MinusOne
+ FABS (Y
) < Zero
);
1114 /*.. now W is just big enough that |((W+1)-W)-1| >= 1 ... */
1123 while (Radix
== Zero
);
1126 printf ("Radix = %s .\n", Radix
.str());
1132 Precision
= Precision
+ One
;
1136 while ((Y
- W
) == One
);
1138 /*... now W == Radix^Precision is barely too big to satisfy (W+1)-W == 1
1142 printf ("Closest relative separation found is U1 = %s .\n\n", U1
.str());
1143 printf ("Recalculating radix and precision\n ");
1145 /*save old values */
1155 X
= FABS (X
- Third
);
1159 /*... now X = (unknown no.) ulps of 1+... */
1163 Y
= Half
* U2
+ ThirtyTwo
* U2
* U2
;
1167 while (!((U2
<= X
) || (X
<= Zero
)));
1169 /*... now U2 == 1 ulp of 1 + ... */
1178 /*... now X == (unknown no.) ulps of 1 -... */
1182 Y
= Half
* U1
+ ThirtyTwo
* U1
* U1
;
1188 while (!((U1
<= X
) || (X
<= Zero
)));
1189 /*... now U1 == 1 ulp of 1 - ... */
1191 printf ("confirms closest relative separation U1 .\n");
1193 printf ("gets better closest relative separation U1 = %s .\n", U1
.str());
1195 F9
= (Half
- U1
) + Half
;
1197 Radix
= FLOOR (FLOAT ("0.01") + U2
/ U1
);
1199 printf ("Radix confirmed.\n");
1201 printf ("MYSTERY: recalculated Radix = %s .\n", Radix
.str());
1202 TstCond (Defect
, Radix
<= Eight
+ Eight
,
1203 "Radix is too big: roundoff problems");
1204 TstCond (Flaw
, (Radix
== Two
) || (Radix
== 10)
1205 || (Radix
== One
), "Radix is not as good as 2 or 10");
1206 /*=============================================*/
1208 /*=============================================*/
1209 TstCond (Failure
, F9
- Half
< Half
,
1210 "(1-U1)-1/2 < 1/2 is FALSE, prog. fails?");
1215 TstCond (Failure
, (X
!= One
)
1216 || (Z
== Zero
), "Comparison is fuzzy,X=1 but X-1/2-1/2 != 0");
1219 /*=============================================*/
1221 /*=============================================*/
1222 /*... BMinusU2 = nextafter(Radix, 0) */
1223 BMinusU2
= Radix
- One
;
1224 BMinusU2
= (BMinusU2
- U2
) + One
;
1225 /* Purify Integers */
1228 X
= -TwoForty
* LOG (U1
) / LOG (Radix
);
1229 Y
= FLOOR (Half
+ X
);
1230 if (FABS (X
- Y
) * Four
< One
)
1232 Precision
= X
/ TwoForty
;
1233 Y
= FLOOR (Half
+ Precision
);
1234 if (FABS (Precision
- Y
) * TwoForty
< Half
)
1237 if ((Precision
!= FLOOR (Precision
)) || (Radix
== One
))
1239 printf ("Precision cannot be characterized by an Integer number\n");
1241 ("of significant digits but, by itself, this is a minor flaw.\n");
1245 ("logarithmic encoding has precision characterized solely by U1.\n");
1247 printf ("The number of significant digits of the Radix is %s .\n",
1249 TstCond (Serious
, U2
* Nine
* Nine
* TwoForty
< One
,
1250 "Precision worse than 5 decimal figures ");
1251 /*=============================================*/
1253 /*=============================================*/
1254 /* Test for extra-precise subexpressions */
1255 X
= FABS (((Four
/ Three
- One
) - One
/ Four
) * Three
- One
/ Four
);
1259 X
= (One
+ (Half
* Z2
+ ThirtyTwo
* Z2
* Z2
)) - One
;
1261 while (!((Z2
<= X
) || (X
<= Zero
)));
1262 X
= Y
= Z
= FABS ((Three
/ Four
- Two
/ Three
) * Three
- One
/ Four
);
1266 Z
= (One
/ Two
- ((One
/ Two
- (Half
* Z1
+ ThirtyTwo
* Z1
* Z1
))
1267 + One
/ Two
)) + One
/ Two
;
1269 while (!((Z1
<= Z
) || (Z
<= Zero
)));
1276 (Half
- ((Half
- (Half
* Y1
+ ThirtyTwo
* Y1
* Y1
)) + Half
)) +
1279 while (!((Y1
<= Y
) || (Y
<= Zero
)));
1281 X
= ((Half
* X1
+ ThirtyTwo
* X1
* X1
) - F9
) + F9
;
1283 while (!((X1
<= X
) || (X
<= Zero
)));
1284 if ((X1
!= Y1
) || (X1
!= Z1
))
1286 BadCond (Serious
, "Disagreements among the values X1, Y1, Z1,\n");
1287 printf ("respectively %s, %s, %s,\n", X1
.str(), Y1
.str(), Z1
.str());
1288 printf ("are symptoms of inconsistencies introduced\n");
1289 printf ("by extra-precise evaluation of arithmetic subexpressions.\n");
1290 notify ("Possibly some part of this");
1291 if ((X1
== U1
) || (Y1
== U1
) || (Z1
== U1
))
1292 printf ("That feature is not tested further by this program.\n");
1296 if ((Z1
!= U1
) || (Z2
!= U2
))
1298 if ((Z1
>= U1
) || (Z2
>= U2
))
1300 BadCond (Failure
, "");
1301 notify ("Precision");
1302 printf ("\tU1 = %s, Z1 - U1 = %s\n", U1
.str(), (Z1
- U1
).str());
1303 printf ("\tU2 = %s, Z2 - U2 = %s\n", U2
.str(), (Z2
- U2
).str());
1307 if ((Z1
<= Zero
) || (Z2
<= Zero
))
1309 printf ("Because of unusual Radix = %s", Radix
.str());
1310 printf (", or exact rational arithmetic a result\n");
1311 printf ("Z1 = %s, or Z2 = %s ", Z1
.str(), Z2
.str());
1312 notify ("of an\nextra-precision");
1314 if (Z1
!= Z2
|| Z1
> Zero
)
1321 printf ("Some subexpressions appear to be calculated "
1322 "extra precisely\n");
1323 printf ("with about %s extra B-digits, i.e.\n",
1324 (Q
/ LOG (Radix
)).str());
1325 printf ("roughly %s extra significant decimals.\n",
1326 (Q
/ LOG (FLOAT (10))).str());
1329 ("That feature is not tested further by this program.\n");
1334 /*=============================================*/
1336 /*=============================================*/
1339 X
= W
/ (Radix
* Radix
);
1344 TstCond (Failure
, X
== U2
,
1345 "Subtraction is not normalized X=Y,X+Z != Y+Z!");
1347 printf ("Subtraction appears to be normalized, as it should be.");
1349 printf ("\nChecking for guard digit in *, /, and -.\n");
1362 X
= X
* (Radix
- One
);
1363 T
= T
* (Radix
- One
);
1364 if ((X
== Zero
) && (Y
== Zero
) && (Z
== Zero
) && (T
== Zero
))
1369 TstCond (Serious
, false, "* lacks a Guard Digit, so 1*X != X");
1373 Y
= FABS ((X
+ Z
) - X
* X
) - U2
;
1375 Z
= FABS ((X
- U2
) - X
* X
) - U1
;
1376 TstCond (Failure
, (Y
<= Zero
)
1377 && (Z
<= Zero
), "* gets too many final digits wrong.\n");
1385 T
= Nine
/ TwentySeven
;
1387 TstCond (Defect
, X
== Zero
&& Y
== Zero
&& Z
== Zero
,
1388 "Division lacks a Guard Digit, so error can exceed 1 ulp\n"
1389 "or 1/3 and 3/9 and 9/27 may disagree");
1396 if ((X
== Zero
) && (Y
== Zero
) && (Z
== Zero
))
1401 TstCond (Serious
, false, "Division lacks a Guard Digit, so X/1 != X");
1403 X
= One
/ (One
+ U2
);
1404 Y
= X
- Half
- Half
;
1405 TstCond (Serious
, Y
< Zero
, "Computed value of 1/1.000..1 >= 1");
1407 Y
= One
+ Radix
* U2
;
1411 StickyBit
= T
/ Radix
;
1414 TstCond (Failure
, X
== Zero
&& Y
== Zero
,
1415 "* and/or / gets too many last digits wrong");
1420 Z
= Radix
- BMinusU2
;
1422 if ((X
== U1
) && (Y
== U1
) && (Z
== U2
) && (T
== U2
))
1427 TstCond (Serious
, false,
1428 "- lacks Guard Digit, so cancellation is obscured");
1430 if (F9
!= One
&& F9
- One
>= Zero
)
1432 BadCond (Serious
, "comparison alleges (1-U1) < 1 although\n");
1433 printf (" subtraction yields (1-U1) - 1 = 0 , thereby vitiating\n");
1434 printf (" such precautions against division by zero as\n");
1435 printf (" ... if (X == 1.0) {.....} else {.../(X-1.0)...}\n");
1437 if (GMult
== Yes
&& GDiv
== Yes
&& GAddSub
== Yes
)
1439 (" *, /, and - appear to have guard digits, as they should.\n");
1440 /*=============================================*/
1442 /*=============================================*/
1444 printf ("Checking rounding on multiply, divide and add/subtract.\n");
1448 RadixD2
= Radix
/ Two
;
1457 AInvrse
= AInvrse
/ A1
;
1459 while (!(FLOOR (AInvrse
) != AInvrse
));
1460 Done
= (X
== One
) || (A1
> Three
);
1474 TstCond (Failure
, Z
== Half
, "X * (1/X) differs from 1");
1482 X
= OneAndHalf
- U2
;
1483 Y
= OneAndHalf
+ U2
;
1492 if ((X
== Zero
) && (Y
== Zero
) && (Z
== Zero
) && (T
<= Zero
))
1494 X
= (OneAndHalf
+ U2
) * Y2
;
1495 Y
= OneAndHalf
- U2
- U2
;
1496 Z
= OneAndHalf
+ U2
+ U2
;
1497 T
= (OneAndHalf
- U2
) * Y1
;
1502 Y
= (U2
- Y
) + StickyBit
;
1503 Z
= S
- (Z
+ U2
+ U2
);
1504 StickyBit
= (Y2
+ U2
) * Y1
;
1506 StickyBit
= StickyBit
- Y2
;
1508 if ((X
== Zero
) && (Y
== Zero
) && (Z
== Zero
) && (T
== Zero
)
1509 && (StickyBit
== Zero
) && (Y1
== Half
))
1512 printf ("Multiplication appears to round correctly.\n");
1514 else if ((X
+ U2
== Zero
) && (Y
< Zero
) && (Z
+ U2
== Zero
)
1515 && (T
< Zero
) && (StickyBit
+ U2
== Zero
) && (Y1
< Half
))
1518 printf ("Multiplication appears to chop.\n");
1521 printf ("* is neither chopped nor correctly rounded.\n");
1522 if ((RMult
== Rounded
) && (GMult
== No
))
1523 notify ("Multiplication");
1526 printf ("* is neither chopped nor correctly rounded.\n");
1527 /*=============================================*/
1529 /*=============================================*/
1532 Z
= OneAndHalf
+ U2
+ U2
;
1534 T
= OneAndHalf
- U2
- U2
;
1540 Z
= Z
- (OneAndHalf
+ U2
);
1541 T
= (U2
- OneAndHalf
) + T
;
1542 if (!((X
> Zero
) || (Y
> Zero
) || (Z
> Zero
) || (T
> Zero
)))
1544 X
= OneAndHalf
/ Y2
;
1545 Y
= OneAndHalf
- U2
;
1546 Z
= OneAndHalf
+ U2
;
1548 T
= OneAndHalf
/ Y1
;
1553 Y1
= (Y2
+ U2
) / Y2
;
1556 Y1
= (F9
- U1
) / F9
;
1557 if ((X
== Zero
) && (Y
== Zero
) && (Z
== Zero
) && (T
== Zero
)
1558 && (Y2
== Zero
) && (Y2
== Zero
) && (Y1
- Half
== F9
- Half
))
1561 printf ("Division appears to round correctly.\n");
1563 notify ("Division");
1565 else if ((X
< Zero
) && (Y
< Zero
) && (Z
< Zero
) && (T
< Zero
)
1566 && (Y2
< Zero
) && (Y1
- Half
< F9
- Half
))
1569 printf ("Division appears to chop.\n");
1573 printf ("/ is neither chopped nor correctly rounded.\n");
1574 BInvrse
= One
/ Radix
;
1575 TstCond (Failure
, (BInvrse
* Radix
- Half
== Half
),
1576 "Radix * ( 1 / Radix ) differs from 1");
1577 /*=============================================*/
1579 /*=============================================*/
1580 TstCond (Failure
, ((F9
+ U1
) - Half
== Half
)
1581 && ((BMinusU2
+ U2
) - One
== Radix
- One
),
1582 "Incomplete carry-propagation in Addition");
1584 Y
= One
+ U2
* (One
- U2
);
1588 if ((X
== Zero
) && (Y
== Zero
))
1591 printf ("Add/Subtract appears to be chopped.\n");
1595 X
= (Half
+ U2
) * U2
;
1596 Y
= (Half
- U2
) * U2
;
1601 if ((X
== Zero
) && (Y
== Zero
))
1603 X
= (Half
+ U2
) * U1
;
1604 Y
= (Half
- U2
) * U1
;
1609 if ((X
== Zero
) && (Y
== Zero
))
1612 printf ("Addition/Subtraction appears to round correctly.\n");
1614 notify ("Add/Subtract");
1617 printf ("Addition/Subtraction neither rounds nor chops.\n");
1620 printf ("Addition/Subtraction neither rounds nor chops.\n");
1623 printf ("Addition/Subtraction neither rounds nor chops.\n");
1625 X
= One
+ Half
* (One
+ Half
);
1626 Y
= (One
+ U2
) * Half
;
1630 if (StickyBit
!= Zero
)
1633 BadCond (Flaw
, "(X - Y) + (Y - X) is non zero!\n");
1636 if ((GMult
== Yes
) && (GDiv
== Yes
) && (GAddSub
== Yes
)
1637 && (RMult
== Rounded
) && (RDiv
== Rounded
)
1638 && (RAddSub
== Rounded
) && (FLOOR (RadixD2
) == RadixD2
))
1640 printf ("Checking for sticky bit.\n");
1641 X
= (Half
+ U1
) * U2
;
1645 if ((Z
- One
<= Zero
) && (T
- One
>= U2
))
1649 if ((Z
- T
>= U2
) && (Y
- T
== Zero
))
1651 X
= (Half
+ U1
) * U1
;
1655 if ((Z
- One
== Zero
) && (T
- F9
== Zero
))
1657 Z
= (Half
- U1
) * U1
;
1660 if ((T
- F9
== Zero
) && (F9
- U1
- Q
== Zero
))
1662 Z
= (One
+ U2
) * OneAndHalf
;
1663 T
= (OneAndHalf
+ U2
) - Z
+ U2
;
1664 X
= One
+ Half
/ Radix
;
1665 Y
= One
+ Radix
* U2
;
1667 if (T
== Zero
&& X
+ Radix
* U2
- Z
== Zero
)
1673 if ((Y
- One
== Zero
))
1684 if (StickyBit
== One
)
1685 printf ("Sticky bit apparently used correctly.\n");
1687 printf ("Sticky bit used incorrectly or not at all.\n");
1688 TstCond (Flaw
, !(GMult
== No
|| GDiv
== No
|| GAddSub
== No
||
1689 RMult
== Other
|| RDiv
== Other
|| RAddSub
== Other
),
1690 "lack(s) of guard digits or failure(s) to correctly round or chop\n\
1691 (noted above) count as one flaw in the final tally below");
1692 /*=============================================*/
1694 /*=============================================*/
1696 printf ("Does Multiplication commute? ");
1697 printf ("Testing on %d random pairs.\n", NoTrials
);
1698 Random9
= SQRT (FLOAT (3));
1710 while (!((I
> NoTrials
) || (Z9
!= Zero
)));
1713 Random1
= One
+ Half
/ Three
;
1714 Random2
= (U2
+ U1
) + One
;
1715 Z
= Random1
* Random2
;
1716 Y
= Random2
* Random1
;
1717 Z9
= (One
+ Half
/ Three
) * ((U2
+ U1
) + One
) - (One
+ Half
/
1718 Three
) * ((U2
+ U1
) +
1721 if (!((I
== NoTrials
) || (Z9
== Zero
)))
1722 BadCond (Defect
, "X * Y == Y * X trial fails.\n");
1724 printf (" No failures found in %d integer pairs.\n", NoTrials
);
1725 /*=============================================*/
1727 /*=============================================*/
1728 printf ("\nRunning test of square root(x).\n");
1729 TstCond (Failure
, (Zero
== SQRT (Zero
))
1730 && (-Zero
== SQRT (-Zero
))
1731 && (One
== SQRT (One
)), "Square root of 0.0, -0.0 or 1.0 wrong");
1739 OneUlp
= BInvrse
* U1
;
1746 printf ("Testing if sqrt(X * X) == X for %d Integers X.\n", NoTrials
);
1756 while (!((Y
- X
>= NoTrials
)));
1759 while (I
<= NoTrials
)
1767 printf ("Test for sqrt monotonicity.\n");
1771 Z
= Radix
+ Radix
* U2
;
1774 while (!(NotMonot
|| Monot
))
1780 if ((X
> Q
) || (Q
> Z
))
1784 Q
= FLOOR (Q
+ Half
);
1785 if (!(I
> 0 || Radix
== Q
* Q
))
1807 printf ("sqrt has passed a test for Monotonicity.\n");
1810 BadCond (Defect
, "");
1811 printf ("sqrt(X) is non-monotonic for X near %s .\n", Y
.str());
1813 /*=============================================*/
1815 /*=============================================*/
1816 printf ("Seeking Underflow thresholds UfThold and E0.\n");
1818 if (Precision
!= FLOOR (Precision
))
1831 /* ... D is power of 1/Radix < 1. */
1838 while ((Y
> Z
) && (Z
+ Z
> Z
));
1847 while ((Y
> Z
) && (Z
+ Z
> Z
));
1853 /* ... 1/HInvrse == H == Min(1/Radix, 1/2) */
1857 /* ...1/Radix^(BIG Integer) << 1 << CInvrse == 1/C */
1864 while ((E0
> Z
) && (Z
+ Z
> Z
));
1879 "multiplication gets too many last digits wrong.\n");
1889 PseudoZero
= Underflow
* H
;
1894 Underflow
= PseudoZero
;
1897 Y2
= Underflow
* HInvrse
;
1898 E1
= FABS (Y1
- Y2
);
1900 if ((UfThold
== Zero
) && (Y1
!= Y2
))
1903 PseudoZero
= PseudoZero
* H
;
1905 while ((Underflow
> PseudoZero
)
1906 && (PseudoZero
+ PseudoZero
> PseudoZero
));
1908 /* Comment line 4530 .. 4560 */
1909 if (PseudoZero
!= Zero
)
1913 /* ... Test PseudoZero for "phoney- zero" violates */
1914 /* ... PseudoZero < Underflow or PseudoZero < PseudoZero + PseudoZero
1916 if (PseudoZero
<= Zero
)
1918 BadCond (Failure
, "Positive expressions can underflow to an\n");
1919 printf ("allegedly negative value\n");
1920 printf ("PseudoZero that prints out as: %s .\n", PseudoZero
.str());
1924 printf ("But -PseudoZero, which should be\n");
1925 printf ("positive, isn't; it prints out as %s .\n", X
.str());
1930 BadCond (Flaw
, "Underflow can stick at an allegedly positive\n");
1931 printf ("value PseudoZero that prints out as %s .\n",
1936 /*=============================================*/
1938 /*=============================================*/
1939 if (CInvrse
* Y
> CInvrse
* Y1
)
1944 if (!((E1
== Zero
) || (E1
== E0
)))
1946 BadCond (Defect
, "");
1949 printf ("Products underflow at a higher");
1950 printf (" threshold than differences.\n");
1951 if (PseudoZero
== Zero
)
1956 printf ("Difference underflows at a higher");
1957 printf (" threshold than products.\n");
1960 printf ("Smallest strictly positive number found is E0 = %s .\n", E0
.str());
1969 if (UfThold
== Zero
)
1975 UfThold
= Underflow
;
1976 if ((CInvrse
* Q
) != ((CInvrse
* Y
) * S
))
1979 BadCond (Failure
, "Either accuracy deteriorates as numbers\n");
1980 printf ("approach a threshold = %s\n", UfThold
.str());
1981 printf (" coming down from %s\n", C
.str());
1983 (" or else multiplication gets too many last digits wrong.\n");
1990 "Underflow confuses Comparison, which alleges that\n");
1991 printf ("Q == Y while denying that |Q - Y| == 0; these values\n");
1992 printf ("print out as Q = %s, Y = %s .\n", Q
.str(), Y2
.str());
1993 printf ("|Q - Y| = %s .\n", FABS (Q
- Y2
).str());
2002 if ((Q
== UfThold
) && (E1
== E0
) && (FABS (UfThold
- E1
/ E9
) <= E1
))
2005 printf ("Underflow is gradual; it incurs Absolute Error =\n");
2006 printf ("(roundoff in UfThold) < E0.\n");
2008 Y
= Y
* (OneAndHalf
+ U2
);
2009 X
= CInvrse
* (One
+ U2
);
2017 if (setjmp (ovfl_buf
))
2019 printf ("Underflow / UfThold failed!\n");
2023 R
= SQRT (Underflow
/ UfThold
);
2027 X
= Z
* (One
+ R
* H
* (One
+ H
));
2032 X
= Z
* (One
+ H
* H
* (One
+ H
));
2034 if (!((X
== Z
) || (X
- Z
!= Zero
)))
2037 printf ("X = %s\n\tis not equal to Z = %s .\n", X
.str(), Z
.str());
2039 printf ("yet X - Z yields %s .\n", Z9
.str());
2040 printf (" Should this NOT signal Underflow, ");
2041 printf ("this is a SERIOUS DEFECT\nthat causes ");
2042 printf ("confusion when innocent statements like\n");;
2043 printf (" if (X == Z) ... else");
2044 printf (" ... (f(X) - f(Z)) / (X - Z) ...\n");
2045 printf ("encounter Division by Zero although actually\n");
2046 if (setjmp (ovfl_buf
))
2047 printf ("X / Z fails!\n");
2049 printf ("X / Z = 1 + %s .\n", ((X
/ Z
- Half
) - Half
).str());
2052 printf ("The Underflow threshold is %s, below which\n", UfThold
.str());
2053 printf ("calculation may suffer larger Relative error than ");
2054 printf ("merely roundoff.\n");
2062 BadCond (Defect
, "");
2067 BadCond (Serious
, "");
2070 printf ("Range is too narrow; U1^%d Underflows.\n", I
);
2072 /*=============================================*/
2074 /*=============================================*/
2075 Y
= -FLOOR (Half
- TwoForty
* LOG (UfThold
) / LOG (HInvrse
)) / TwoForty
;
2077 printf ("Since underflow occurs below the threshold\n");
2078 printf ("UfThold = (%s) ^ (%s)\nonly underflow ", HInvrse
.str(), Y
.str());
2079 printf ("should afflict the expression\n\t(%s) ^ (%s);\n",
2080 HInvrse
.str(), Y2
.str());
2081 printf ("actually calculating yields:");
2082 if (setjmp (ovfl_buf
))
2084 BadCond (Serious
, "trap on underflow.\n");
2088 V9
= POW (HInvrse
, Y2
);
2089 printf (" %s .\n", V9
.str());
2090 if (!((V9
>= Zero
) && (V9
<= (Radix
+ Radix
+ E9
) * UfThold
)))
2092 BadCond (Serious
, "this is not between 0 and underflow\n");
2093 printf (" threshold = %s .\n", UfThold
.str());
2095 else if (!(V9
> UfThold
* (One
+ E9
)))
2096 printf ("This computed value is O.K.\n");
2099 BadCond (Defect
, "this is not between 0 and underflow\n");
2100 printf (" threshold = %s .\n", UfThold
.str());
2103 /*=============================================*/
2105 /*=============================================*/
2107 printf ("Searching for Overflow threshold:\n");
2108 printf ("This may generate an error.\n");
2111 if (setjmp (ovfl_buf
))
2127 printf ("Can `Z = -Y' overflow?\n");
2128 printf ("Trying it on Y = %s .\n", Y
.str());
2131 if (V
- Y
== V
+ V0
)
2132 printf ("Seems O.K.\n");
2135 printf ("finds a ");
2136 BadCond (Flaw
, "-(-Y) differs from Y.\n");
2140 BadCond (Serious
, "");
2141 printf ("overflow past %s\n\tshrinks to %s .\n", Y
.str(), Z
.str());
2145 Y
= V
* (HInvrse
* U2
- HInvrse
);
2146 Z
= Y
+ ((One
- HInvrse
) * U2
) * V
;
2156 V
= Y
* (HInvrse
* U2
- HInvrse
);
2157 V
= V
+ ((One
- HInvrse
) * U2
) * Y
;
2159 printf ("Overflow threshold is V = %s .\n", V
.str());
2161 printf ("Overflow saturates at V0 = %s .\n", V0
.str());
2163 printf ("There is no saturation value because "
2164 "the system traps on overflow.\n");
2166 printf ("No Overflow should be signaled for V * 1 = %s\n", V9
.str());
2168 printf (" nor for V / 1 = %s.\n", V9
.str());
2169 printf ("Any overflow signal separating this * from the one\n");
2170 printf ("above is a DEFECT.\n");
2171 /*=============================================*/
2173 /*=============================================*/
2174 if (!(-V
< V
&& -V0
< V0
&& -UfThold
< V
&& UfThold
< V
))
2176 BadCond (Failure
, "Comparisons involving ");
2177 printf ("+-%s, +-%s\nand +-%s are confused by Overflow.",
2178 V
.str(), V0
.str(), UfThold
.str());
2180 /*=============================================*/
2182 /*=============================================*/
2184 for (Indx
= 1; Indx
<= 3; ++Indx
)
2202 if (Y
/ (One
- Radix
* E9
) < Z
|| Y
> (One
+ Radix
* E9
) * Z
)
2203 { /* dgh: + E9 --> * E9 */
2205 BadCond (Serious
, "");
2207 BadCond (Defect
, "");
2208 printf ("Comparison alleges that what prints as Z = %s\n",
2210 printf (" is too far from sqrt(Z) ^ 2 = %s .\n", Y
.str());
2214 /*=============================================*/
2216 /*=============================================*/
2217 for (Indx
= 1; Indx
<= 2; ++Indx
)
2224 X
= (One
- Radix
* E9
) * V9
;
2226 if (((V9
< (One
- Two
* Radix
* E9
) * Z
) || (V9
> Z
)))
2230 BadCond (Serious
, "");
2232 BadCond (Defect
, "");
2233 printf ("Comparison alleges that Z = %s\n", Z
.str());
2234 printf (" is too far from sqrt(Z) ^ 2 (%s) .\n", Y
.str());
2237 /*=============================================*/
2239 /*=============================================*/
2243 if (X
* Y
< One
|| X
> Y
)
2245 if (X
* Y
< U1
|| X
> Y
/ U1
)
2246 BadCond (Defect
, "Badly");
2250 printf (" unbalanced range; UfThold * V = %s\n\t%s\n",
2251 X
.str(), "is too far from 1.\n");
2253 /*=============================================*/
2255 /*=============================================*/
2256 for (Indx
= 1; Indx
<= 5; ++Indx
)
2274 if (setjmp (ovfl_buf
))
2275 printf (" X / X traps when X = %s\n", X
.str());
2278 V9
= (Y
/ X
- Half
) - Half
;
2281 if (V9
== -U1
&& Indx
< 5)
2284 BadCond (Serious
, "");
2285 printf (" X / X differs from 1 when X = %s\n", X
.str());
2286 printf (" instead, X / X - 1/2 - 1/2 = %s .\n", V9
.str());
2289 /*=============================================*/
2291 /*=============================================*/
2294 printf ("What message and/or values does Division by Zero produce?\n");
2295 printf (" Trying to compute 1 / 0 produces ...");
2296 if (!setjmp (ovfl_buf
))
2297 printf (" %s .\n", (One
/ MyZero
).str());
2298 printf ("\n Trying to compute 0 / 0 produces ...");
2299 if (!setjmp (ovfl_buf
))
2300 printf (" %s .\n", (Zero
/ MyZero
).str());
2301 /*=============================================*/
2303 /*=============================================*/
2307 static const char *msg
[] = {
2308 "FAILUREs encountered =",
2309 "SERIOUS DEFECTs discovered =",
2310 "DEFECTs discovered =",
2311 "FLAWs discovered ="
2314 for (i
= 0; i
< 4; i
++)
2316 printf ("The number of %-29s %d.\n", msg
[i
], ErrCnt
[i
]);
2319 if ((ErrCnt
[Failure
] + ErrCnt
[Serious
] + ErrCnt
[Defect
] + ErrCnt
[Flaw
]) > 0)
2321 if ((ErrCnt
[Failure
] + ErrCnt
[Serious
] + ErrCnt
[Defect
] == 0)
2322 && (ErrCnt
[Flaw
] > 0))
2324 printf ("The arithmetic diagnosed seems ");
2325 printf ("Satisfactory though flawed.\n");
2327 if ((ErrCnt
[Failure
] + ErrCnt
[Serious
] == 0) && (ErrCnt
[Defect
] > 0))
2329 printf ("The arithmetic diagnosed may be Acceptable\n");
2330 printf ("despite inconvenient Defects.\n");
2332 if ((ErrCnt
[Failure
] + ErrCnt
[Serious
]) > 0)
2334 printf ("The arithmetic diagnosed has ");
2335 printf ("unacceptable Serious Defects.\n");
2337 if (ErrCnt
[Failure
] > 0)
2339 printf ("Potentially fatal FAILURE may have spoiled this");
2340 printf (" program's subsequent diagnoses.\n");
2345 printf ("No failures, defects nor flaws have been discovered.\n");
2346 if (!((RMult
== Rounded
) && (RDiv
== Rounded
)
2347 && (RAddSub
== Rounded
) && (RSqrt
== Rounded
)))
2348 printf ("The arithmetic diagnosed seems Satisfactory.\n");
2351 if (StickyBit
>= One
&&
2352 (Radix
- Two
) * (Radix
- Nine
- One
) == Zero
)
2354 printf ("Rounding appears to conform to ");
2355 printf ("the proposed IEEE standard P");
2356 if ((Radix
== Two
) &&
2357 ((Precision
- Four
* Three
* Two
) *
2358 (Precision
- TwentySeven
- TwentySeven
+ One
) == Zero
))
2366 printf (",\nexcept for possibly Double Rounding");
2367 printf (" during Gradual Underflow.\n");
2370 printf ("The arithmetic diagnosed appears to be Excellent!\n");
2373 printf ("END OF TEST.\n");
2377 template<typename FLOAT
>
2379 Paranoia
<FLOAT
>::Sign (FLOAT X
)
2381 return X
>= FLOAT (long (0)) ? 1 : -1;
2384 template<typename FLOAT
>
2386 Paranoia
<FLOAT
>::Pause ()
2390 fputs ("Press return...", stdout
);
2394 printf ("\nDiagnosis resumes after milestone Number %d", Milestone
);
2395 printf (" Page: %d\n\n", PageNo
);
2400 template<typename FLOAT
>
2402 Paranoia
<FLOAT
>::TstCond (int K
, int Valid
, const char *T
)
2411 template<typename FLOAT
>
2413 Paranoia
<FLOAT
>::BadCond (int K
, const char *T
)
2415 static const char *msg
[] = { "FAILURE", "SERIOUS DEFECT", "DEFECT", "FLAW" };
2417 ErrCnt
[K
] = ErrCnt
[K
] + 1;
2418 printf ("%s: %s", msg
[K
], T
);
2422 X = (Random1 + Random9)^5
2423 Random1 = X - FLOOR(X) + 0.000005 * X;
2424 and returns the new value of Random1. */
2426 template<typename FLOAT
>
2428 Paranoia
<FLOAT
>::Random ()
2432 X
= Random1
+ Random9
;
2437 Random1
= Y
+ X
* FLOAT ("0.000005");
2441 template<typename FLOAT
>
2443 Paranoia
<FLOAT
>::SqXMinX (int ErrKind
)
2449 SqEr
= ((SQRT (X
* X
) - XB
) - XA
) / OneUlp
;
2457 BadCond (ErrKind
, "\n");
2458 printf ("sqrt(%s) - %s = %s\n", (X
* X
).str(), X
.str(),
2459 (OneUlp
* SqEr
).str());
2460 printf ("\tinstead of correct value 0 .\n");
2464 template<typename FLOAT
>
2466 Paranoia
<FLOAT
>::NewD ()
2469 X
= FLOOR (Half
- X
/ Radix
) * Radix
+ X
;
2470 Q
= (Q
- X
* Z
) / Radix
+ X
* X
* (D
/ Radix
);
2471 Z
= Z
- Two
* X
* D
;
2480 template<typename FLOAT
>
2482 Paranoia
<FLOAT
>::SR3750 ()
2484 if (!((X
- Radix
< Z2
- Radix
) || (X
- Z2
> W
- Z2
)))
2488 Y2
= (X2
- Z2
) - (Y
- Z2
);
2489 X2
= X8
/ (Y
- Half
);
2490 X2
= X2
- Half
* X2
* X2
;
2491 SqEr
= (Y2
+ Half
) + (Half
- X2
);
2500 template<typename FLOAT
>
2502 Paranoia
<FLOAT
>::IsYeqX ()
2508 if (Z
== Zero
&& Q
<= Zero
)
2509 printf ("WARNING: computing\n");
2511 BadCond (Defect
, "computing\n");
2512 printf ("\t(%s) ^ (%s)\n", Z
.str(), Q
.str());
2513 printf ("\tyielded %s;\n", Y
.str());
2514 printf ("\twhich compared unequal to correct %s ;\n", X
.str());
2515 printf ("\t\tthey differ by %s .\n", (Y
- X
).str());
2517 N
= N
+ 1; /* ... count discrepancies. */
2521 template<typename FLOAT
>
2523 Paranoia
<FLOAT
>::PrintIfNPositive ()
2526 printf ("Similar discrepancies have occurred %d times.\n", N
);
2529 template<typename FLOAT
>
2531 Paranoia
<FLOAT
>::TstPtUf ()
2536 printf ("Since comparison denies Z = 0, evaluating ");
2537 printf ("(Z + Z) / Z should be safe.\n");
2538 if (setjmp (ovfl_buf
))
2541 printf ("What the machine gets for (Z + Z) / Z is %s .\n", Q9
.str());
2542 if (FABS (Q9
- Two
) < Radix
* U2
)
2544 printf ("This is O.K., provided Over/Underflow");
2545 printf (" has NOT just been signaled.\n");
2549 if ((Q9
< One
) || (Q9
> Two
))
2553 ErrCnt
[Serious
] = ErrCnt
[Serious
] + 1;
2554 printf ("This is a VERY SERIOUS DEFECT!\n");
2559 ErrCnt
[Defect
] = ErrCnt
[Defect
] + 1;
2560 printf ("This is a DEFECT!\n");
2568 if ((Z
== Random1
) && (Z
== Random2
) && (Z
== V9
))
2576 BadCond (Defect
, "What prints as Z = ");
2577 printf ("%s\n\tcompares different from ", Z
.str());
2579 printf ("Z * 1 = %s ", Random1
.str());
2580 if (!((Z
== Random2
) || (Random2
== Random1
)))
2581 printf ("1 * Z == %s\n", Random2
.str());
2583 printf ("Z / 1 = %s\n", V9
.str());
2584 if (Random2
!= Random1
)
2586 ErrCnt
[Defect
] = ErrCnt
[Defect
] + 1;
2587 BadCond (Defect
, "Multiplication does not commute!\n");
2588 printf ("\tComparison alleges that 1 * Z = %s\n", Random2
.str());
2589 printf ("\tdiffers from Z * 1 = %s\n", Random1
.str());
2596 template<typename FLOAT
>
2598 Paranoia
<FLOAT
>::notify (const char *s
)
2600 printf ("%s test appears to be inconsistent...\n", s
);
2601 printf (" PLEASE NOTIFY KARPINKSI!\n");
2604 /* ====================================================================== */
2606 int main(int ac
, char **av
)
2611 switch (getopt (ac
, av
, "pvg:fdl"))
2623 int size
= strtol (optarg
, 0, 0);
2628 Paranoia
< real_c_float
<32, SFmode
> >().main();
2632 Paranoia
< real_c_float
<64, DFmode
> >().main();
2636 Paranoia
< real_c_float
<96, XFmode
> >().main();
2640 Paranoia
< real_c_float
<128, TFmode
> >().main();
2644 puts ("Invalid gcc implementation size.");
2651 Paranoia
< native_float
<float> >().main();
2654 Paranoia
< native_float
<double> >().main();
2657 #ifndef NO_LONG_DOUBLE
2658 Paranoia
< native_float
<long double> >().main();
2663 puts ("-p\tpause between pages");
2664 puts ("-g<N>\treal.c implementation size N");
2665 puts ("-f\tnative float");
2666 puts ("-d\tnative double");
2667 puts ("-l\tnative long double");
2672 /* GCC stuff referenced by real.o. */
2680 int target_flags
= 0;
2684 mode_for_size (unsigned int size
, enum mode_class
, int)