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