Automatic commit of irc logs
[ipdf/documents.git] / references / paranoia.c
1 /*      A C version of Kahan's Floating Point Test "Paranoia"
2
3                         Thos Sumner, UCSF, Feb. 1985
4                         David Gay, BTL, Jan. 1986
5
6         This is a rewrite from the Pascal version by
7
8                         B. A. Wichmann, 18 Jan. 1985
9
10         (and does NOT exhibit good C programming style).
11
12         Adjusted to use Standard C headers 19 Jan. 1992 (dmg);
13         compile with -DKR_headers or insert
14 #define KR_headers
15         at the beginning if you have an old-style C compiler.
16
17 (C) Apr 19 1983 in BASIC version by:
18         Professor W. M. Kahan,
19         567 Evans Hall
20         Electrical Engineering & Computer Science Dept.
21         University of California
22         Berkeley, California 94720
23         USA
24
25 converted to Pascal by:
26         B. A. Wichmann
27         National Physical Laboratory
28         Teddington Middx
29         TW11 OLW
30         UK
31
32 converted to C by:
33
34         David M. Gay            and     Thos Sumner
35         AT&T Bell Labs                  Computer Center, Rm. U-76
36         600 Mountain Avenue             University of California
37         Murray Hill, NJ 07974           San Francisco, CA 94143
38         USA                             USA
39
40 with simultaneous corrections to the Pascal source (reflected
41 in the Pascal source available over netlib).
42 [A couple of bug fixes from dgh = sun!dhough incorporated 31 July 1986.]
43
44 Reports of results on various systems from all the versions
45 of Paranoia are being collected by Richard Karpinski at the
46 same address as Thos Sumner.  This includes sample outputs,
47 bug reports, and criticisms.
48
49 You may copy this program freely if you acknowledge its source.
50 Comments on the Pascal version to NPL, please.
51
52
53 The C version catches signals from floating-point exceptions.
54 If signal(SIGFPE,...) is unavailable in your environment, you may
55 #define NOSIGNAL to comment out the invocations of signal.
56
57 This source file is too big for some C compilers, but may be split
58 into pieces.  Comments containing "SPLIT" suggest convenient places
59 for this splitting.  At the end of these comments is an "ed script"
60 (for the UNIX(tm) editor ed) that will do this splitting.
61
62 By #defining Single when you compile this source, you may obtain
63 a single-precision C version of Paranoia.
64
65
66 The following is from the introductory commentary from Wichmann's work:
67
68 The BASIC program of Kahan is written in Microsoft BASIC using many
69 facilities which have no exact analogy in Pascal.  The Pascal
70 version below cannot therefore be exactly the same.  Rather than be
71 a minimal transcription of the BASIC program, the Pascal coding
72 follows the conventional style of block-structured languages.  Hence
73 the Pascal version could be useful in producing versions in other
74 structured languages.
75
76 Rather than use identifiers of minimal length (which therefore have
77 little mnemonic significance), the Pascal version uses meaningful
78 identifiers as follows [Note: A few changes have been made for C]:
79
80
81 BASIC   C               BASIC   C               BASIC   C               
82
83    A                       J                       S    StickyBit
84    A1   AInverse           J0   NoErrors           T
85    B    Radix                    [Failure]         T0   Underflow
86    B1   BInverse           J1   NoErrors           T2   ThirtyTwo
87    B2   RadixD2                  [SeriousDefect]   T5   OneAndHalf
88    B9   BMinusU2           J2   NoErrors           T7   TwentySeven
89    C                             [Defect]          T8   TwoForty
90    C1   CInverse           J3   NoErrors           U    OneUlp
91    D                             [Flaw]            U0   UnderflowThreshold
92    D4   FourD              K    PageNo             U1
93    E0                      L    Milestone          U2
94    E1                      M                       V
95    E2   Exp2               N                       V0
96    E3                      N1                      V8
97    E5   MinSqEr            O    Zero               V9
98    E6   SqEr               O1   One                W
99    E7   MaxSqEr            O2   Two                X
100    E8                      O3   Three              X1
101    E9                      O4   Four               X8
102    F1   MinusOne           O5   Five               X9   Random1
103    F2   Half               O8   Eight              Y
104    F3   Third              O9   Nine               Y1
105    F6                      P    Precision          Y2
106    F9                      Q                       Y9   Random2
107    G1   GMult              Q8                      Z
108    G2   GDiv               Q9                      Z0   PseudoZero
109    G3   GAddSub            R                       Z1
110    H                       R1   RMult              Z2
111    H1   HInverse           R2   RDiv               Z9
112    I                       R3   RAddSub
113    IO   NoTrials           R4   RSqrt
114    I3   IEEE               R9   Random9
115
116    SqRWrng
117
118 All the variables in BASIC are true variables and in consequence,
119 the program is more difficult to follow since the "constants" must
120 be determined (the glossary is very helpful).  The Pascal version
121 uses Real constants, but checks are added to ensure that the values
122 are correctly converted by the compiler.
123
124 The major textual change to the Pascal version apart from the
125 identifiersis that named procedures are used, inserting parameters
126 wherehelpful.  New procedures are also introduced.  The
127 correspondence is as follows:
128
129
130 BASIC       Pascal
131 lines 
132
133   90- 140   Pause
134  170- 250   Instructions
135  380- 460   Heading
136  480- 670   Characteristics
137  690- 870   History
138 2940-2950   Random
139 3710-3740   NewD
140 4040-4080   DoesYequalX
141 4090-4110   PrintIfNPositive
142 4640-4850   TestPartialUnderflow
143
144 =*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
145
146 Below is an "ed script" that splits para.c into 10 files
147 of the form part[1-8].c, subs.c, and msgs.c, plus a header
148 file, paranoia.h, that these files require.
149
150 r paranoia.c
151 $
152 ?SPLIT
153  .d
154 +d
155 -,$w msgs.c
156 -,$d
157 ?SPLIT
158  .d
159 +d
160 -,$w subs.c
161 -,$d
162 ?part8
163 +d
164 ?include
165  .,$w part8.c
166  .,$d
167 -d
168 ?part7
169 +d
170 ?include
171  .,$w part7.c
172  .,$d
173 -d
174 ?part6
175 +d
176 ?include
177  .,$w part6.c
178  .,$d
179 -d
180 ?part5
181 +d
182 ?include
183  .,$w part5.c
184  .,$d
185 -d
186 ?part4
187 +d
188 ?include
189  .,$w part4.c
190  .,$d
191 -d
192 ?part3
193 +d
194 ?include
195  .,$w part3.c
196  .,$d
197 -d
198 ?part2
199 +d
200 ?include
201  .,$w part2.c
202  .,$d
203 ?SPLIT
204  .d
205 1,/^#include/-1d
206 1,$w part1.c
207 /Computed constants/,$d
208 1,$s/^int/extern &/
209 1,$s/^FLOAT/extern &/
210 1,$s/^char/extern &/
211 1,$s! = .*!;!
212 /^Guard/,/^Round/s/^/extern /
213 /^jmp_buf/s/^/extern /
214 /^Sig_type/s/^/extern /
215 s/$/\
216 extern void sigfpe(INT);/
217 w paranoia.h
218 q
219
220 */
221
222 #include <stdio.h>
223 #ifndef NOSIGNAL
224 #include <signal.h>
225 #endif
226 #include <setjmp.h>
227
228 #ifdef Single
229 #define FLOAT float
230 #define FABS(x) (float)fabs((double)(x))
231 #define FLOOR(x) (float)floor((double)(x))
232 #define LOG(x) (float)log((double)(x))
233 #define POW(x,y) (float)pow((double)(x),(double)(y))
234 #define SQRT(x) (float)sqrt((double)(x))
235 #else
236 #define FLOAT double
237 #define FABS(x) fabs(x)
238 #define FLOOR(x) floor(x)
239 #define LOG(x) log(x)
240 #define POW(x,y) pow(x,y)
241 #define SQRT(x) sqrt(x)
242 #endif
243
244 jmp_buf ovfl_buf;
245 #ifdef KR_headers
246 #define VOID /* void */
247 #define INT /* int */
248 #define FP /* FLOAT */
249 #define CHARP /* char * */
250 #define CHARPP /* char ** */
251 extern double fabs(), floor(), log(), pow(), sqrt();
252 extern void exit();
253 typedef void (*Sig_type)();
254 FLOAT Sign(), Random();
255 extern void BadCond();
256 extern void SqXMinX();
257 extern void TstCond();
258 extern void notify();
259 extern int read();
260 #else
261 #define VOID void
262 #define INT int
263 #define FP FLOAT
264 #define CHARP char *
265 #define CHARPP char **
266 #ifdef __STDC__
267 #include <stdlib.h>
268 #include <math.h>
269 #else
270 #ifdef __cplusplus
271 extern "C" {
272 #endif
273 extern double fabs(double), floor(double), log(double);
274 extern double pow(double,double), sqrt(double);
275 extern void exit(INT);
276 #ifdef __cplusplus
277         }
278 #endif
279 #endif
280 typedef void (*Sig_type)(int);
281 FLOAT Sign(FLOAT), Random(void);
282 extern void BadCond(int, char*);
283 extern void SqXMinX(int);
284 extern void TstCond(int, int, char*);
285 extern void notify(char*);
286 extern int read(int, char*, int);
287 #endif
288 #undef V9
289 extern void Characteristics(VOID);
290 extern void Heading(VOID);
291 extern void History(VOID);
292 extern void Instructions(VOID);
293 extern void IsYeqX(VOID);
294 extern void NewD(VOID);
295 extern void Pause(VOID);
296 extern void PrintIfNPositive(VOID);
297 extern void SR3750(VOID);
298 extern void SR3980(VOID);
299 extern void TstPtUf(VOID);
300
301 Sig_type sigsave;
302
303 #define KEYBOARD 0
304
305 FLOAT Radix, BInvrse, RadixD2, BMinusU2;
306
307 /*Small floating point constants.*/
308 FLOAT Zero = 0.0;
309 FLOAT Half = 0.5;
310 FLOAT One = 1.0;
311 FLOAT Two = 2.0;
312 FLOAT Three = 3.0;
313 FLOAT Four = 4.0;
314 FLOAT Five = 5.0;
315 FLOAT Eight = 8.0;
316 FLOAT Nine = 9.0;
317 FLOAT TwentySeven = 27.0;
318 FLOAT ThirtyTwo = 32.0;
319 FLOAT TwoForty = 240.0;
320 FLOAT MinusOne = -1.0;
321 FLOAT OneAndHalf = 1.5;
322 /*Integer constants*/
323 int NoTrials = 20; /*Number of tests for commutativity. */
324 #define False 0
325 #define True 1
326
327 /* Definitions for declared types 
328         Guard == (Yes, No);
329         Rounding == (Chopped, Rounded, Other);
330         Message == packed array [1..40] of char;
331         Class == (Flaw, Defect, Serious, Failure);
332           */
333 #define Yes 1
334 #define No  0
335 #define Chopped 2
336 #define Rounded 1
337 #define Other   0
338 #define Flaw    3
339 #define Defect  2
340 #define Serious 1
341 #define Failure 0
342 typedef int Guard, Rounding, Class;
343 typedef char Message;
344
345 /* Declarations of Variables */
346 int Indx;
347 char ch[8];
348 FLOAT AInvrse, A1;
349 FLOAT C, CInvrse;
350 FLOAT D, FourD;
351 FLOAT E0, E1, Exp2, E3, MinSqEr;
352 FLOAT SqEr, MaxSqEr, E9;
353 FLOAT Third;
354 FLOAT F6, F9;
355 FLOAT H, HInvrse;
356 int I;
357 FLOAT StickyBit, J;
358 FLOAT MyZero;
359 FLOAT Precision;
360 FLOAT Q, Q9;
361 FLOAT R, Random9;
362 FLOAT T, Underflow, S;
363 FLOAT OneUlp, UfThold, U1, U2;
364 FLOAT V, V0, V9;
365 FLOAT W;
366 FLOAT X, X1, X2, X8, Random1;
367 FLOAT Y, Y1, Y2, Random2;
368 FLOAT Z, PseudoZero, Z1, Z2, Z9;
369 int ErrCnt[4];
370 int fpecount;
371 int Milestone;
372 int PageNo;
373 int M, N, N1;
374 Guard GMult, GDiv, GAddSub;
375 Rounding RMult, RDiv, RAddSub, RSqrt;
376 int Break, Done, NotMonot, Monot, Anomaly, IEEE,
377                 SqRWrng, UfNGrad;
378 /* Computed constants. */
379 /*U1  gap below 1.0, i.e, 1.0-U1 is next number below 1.0 */
380 /*U2  gap above 1.0, i.e, 1.0+U2 is next number above 1.0 */
381
382 /* floating point exception receiver */
383  void
384 sigfpe(INT x)
385 {
386         fpecount++;
387         printf("\n* * * FLOATING-POINT ERROR %d * * *\n", x);
388         fflush(stdout);
389         if (sigsave) {
390 #ifndef NOSIGNAL
391                 signal(SIGFPE, sigsave);
392 #endif
393                 sigsave = 0;
394                 longjmp(ovfl_buf, 1);
395                 }
396         exit(1);
397 }
398
399 main(VOID)
400 {
401         /* First two assignments use integer right-hand sides. */
402         Zero = 0;
403         One = 1;
404         Two = One + One;
405         Three = Two + One;
406         Four = Three + One;
407         Five = Four + One;
408         Eight = Four + Four;
409         Nine = Three * Three;
410         TwentySeven = Nine * Three;
411         ThirtyTwo = Four * Eight;
412         TwoForty = Four * Five * Three * Four;
413         MinusOne = -One;
414         Half = One / Two;
415         OneAndHalf = One + Half;
416         ErrCnt[Failure] = 0;
417         ErrCnt[Serious] = 0;
418         ErrCnt[Defect] = 0;
419         ErrCnt[Flaw] = 0;
420         PageNo = 1;
421         /*=============================================*/
422         Milestone = 0;
423         /*=============================================*/
424 #ifndef NOSIGNAL
425         signal(SIGFPE, sigfpe);
426 #endif
427         Instructions();
428         Pause();
429         Heading();
430         Pause();
431         Characteristics();
432         Pause();
433         History();
434         Pause();
435         /*=============================================*/
436         Milestone = 7;
437         /*=============================================*/
438         printf("Program is now RUNNING tests on small integers:\n");
439         
440         TstCond (Failure, (Zero + Zero == Zero) && (One - One == Zero)
441                    && (One > Zero) && (One + One == Two),
442                         "0+0 != 0, 1-1 != 0, 1 <= 0, or 1+1 != 2");
443         Z = - Zero;
444         if (Z != 0.0) {
445                 ErrCnt[Failure] = ErrCnt[Failure] + 1;
446                 printf("Comparison alleges that -0.0 is Non-zero!\n");
447                 U2 = 0.001;
448                 Radix = 1;
449                 TstPtUf();
450                 }
451         TstCond (Failure, (Three == Two + One) && (Four == Three + One)
452                    && (Four + Two * (- Two) == Zero)
453                    && (Four - Three - One == Zero),
454                    "3 != 2+1, 4 != 3+1, 4+2*(-2) != 0, or 4-3-1 != 0");
455         TstCond (Failure, (MinusOne == (0 - One))
456                    && (MinusOne + One == Zero ) && (One + MinusOne == Zero)
457                    && (MinusOne + FABS(One) == Zero)
458                    && (MinusOne + MinusOne * MinusOne == Zero),
459                    "-1+1 != 0, (-1)+abs(1) != 0, or -1+(-1)*(-1) != 0");
460         TstCond (Failure, Half + MinusOne + Half == Zero,
461                   "1/2 + (-1) + 1/2 != 0");
462         /*=============================================*/
463         /*SPLIT
464         {
465                 extern void part2(VOID), part3(VOID), part4(VOID),
466                         part5(VOID), part6(VOID), part7(VOID);
467                 int part8(VOID);
468
469                 part2();
470                 part3();
471                 part4();
472                 part5();
473                 part6();
474                 part7();
475                 return part8();
476                 }
477         }
478 #include "paranoia.h"
479 void part2(VOID){
480 */
481         Milestone = 10;
482         /*=============================================*/
483         TstCond (Failure, (Nine == Three * Three)
484                    && (TwentySeven == Nine * Three) && (Eight == Four + Four)
485                    && (ThirtyTwo == Eight * Four)
486                    && (ThirtyTwo - TwentySeven - Four - One == Zero),
487                    "9 != 3*3, 27 != 9*3, 32 != 8*4, or 32-27-4-1 != 0");
488         TstCond (Failure, (Five == Four + One) &&
489                         (TwoForty == Four * Five * Three * Four)
490                    && (TwoForty / Three - Four * Four * Five == Zero)
491                    && ( TwoForty / Four - Five * Three * Four == Zero)
492                    && ( TwoForty / Five - Four * Three * Four == Zero),
493                   "5 != 4+1, 240/3 != 80, 240/4 != 60, or 240/5 != 48");
494         if (ErrCnt[Failure] == 0) {
495                 printf("-1, 0, 1/2, 1, 2, 3, 4, 5, 9, 27, 32 & 240 are O.K.\n");
496                 printf("\n");
497                 }
498         printf("Searching for Radix and Precision.\n");
499         W = One;
500         do  {
501                 W = W + W;
502                 Y = W + One;
503                 Z = Y - W;
504                 Y = Z - One;
505                 } while (MinusOne + FABS(Y) < Zero);
506         /*.. now W is just big enough that |((W+1)-W)-1| >= 1 ...*/
507         Precision = Zero;
508         Y = One;
509         do  {
510                 Radix = W + Y;
511                 Y = Y + Y;
512                 Radix = Radix - W;
513                 } while ( Radix == Zero);
514         if (Radix < Two) Radix = One;
515         printf("Radix = %f .\n", Radix);
516         if (Radix != 1) {
517                 W = One;
518                 do  {
519                         Precision = Precision + One;
520                         W = W * Radix;
521                         Y = W + One;
522                         } while ((Y - W) == One);
523                 }
524         /*... now W == Radix^Precision is barely too big to satisfy (W+1)-W == 1
525                                                       ...*/
526         U1 = One / W;
527         U2 = Radix * U1;
528         printf("Closest relative separation found is U1 = %.7e .\n\n", U1);
529         printf("Recalculating radix and precision\n ");
530         
531         /*save old values*/
532         E0 = Radix;
533         E1 = U1;
534         E9 = U2;
535         E3 = Precision;
536         
537         X = Four / Three;
538         Third = X - One;
539         F6 = Half - Third;
540         X = F6 + F6;
541         X = FABS(X - Third);
542         if (X < U2) X = U2;
543         
544         /*... now X = (unknown no.) ulps of 1+...*/
545         do  {
546                 U2 = X;
547                 Y = Half * U2 + ThirtyTwo * U2 * U2;
548                 Y = One + Y;
549                 X = Y - One;
550                 } while ( ! ((U2 <= X) || (X <= Zero)));
551         
552         /*... now U2 == 1 ulp of 1 + ... */
553         X = Two / Three;
554         F6 = X - Half;
555         Third = F6 + F6;
556         X = Third - Half;
557         X = FABS(X + F6);
558         if (X < U1) X = U1;
559         
560         /*... now  X == (unknown no.) ulps of 1 -... */
561         do  {
562                 U1 = X;
563                 Y = Half * U1 + ThirtyTwo * U1 * U1;
564                 Y = Half - Y;
565                 X = Half + Y;
566                 Y = Half - X;
567                 X = Half + Y;
568                 } while ( ! ((U1 <= X) || (X <= Zero)));
569         /*... now U1 == 1 ulp of 1 - ... */
570         if (U1 == E1) printf("confirms closest relative separation U1 .\n");
571         else printf("gets better closest relative separation U1 = %.7e .\n", U1);
572         W = One / U1;
573         F9 = (Half - U1) + Half;
574         Radix = FLOOR(0.01 + U2 / U1);
575         if (Radix == E0) printf("Radix confirmed.\n");
576         else printf("MYSTERY: recalculated Radix = %.7e .\n", Radix);
577         TstCond (Defect, Radix <= Eight + Eight,
578                    "Radix is too big: roundoff problems");
579         TstCond (Flaw, (Radix == Two) || (Radix == 10)
580                    || (Radix == One), "Radix is not as good as 2 or 10");
581         /*=============================================*/
582         Milestone = 20;
583         /*=============================================*/
584         TstCond (Failure, F9 - Half < Half,
585                    "(1-U1)-1/2 < 1/2 is FALSE, prog. fails?");
586         X = F9;
587         I = 1;
588         Y = X - Half;
589         Z = Y - Half;
590         TstCond (Failure, (X != One)
591                    || (Z == Zero), "Comparison is fuzzy,X=1 but X-1/2-1/2 != 0");
592         X = One + U2;
593         I = 0;
594         /*=============================================*/
595         Milestone = 25;
596         /*=============================================*/
597         /*... BMinusU2 = nextafter(Radix, 0) */
598         BMinusU2 = Radix - One;
599         BMinusU2 = (BMinusU2 - U2) + One;
600         /* Purify Integers */
601         if (Radix != One)  {
602                 X = - TwoForty * LOG(U1) / LOG(Radix);
603                 Y = FLOOR(Half + X);
604                 if (FABS(X - Y) * Four < One) X = Y;
605                 Precision = X / TwoForty;
606                 Y = FLOOR(Half + Precision);
607                 if (FABS(Precision - Y) * TwoForty < Half) Precision = Y;
608                 }
609         if ((Precision != FLOOR(Precision)) || (Radix == One)) {
610                 printf("Precision cannot be characterized by an Integer number\n");
611                 printf("of significant digits but, by itself, this is a minor flaw.\n");
612                 }
613         if (Radix == One) 
614                 printf("logarithmic encoding has precision characterized solely by U1.\n");
615         else printf("The number of significant digits of the Radix is %f .\n",
616                         Precision);
617         TstCond (Serious, U2 * Nine * Nine * TwoForty < One,
618                    "Precision worse than 5 decimal figures  ");
619         /*=============================================*/
620         Milestone = 30;
621         /*=============================================*/
622         /* Test for extra-precise subepressions */
623         X = FABS(((Four / Three - One) - One / Four) * Three - One / Four);
624         do  {
625                 Z2 = X;
626                 X = (One + (Half * Z2 + ThirtyTwo * Z2 * Z2)) - One;
627                 } while ( ! ((Z2 <= X) || (X <= Zero)));
628         X = Y = Z = FABS((Three / Four - Two / Three) * Three - One / Four);
629         do  {
630                 Z1 = Z;
631                 Z = (One / Two - ((One / Two - (Half * Z1 + ThirtyTwo * Z1 * Z1))
632                         + One / Two)) + One / Two;
633                 } while ( ! ((Z1 <= Z) || (Z <= Zero)));
634         do  {
635                 do  {
636                         Y1 = Y;
637                         Y = (Half - ((Half - (Half * Y1 + ThirtyTwo * Y1 * Y1)) + Half
638                                 )) + Half;
639                         } while ( ! ((Y1 <= Y) || (Y <= Zero)));
640                 X1 = X;
641                 X = ((Half * X1 + ThirtyTwo * X1 * X1) - F9) + F9;
642                 } while ( ! ((X1 <= X) || (X <= Zero)));
643         if ((X1 != Y1) || (X1 != Z1)) {
644                 BadCond(Serious, "Disagreements among the values X1, Y1, Z1,\n");
645                 printf("respectively  %.7e,  %.7e,  %.7e,\n", X1, Y1, Z1);
646                 printf("are symptoms of inconsistencies introduced\n");
647                 printf("by extra-precise evaluation of arithmetic subexpressions.\n");
648                 notify("Possibly some part of this");
649                 if ((X1 == U1) || (Y1 == U1) || (Z1 == U1))  printf(
650                         "That feature is not tested further by this program.\n") ;
651                 }
652         else  {
653                 if ((Z1 != U1) || (Z2 != U2)) {
654                         if ((Z1 >= U1) || (Z2 >= U2)) {
655                                 BadCond(Failure, "");
656                                 notify("Precision");
657                                 printf("\tU1 = %.7e, Z1 - U1 = %.7e\n",U1,Z1-U1);
658                                 printf("\tU2 = %.7e, Z2 - U2 = %.7e\n",U2,Z2-U2);
659                                 }
660                         else {
661                                 if ((Z1 <= Zero) || (Z2 <= Zero)) {
662                                         printf("Because of unusual Radix = %f", Radix);
663                                         printf(", or exact rational arithmetic a result\n");
664                                         printf("Z1 = %.7e, or Z2 = %.7e ", Z1, Z2);
665                                         notify("of an\nextra-precision");
666                                         }
667                                 if (Z1 != Z2 || Z1 > Zero) {
668                                         X = Z1 / U1;
669                                         Y = Z2 / U2;
670                                         if (Y > X) X = Y;
671                                         Q = - LOG(X);
672                                         printf("Some subexpressions appear to be calculated extra\n");
673                                         printf("precisely with about %g extra B-digits, i.e.\n",
674                                                 (Q / LOG(Radix)));
675                                         printf("roughly %g extra significant decimals.\n",
676                                                 Q / LOG(10.));
677                                         }
678                                 printf("That feature is not tested further by this program.\n");
679                                 }
680                         }
681                 }
682         Pause();
683         /*=============================================*/
684         /*SPLIT
685         }
686 #include "paranoia.h"
687 void part3(VOID){
688 */
689         Milestone = 35;
690         /*=============================================*/
691         if (Radix >= Two) {
692                 X = W / (Radix * Radix);
693                 Y = X + One;
694                 Z = Y - X;
695                 T = Z + U2;
696                 X = T - Z;
697                 TstCond (Failure, X == U2,
698                         "Subtraction is not normalized X=Y,X+Z != Y+Z!");
699                 if (X == U2) printf(
700                         "Subtraction appears to be normalized, as it should be.");
701                 }
702         printf("\nChecking for guard digit in *, /, and -.\n");
703         Y = F9 * One;
704         Z = One * F9;
705         X = F9 - Half;
706         Y = (Y - Half) - X;
707         Z = (Z - Half) - X;
708         X = One + U2;
709         T = X * Radix;
710         R = Radix * X;
711         X = T - Radix;
712         X = X - Radix * U2;
713         T = R - Radix;
714         T = T - Radix * U2;
715         X = X * (Radix - One);
716         T = T * (Radix - One);
717         if ((X == Zero) && (Y == Zero) && (Z == Zero) && (T == Zero)) GMult = Yes;
718         else {
719                 GMult = No;
720                 TstCond (Serious, False,
721                         "* lacks a Guard Digit, so 1*X != X");
722                 }
723         Z = Radix * U2;
724         X = One + Z;
725         Y = FABS((X + Z) - X * X) - U2;
726         X = One - U2;
727         Z = FABS((X - U2) - X * X) - U1;
728         TstCond (Failure, (Y <= Zero)
729                    && (Z <= Zero), "* gets too many final digits wrong.\n");
730         Y = One - U2;
731         X = One + U2;
732         Z = One / Y;
733         Y = Z - X;
734         X = One / Three;
735         Z = Three / Nine;
736         X = X - Z;
737         T = Nine / TwentySeven;
738         Z = Z - T;
739         TstCond(Defect, X == Zero && Y == Zero && Z == Zero,
740                 "Division lacks a Guard Digit, so error can exceed 1 ulp\n\
741 or  1/3  and  3/9  and  9/27 may disagree");
742         Y = F9 / One;
743         X = F9 - Half;
744         Y = (Y - Half) - X;
745         X = One + U2;
746         T = X / One;
747         X = T - X;
748         if ((X == Zero) && (Y == Zero) && (Z == Zero)) GDiv = Yes;
749         else {
750                 GDiv = No;
751                 TstCond (Serious, False,
752                         "Division lacks a Guard Digit, so X/1 != X");
753                 }
754         X = One / (One + U2);
755         Y = X - Half - Half;
756         TstCond (Serious, Y < Zero,
757                    "Computed value of 1/1.000..1 >= 1");
758         X = One - U2;
759         Y = One + Radix * U2;
760         Z = X * Radix;
761         T = Y * Radix;
762         R = Z / Radix;
763         StickyBit = T / Radix;
764         X = R - X;
765         Y = StickyBit - Y;
766         TstCond (Failure, X == Zero && Y == Zero,
767                         "* and/or / gets too many last digits wrong");
768         Y = One - U1;
769         X = One - F9;
770         Y = One - Y;
771         T = Radix - U2;
772         Z = Radix - BMinusU2;
773         T = Radix - T;
774         if ((X == U1) && (Y == U1) && (Z == U2) && (T == U2)) GAddSub = Yes;
775         else {
776                 GAddSub = No;
777                 TstCond (Serious, False,
778                         "- lacks Guard Digit, so cancellation is obscured");
779                 }
780         if (F9 != One && F9 - One >= Zero) {
781                 BadCond(Serious, "comparison alleges  (1-U1) < 1  although\n");
782                 printf("  subtraction yields  (1-U1) - 1 = 0 , thereby vitiating\n");
783                 printf("  such precautions against division by zero as\n");
784                 printf("  ...  if (X == 1.0) {.....} else {.../(X-1.0)...}\n");
785                 }
786         if (GMult == Yes && GDiv == Yes && GAddSub == Yes) printf(
787                 "     *, /, and - appear to have guard digits, as they should.\n");
788         /*=============================================*/
789         Milestone = 40;
790         /*=============================================*/
791         Pause();
792         printf("Checking rounding on multiply, divide and add/subtract.\n");
793         RMult = Other;
794         RDiv = Other;
795         RAddSub = Other;
796         RadixD2 = Radix / Two;
797         A1 = Two;
798         Done = False;
799         do  {
800                 AInvrse = Radix;
801                 do  {
802                         X = AInvrse;
803                         AInvrse = AInvrse / A1;
804                         } while ( ! (FLOOR(AInvrse) != AInvrse));
805                 Done = (X == One) || (A1 > Three);
806                 if (! Done) A1 = Nine + One;
807                 } while ( ! (Done));
808         if (X == One) A1 = Radix;
809         AInvrse = One / A1;
810         X = A1;
811         Y = AInvrse;
812         Done = False;
813         do  {
814                 Z = X * Y - Half;
815                 TstCond (Failure, Z == Half,
816                         "X * (1/X) differs from 1");
817                 Done = X == Radix;
818                 X = Radix;
819                 Y = One / X;
820                 } while ( ! (Done));
821         Y2 = One + U2;
822         Y1 = One - U2;
823         X = OneAndHalf - U2;
824         Y = OneAndHalf + U2;
825         Z = (X - U2) * Y2;
826         T = Y * Y1;
827         Z = Z - X;
828         T = T - X;
829         X = X * Y2;
830         Y = (Y + U2) * Y1;
831         X = X - OneAndHalf;
832         Y = Y - OneAndHalf;
833         if ((X == Zero) && (Y == Zero) && (Z == Zero) && (T <= Zero)) {
834                 X = (OneAndHalf + U2) * Y2;
835                 Y = OneAndHalf - U2 - U2;
836                 Z = OneAndHalf + U2 + U2;
837                 T = (OneAndHalf - U2) * Y1;
838                 X = X - (Z + U2);
839                 StickyBit = Y * Y1;
840                 S = Z * Y2;
841                 T = T - Y;
842                 Y = (U2 - Y) + StickyBit;
843                 Z = S - (Z + U2 + U2);
844                 StickyBit = (Y2 + U2) * Y1;
845                 Y1 = Y2 * Y1;
846                 StickyBit = StickyBit - Y2;
847                 Y1 = Y1 - Half;
848                 if ((X == Zero) && (Y == Zero) && (Z == Zero) && (T == Zero)
849                         && ( StickyBit == Zero) && (Y1 == Half)) {
850                         RMult = Rounded;
851                         printf("Multiplication appears to round correctly.\n");
852                         }
853                 else    if ((X + U2 == Zero) && (Y < Zero) && (Z + U2 == Zero)
854                                 && (T < Zero) && (StickyBit + U2 == Zero)
855                                 && (Y1 < Half)) {
856                                 RMult = Chopped;
857                                 printf("Multiplication appears to chop.\n");
858                                 }
859                         else printf("* is neither chopped nor correctly rounded.\n");
860                 if ((RMult == Rounded) && (GMult == No)) notify("Multiplication");
861                 }
862         else printf("* is neither chopped nor correctly rounded.\n");
863         /*=============================================*/
864         Milestone = 45;
865         /*=============================================*/
866         Y2 = One + U2;
867         Y1 = One - U2;
868         Z = OneAndHalf + U2 + U2;
869         X = Z / Y2;
870         T = OneAndHalf - U2 - U2;
871         Y = (T - U2) / Y1;
872         Z = (Z + U2) / Y2;
873         X = X - OneAndHalf;
874         Y = Y - T;
875         T = T / Y1;
876         Z = Z - (OneAndHalf + U2);
877         T = (U2 - OneAndHalf) + T;
878         if (! ((X > Zero) || (Y > Zero) || (Z > Zero) || (T > Zero))) {
879                 X = OneAndHalf / Y2;
880                 Y = OneAndHalf - U2;
881                 Z = OneAndHalf + U2;
882                 X = X - Y;
883                 T = OneAndHalf / Y1;
884                 Y = Y / Y1;
885                 T = T - (Z + U2);
886                 Y = Y - Z;
887                 Z = Z / Y2;
888                 Y1 = (Y2 + U2) / Y2;
889                 Z = Z - OneAndHalf;
890                 Y2 = Y1 - Y2;
891                 Y1 = (F9 - U1) / F9;
892                 if ((X == Zero) && (Y == Zero) && (Z == Zero) && (T == Zero)
893                         && (Y2 == Zero) && (Y2 == Zero)
894                         && (Y1 - Half == F9 - Half )) {
895                         RDiv = Rounded;
896                         printf("Division appears to round correctly.\n");
897                         if (GDiv == No) notify("Division");
898                         }
899                 else if ((X < Zero) && (Y < Zero) && (Z < Zero) && (T < Zero)
900                         && (Y2 < Zero) && (Y1 - Half < F9 - Half)) {
901                         RDiv = Chopped;
902                         printf("Division appears to chop.\n");
903                         }
904                 }
905         if (RDiv == Other) printf("/ is neither chopped nor correctly rounded.\n");
906         BInvrse = One / Radix;
907         TstCond (Failure, (BInvrse * Radix - Half == Half),
908                    "Radix * ( 1 / Radix ) differs from 1");
909         /*=============================================*/
910         /*SPLIT
911         }
912 #include "paranoia.h"
913 void part4(VOID){
914 */
915         Milestone = 50;
916         /*=============================================*/
917         TstCond (Failure, ((F9 + U1) - Half == Half)
918                    && ((BMinusU2 + U2 ) - One == Radix - One),
919                    "Incomplete carry-propagation in Addition");
920         X = One - U1 * U1;
921         Y = One + U2 * (One - U2);
922         Z = F9 - Half;
923         X = (X - Half) - Z;
924         Y = Y - One;
925         if ((X == Zero) && (Y == Zero)) {
926                 RAddSub = Chopped;
927                 printf("Add/Subtract appears to be chopped.\n");
928                 }
929         if (GAddSub == Yes) {
930                 X = (Half + U2) * U2;
931                 Y = (Half - U2) * U2;
932                 X = One + X;
933                 Y = One + Y;
934                 X = (One + U2) - X;
935                 Y = One - Y;
936                 if ((X == Zero) && (Y == Zero)) {
937                         X = (Half + U2) * U1;
938                         Y = (Half - U2) * U1;
939                         X = One - X;
940                         Y = One - Y;
941                         X = F9 - X;
942                         Y = One - Y;
943                         if ((X == Zero) && (Y == Zero)) {
944                                 RAddSub = Rounded;
945                                 printf("Addition/Subtraction appears to round correctly.\n");
946                                 if (GAddSub == No) notify("Add/Subtract");
947                                 }
948                         else printf("Addition/Subtraction neither rounds nor chops.\n");
949                         }
950                 else printf("Addition/Subtraction neither rounds nor chops.\n");
951                 }
952         else printf("Addition/Subtraction neither rounds nor chops.\n");
953         S = One;
954         X = One + Half * (One + Half);
955         Y = (One + U2) * Half;
956         Z = X - Y;
957         T = Y - X;
958         StickyBit = Z + T;
959         if (StickyBit != Zero) {
960                 S = Zero;
961                 BadCond(Flaw, "(X - Y) + (Y - X) is non zero!\n");
962                 }
963         StickyBit = Zero;
964         if ((GMult == Yes) && (GDiv == Yes) && (GAddSub == Yes)
965                 && (RMult == Rounded) && (RDiv == Rounded)
966                 && (RAddSub == Rounded) && (FLOOR(RadixD2) == RadixD2)) {
967                 printf("Checking for sticky bit.\n");
968                 X = (Half + U1) * U2;
969                 Y = Half * U2;
970                 Z = One + Y;
971                 T = One + X;
972                 if ((Z - One <= Zero) && (T - One >= U2)) {
973                         Z = T + Y;
974                         Y = Z - X;
975                         if ((Z - T >= U2) && (Y - T == Zero)) {
976                                 X = (Half + U1) * U1;
977                                 Y = Half * U1;
978                                 Z = One - Y;
979                                 T = One - X;
980                                 if ((Z - One == Zero) && (T - F9 == Zero)) {
981                                         Z = (Half - U1) * U1;
982                                         T = F9 - Z;
983                                         Q = F9 - Y;
984                                         if ((T - F9 == Zero) && (F9 - U1 - Q == Zero)) {
985                                                 Z = (One + U2) * OneAndHalf;
986                                                 T = (OneAndHalf + U2) - Z + U2;
987                                                 X = One + Half / Radix;
988                                                 Y = One + Radix * U2;
989                                                 Z = X * Y;
990                                                 if (T == Zero && X + Radix * U2 - Z == Zero) {
991                                                         if (Radix != Two) {
992                                                                 X = Two + U2;
993                                                                 Y = X / Two;
994                                                                 if ((Y - One == Zero)) StickyBit = S;
995                                                                 }
996                                                         else StickyBit = S;
997                                                         }
998                                                 }
999                                         }
1000                                 }
1001                         }
1002                 }
1003         if (StickyBit == One) printf("Sticky bit apparently used correctly.\n");
1004         else printf("Sticky bit used incorrectly or not at all.\n");
1005         TstCond (Flaw, !(GMult == No || GDiv == No || GAddSub == No ||
1006                         RMult == Other || RDiv == Other || RAddSub == Other),
1007                 "lack(s) of guard digits or failure(s) to correctly round or chop\n\
1008 (noted above) count as one flaw in the final tally below");
1009         /*=============================================*/
1010         Milestone = 60;
1011         /*=============================================*/
1012         printf("\n");
1013         printf("Does Multiplication commute?  ");
1014         printf("Testing on %d random pairs.\n", NoTrials);
1015         Random9 = SQRT(3.0);
1016         Random1 = Third;
1017         I = 1;
1018         do  {
1019                 X = Random();
1020                 Y = Random();
1021                 Z9 = Y * X;
1022                 Z = X * Y;
1023                 Z9 = Z - Z9;
1024                 I = I + 1;
1025                 } while ( ! ((I > NoTrials) || (Z9 != Zero)));
1026         if (I == NoTrials) {
1027                 Random1 = One + Half / Three;
1028                 Random2 = (U2 + U1) + One;
1029                 Z = Random1 * Random2;
1030                 Y = Random2 * Random1;
1031                 Z9 = (One + Half / Three) * ((U2 + U1) + One) - (One + Half /
1032                         Three) * ((U2 + U1) + One);
1033                 }
1034         if (! ((I == NoTrials) || (Z9 == Zero)))
1035                 BadCond(Defect, "X * Y == Y * X trial fails.\n");
1036         else printf("     No failures found in %d integer pairs.\n", NoTrials);
1037         /*=============================================*/
1038         Milestone = 70;
1039         /*=============================================*/
1040         printf("\nRunning test of square root(x).\n");
1041         TstCond (Failure, (Zero == SQRT(Zero))
1042                    && (- Zero == SQRT(- Zero))
1043                    && (One == SQRT(One)), "Square root of 0.0, -0.0 or 1.0 wrong");
1044         MinSqEr = Zero;
1045         MaxSqEr = Zero;
1046         J = Zero;
1047         X = Radix;
1048         OneUlp = U2;
1049         SqXMinX (Serious);
1050         X = BInvrse;
1051         OneUlp = BInvrse * U1;
1052         SqXMinX (Serious);
1053         X = U1;
1054         OneUlp = U1 * U1;
1055         SqXMinX (Serious);
1056         if (J != Zero) Pause();
1057         printf("Testing if sqrt(X * X) == X for %d Integers X.\n", NoTrials);
1058         J = Zero;
1059         X = Two;
1060         Y = Radix;
1061         if ((Radix != One)) do  {
1062                 X = Y;
1063                 Y = Radix * Y;
1064                 } while ( ! ((Y - X >= NoTrials)));
1065         OneUlp = X * U2;
1066         I = 1;
1067         while (I <= NoTrials) {
1068                 X = X + One;
1069                 SqXMinX (Defect);
1070                 if (J > Zero) break;
1071                 I = I + 1;
1072                 }
1073         printf("Test for sqrt monotonicity.\n");
1074         I = - 1;
1075         X = BMinusU2;
1076         Y = Radix;
1077         Z = Radix + Radix * U2;
1078         NotMonot = False;
1079         Monot = False;
1080         while ( ! (NotMonot || Monot)) {
1081                 I = I + 1;
1082                 X = SQRT(X);
1083                 Q = SQRT(Y);
1084                 Z = SQRT(Z);
1085                 if ((X > Q) || (Q > Z)) NotMonot = True;
1086                 else {
1087                         Q = FLOOR(Q + Half);
1088                         if (!(I > 0 || Radix == Q * Q)) Monot = True;
1089                         else if (I > 0) {
1090                         if (I > 1) Monot = True;
1091                         else {
1092                                 Y = Y * BInvrse;
1093                                 X = Y - U1;
1094                                 Z = Y + U1;
1095                                 }
1096                         }
1097                         else {
1098                                 Y = Q;
1099                                 X = Y - U2;
1100                                 Z = Y + U2;
1101                                 }
1102                         }
1103                 }
1104         if (Monot) printf("sqrt has passed a test for Monotonicity.\n");
1105         else {
1106                 BadCond(Defect, "");
1107                 printf("sqrt(X) is non-monotonic for X near %.7e .\n", Y);
1108                 }
1109         /*=============================================*/
1110         /*SPLIT
1111         }
1112 #include "paranoia.h"
1113 void part5(VOID){
1114 */
1115         Milestone = 80;
1116         /*=============================================*/
1117         MinSqEr = MinSqEr + Half;
1118         MaxSqEr = MaxSqEr - Half;
1119         Y = (SQRT(One + U2) - One) / U2;
1120         SqEr = (Y - One) + U2 / Eight;
1121         if (SqEr > MaxSqEr) MaxSqEr = SqEr;
1122         SqEr = Y + U2 / Eight;
1123         if (SqEr < MinSqEr) MinSqEr = SqEr;
1124         Y = ((SQRT(F9) - U2) - (One - U2)) / U1;
1125         SqEr = Y + U1 / Eight;
1126         if (SqEr > MaxSqEr) MaxSqEr = SqEr;
1127         SqEr = (Y + One) + U1 / Eight;
1128         if (SqEr < MinSqEr) MinSqEr = SqEr;
1129         OneUlp = U2;
1130         X = OneUlp;
1131         for( Indx = 1; Indx <= 3; ++Indx) {
1132                 Y = SQRT((X + U1 + X) + F9);
1133                 Y = ((Y - U2) - ((One - U2) + X)) / OneUlp;
1134                 Z = ((U1 - X) + F9) * Half * X * X / OneUlp;
1135                 SqEr = (Y + Half) + Z;
1136                 if (SqEr < MinSqEr) MinSqEr = SqEr;
1137                 SqEr = (Y - Half) + Z;
1138                 if (SqEr > MaxSqEr) MaxSqEr = SqEr;
1139                 if (((Indx == 1) || (Indx == 3))) 
1140                         X = OneUlp * Sign (X) * FLOOR(Eight / (Nine * SQRT(OneUlp)));
1141                 else {
1142                         OneUlp = U1;
1143                         X = - OneUlp;
1144                         }
1145                 }
1146         /*=============================================*/
1147         Milestone = 85;
1148         /*=============================================*/
1149         SqRWrng = False;
1150         Anomaly = False;
1151         RSqrt = Other; /* ~dgh */
1152         if (Radix != One) {
1153                 printf("Testing whether sqrt is rounded or chopped.\n");
1154                 D = FLOOR(Half + POW(Radix, One + Precision - FLOOR(Precision)));
1155         /* ... == Radix^(1 + fract) if (Precision == Integer + fract. */
1156                 X = D / Radix;
1157                 Y = D / A1;
1158                 if ((X != FLOOR(X)) || (Y != FLOOR(Y))) {
1159                         Anomaly = True;
1160                         }
1161                 else {
1162                         X = Zero;
1163                         Z2 = X;
1164                         Y = One;
1165                         Y2 = Y;
1166                         Z1 = Radix - One;
1167                         FourD = Four * D;
1168                         do  {
1169                                 if (Y2 > Z2) {
1170                                         Q = Radix;
1171                                         Y1 = Y;
1172                                         do  {
1173                                                 X1 = FABS(Q + FLOOR(Half - Q / Y1) * Y1);
1174                                                 Q = Y1;
1175                                                 Y1 = X1;
1176                                                 } while ( ! (X1 <= Zero));
1177                                         if (Q <= One) {
1178                                                 Z2 = Y2;
1179                                                 Z = Y;
1180                                                 }
1181                                         }
1182                                 Y = Y + Two;
1183                                 X = X + Eight;
1184                                 Y2 = Y2 + X;
1185                                 if (Y2 >= FourD) Y2 = Y2 - FourD;
1186                                 } while ( ! (Y >= D));
1187                         X8 = FourD - Z2;
1188                         Q = (X8 + Z * Z) / FourD;
1189                         X8 = X8 / Eight;
1190                         if (Q != FLOOR(Q)) Anomaly = True;
1191                         else {
1192                                 Break = False;
1193                                 do  {
1194                                         X = Z1 * Z;
1195                                         X = X - FLOOR(X / Radix) * Radix;
1196                                         if (X == One) 
1197                                                 Break = True;
1198                                         else
1199                                                 Z1 = Z1 - One;
1200                                         } while ( ! (Break || (Z1 <= Zero)));
1201                                 if ((Z1 <= Zero) && (! Break)) Anomaly = True;
1202                                 else {
1203                                         if (Z1 > RadixD2) Z1 = Z1 - Radix;
1204                                         do  {
1205                                                 NewD();
1206                                                 } while ( ! (U2 * D >= F9));
1207                                         if (D * Radix - D != W - D) Anomaly = True;
1208                                         else {
1209                                                 Z2 = D;
1210                                                 I = 0;
1211                                                 Y = D + (One + Z) * Half;
1212                                                 X = D + Z + Q;
1213                                                 SR3750();
1214                                                 Y = D + (One - Z) * Half + D;
1215                                                 X = D - Z + D;
1216                                                 X = X + Q + X;
1217                                                 SR3750();
1218                                                 NewD();
1219                                                 if (D - Z2 != W - Z2) Anomaly = True;
1220                                                 else {
1221                                                         Y = (D - Z2) + (Z2 + (One - Z) * Half);
1222                                                         X = (D - Z2) + (Z2 - Z + Q);
1223                                                         SR3750();
1224                                                         Y = (One + Z) * Half;
1225                                                         X = Q;
1226                                                         SR3750();
1227                                                         if (I == 0) Anomaly = True;
1228                                                         }
1229                                                 }
1230                                         }
1231                                 }
1232                         }
1233                 if ((I == 0) || Anomaly) {
1234                         BadCond(Failure, "Anomalous arithmetic with Integer < ");
1235                         printf("Radix^Precision = %.7e\n", W);
1236                         printf(" fails test whether sqrt rounds or chops.\n");
1237                         SqRWrng = True;
1238                         }
1239                 }
1240         if (! Anomaly) {
1241                 if (! ((MinSqEr < Zero) || (MaxSqEr > Zero))) {
1242                         RSqrt = Rounded;
1243                         printf("Square root appears to be correctly rounded.\n");
1244                         }
1245                 else  {
1246                         if ((MaxSqEr + U2 > U2 - Half) || (MinSqEr > Half)
1247                                 || (MinSqEr + Radix < Half)) SqRWrng = True;
1248                         else {
1249                                 RSqrt = Chopped;
1250                                 printf("Square root appears to be chopped.\n");
1251                                 }
1252                         }
1253                 }
1254         if (SqRWrng) {
1255                 printf("Square root is neither chopped nor correctly rounded.\n");
1256                 printf("Observed errors run from %.7e ", MinSqEr - Half);
1257                 printf("to %.7e ulps.\n", Half + MaxSqEr);
1258                 TstCond (Serious, MaxSqEr - MinSqEr < Radix * Radix,
1259                         "sqrt gets too many last digits wrong");
1260                 }
1261         /*=============================================*/
1262         Milestone = 90;
1263         /*=============================================*/
1264         Pause();
1265         printf("Testing powers Z^i for small Integers Z and i.\n");
1266         N = 0;
1267         /* ... test powers of zero. */
1268         I = 0;
1269         Z = -Zero;
1270         M = 3;
1271         Break = False;
1272         do  {
1273                 X = One;
1274                 SR3980();
1275                 if (I <= 10) {
1276                         I = 1023;
1277                         SR3980();
1278                         }
1279                 if (Z == MinusOne) Break = True;
1280                 else {
1281                         Z = MinusOne;
1282                         /* .. if(-1)^N is invalid, replace MinusOne by One. */
1283                         I = - 4;
1284                         }
1285                 } while ( ! Break);
1286         PrintIfNPositive();
1287         N1 = N;
1288         N = 0;
1289         Z = A1;
1290         M = (int)FLOOR(Two * LOG(W) / LOG(A1));
1291         Break = False;
1292         do  {
1293                 X = Z;
1294                 I = 1;
1295                 SR3980();
1296                 if (Z == AInvrse) Break = True;
1297                 else Z = AInvrse;
1298                 } while ( ! (Break));
1299         /*=============================================*/
1300                 Milestone = 100;
1301         /*=============================================*/
1302         /*  Powers of Radix have been tested, */
1303         /*         next try a few primes     */
1304         M = NoTrials;
1305         Z = Three;
1306         do  {
1307                 X = Z;
1308                 I = 1;
1309                 SR3980();
1310                 do  {
1311                         Z = Z + Two;
1312                         } while ( Three * FLOOR(Z / Three) == Z );
1313                 } while ( Z < Eight * Three );
1314         if (N > 0) {
1315                 printf("Errors like this may invalidate financial calculations\n");
1316                 printf("\tinvolving interest rates.\n");
1317                 }
1318         PrintIfNPositive();
1319         N += N1;
1320         if (N == 0) printf("... no discrepancies found.\n");
1321         if (N > 0) Pause();
1322         else printf("\n");
1323         /*=============================================*/
1324         /*SPLIT
1325         }
1326 #include "paranoia.h"
1327 void part6(VOID){
1328 */
1329         Milestone = 110;
1330         /*=============================================*/
1331         printf("Seeking Underflow thresholds UfThold and E0.\n");
1332         D = U1;
1333         if (Precision != FLOOR(Precision)) {
1334                 D = BInvrse;
1335                 X = Precision;
1336                 do  {
1337                         D = D * BInvrse;
1338                         X = X - One;
1339                         } while ( X > Zero);
1340                 }
1341         Y = One;
1342         Z = D;
1343         /* ... D is power of 1/Radix < 1. */
1344         do  {
1345                 C = Y;
1346                 Y = Z;
1347                 Z = Y * Y;
1348                 } while ((Y > Z) && (Z + Z > Z));
1349         Y = C;
1350         Z = Y * D;
1351         do  {
1352                 C = Y;
1353                 Y = Z;
1354                 Z = Y * D;
1355                 } while ((Y > Z) && (Z + Z > Z));
1356         if (Radix < Two) HInvrse = Two;
1357         else HInvrse = Radix;
1358         H = One / HInvrse;
1359         /* ... 1/HInvrse == H == Min(1/Radix, 1/2) */
1360         CInvrse = One / C;
1361         E0 = C;
1362         Z = E0 * H;
1363         /* ...1/Radix^(BIG Integer) << 1 << CInvrse == 1/C */
1364         do  {
1365                 Y = E0;
1366                 E0 = Z;
1367                 Z = E0 * H;
1368                 } while ((E0 > Z) && (Z + Z > Z));
1369         UfThold = E0;
1370         E1 = Zero;
1371         Q = Zero;
1372         E9 = U2;
1373         S = One + E9;
1374         D = C * S;
1375         if (D <= C) {
1376                 E9 = Radix * U2;
1377                 S = One + E9;
1378                 D = C * S;
1379                 if (D <= C) {
1380                         BadCond(Failure, "multiplication gets too many last digits wrong.\n");
1381                         Underflow = E0;
1382                         Y1 = Zero;
1383                         PseudoZero = Z;
1384                         Pause();
1385                         }
1386                 }
1387         else {
1388                 Underflow = D;
1389                 PseudoZero = Underflow * H;
1390                 UfThold = Zero;
1391                 do  {
1392                         Y1 = Underflow;
1393                         Underflow = PseudoZero;
1394                         if (E1 + E1 <= E1) {
1395                                 Y2 = Underflow * HInvrse;
1396                                 E1 = FABS(Y1 - Y2);
1397                                 Q = Y1;
1398                                 if ((UfThold == Zero) && (Y1 != Y2)) UfThold = Y1;
1399                                 }
1400                         PseudoZero = PseudoZero * H;
1401                         } while ((Underflow > PseudoZero)
1402                                 && (PseudoZero + PseudoZero > PseudoZero));
1403                 }
1404         /* Comment line 4530 .. 4560 */
1405         if (PseudoZero != Zero) {
1406                 printf("\n");
1407                 Z = PseudoZero;
1408         /* ... Test PseudoZero for "phoney- zero" violates */
1409         /* ... PseudoZero < Underflow or PseudoZero < PseudoZero + PseudoZero
1410                    ... */
1411                 if (PseudoZero <= Zero) {
1412                         BadCond(Failure, "Positive expressions can underflow to an\n");
1413                         printf("allegedly negative value\n");
1414                         printf("PseudoZero that prints out as: %g .\n", PseudoZero);
1415                         X = - PseudoZero;
1416                         if (X <= Zero) {
1417                                 printf("But -PseudoZero, which should be\n");
1418                                 printf("positive, isn't; it prints out as  %g .\n", X);
1419                                 }
1420                         }
1421                 else {
1422                         BadCond(Flaw, "Underflow can stick at an allegedly positive\n");
1423                         printf("value PseudoZero that prints out as %g .\n", PseudoZero);
1424                         }
1425                 TstPtUf();
1426                 }
1427         /*=============================================*/
1428         Milestone = 120;
1429         /*=============================================*/
1430         if (CInvrse * Y > CInvrse * Y1) {
1431                 S = H * S;
1432                 E0 = Underflow;
1433                 }
1434         if (! ((E1 == Zero) || (E1 == E0))) {
1435                 BadCond(Defect, "");
1436                 if (E1 < E0) {
1437                         printf("Products underflow at a higher");
1438                         printf(" threshold than differences.\n");
1439                         if (PseudoZero == Zero) 
1440                         E0 = E1;
1441                         }
1442                 else {
1443                         printf("Difference underflows at a higher");
1444                         printf(" threshold than products.\n");
1445                         }
1446                 }
1447         printf("Smallest strictly positive number found is E0 = %g .\n", E0);
1448         Z = E0;
1449         TstPtUf();
1450         Underflow = E0;
1451         if (N == 1) Underflow = Y;
1452         I = 4;
1453         if (E1 == Zero) I = 3;
1454         if (UfThold == Zero) I = I - 2;
1455         UfNGrad = True;
1456         switch (I)  {
1457                 case    1:
1458                 UfThold = Underflow;
1459                 if ((CInvrse * Q) != ((CInvrse * Y) * S)) {
1460                         UfThold = Y;
1461                         BadCond(Failure, "Either accuracy deteriorates as numbers\n");
1462                         printf("approach a threshold = %.17e\n", UfThold);;
1463                         printf(" coming down from %.17e\n", C);
1464                         printf(" or else multiplication gets too many last digits wrong.\n");
1465                         }
1466                 Pause();
1467                 break;
1468         
1469                 case    2:
1470                 BadCond(Failure, "Underflow confuses Comparison, which alleges that\n");
1471                 printf("Q == Y while denying that |Q - Y| == 0; these values\n");
1472                 printf("print out as Q = %.17e, Y = %.17e .\n", Q, Y2);
1473                 printf ("|Q - Y| = %.17e .\n" , FABS(Q - Y2));
1474                 UfThold = Q;
1475                 break;
1476         
1477                 case    3:
1478                 X = X;
1479                 break;
1480         
1481                 case    4:
1482                 if ((Q == UfThold) && (E1 == E0)
1483                         && (FABS( UfThold - E1 / E9) <= E1)) {
1484                         UfNGrad = False;
1485                         printf("Underflow is gradual; it incurs Absolute Error =\n");
1486                         printf("(roundoff in UfThold) < E0.\n");
1487                         Y = E0 * CInvrse;
1488                         Y = Y * (OneAndHalf + U2);
1489                         X = CInvrse * (One + U2);
1490                         Y = Y / X;
1491                         IEEE = (Y == E0);
1492                         }
1493                 }
1494         if (UfNGrad) {
1495                 printf("\n");
1496                 sigsave = sigfpe;
1497                 if (setjmp(ovfl_buf)) {
1498                         printf("Underflow / UfThold failed!\n");
1499                         R = H + H;
1500                         }
1501                 else R = SQRT(Underflow / UfThold);
1502                 sigsave = 0;
1503                 if (R <= H) {
1504                         Z = R * UfThold;
1505                         X = Z * (One + R * H * (One + H));
1506                         }
1507                 else {
1508                         Z = UfThold;
1509                         X = Z * (One + H * H * (One + H));
1510                         }
1511                 if (! ((X == Z) || (X - Z != Zero))) {
1512                         BadCond(Flaw, "");
1513                         printf("X = %.17e\n\tis not equal to Z = %.17e .\n", X, Z);
1514                         Z9 = X - Z;
1515                         printf("yet X - Z yields %.17e .\n", Z9);
1516                         printf("    Should this NOT signal Underflow, ");
1517                         printf("this is a SERIOUS DEFECT\nthat causes ");
1518                         printf("confusion when innocent statements like\n");;
1519                         printf("    if (X == Z)  ...  else");
1520                         printf("  ... (f(X) - f(Z)) / (X - Z) ...\n");
1521                         printf("encounter Division by Zero although actually\n");
1522                         sigsave = sigfpe;
1523                         if (setjmp(ovfl_buf)) printf("X / Z fails!\n");
1524                         else printf("X / Z = 1 + %g .\n", (X / Z - Half) - Half);
1525                         sigsave = 0;
1526                         }
1527                 }
1528         printf("The Underflow threshold is %.17e, %s\n", UfThold,
1529                    " below which");
1530         printf("calculation may suffer larger Relative error than ");
1531         printf("merely roundoff.\n");
1532         Y2 = U1 * U1;
1533         Y = Y2 * Y2;
1534         Y2 = Y * U1;
1535         if (Y2 <= UfThold) {
1536                 if (Y > E0) {
1537                         BadCond(Defect, "");
1538                         I = 5;
1539                         }
1540                 else {
1541                         BadCond(Serious, "");
1542                         I = 4;
1543                         }
1544                 printf("Range is too narrow; U1^%d Underflows.\n", I);
1545                 }
1546         /*=============================================*/
1547         /*SPLIT
1548         }
1549 #include "paranoia.h"
1550 void part7(VOID){
1551 */
1552         Milestone = 130;
1553         /*=============================================*/
1554         Y = - FLOOR(Half - TwoForty * LOG(UfThold) / LOG(HInvrse)) / TwoForty;
1555         Y2 = Y + Y;
1556         printf("Since underflow occurs below the threshold\n");
1557         printf("UfThold = (%.17e) ^ (%.17e)\nonly underflow ", HInvrse, Y);
1558         printf("should afflict the expression\n\t(%.17e) ^ (%.17e);\n",
1559                 HInvrse, Y2);
1560         printf("actually calculating yields:");
1561         if (setjmp(ovfl_buf)) {
1562                 sigsave = 0;
1563                 BadCond(Serious, "trap on underflow.\n");
1564                 }
1565         else {
1566                 sigsave = sigfpe;
1567                 V9 = POW(HInvrse, Y2);
1568                 sigsave = 0;
1569                 printf(" %.17e .\n", V9);
1570                 if (! ((V9 >= Zero) && (V9 <= (Radix + Radix + E9) * UfThold))) {
1571                         BadCond(Serious, "this is not between 0 and underflow\n");
1572                 printf("   threshold = %.17e .\n", UfThold);
1573                 }
1574                 else if (! (V9 > UfThold * (One + E9)))
1575                         printf("This computed value is O.K.\n");
1576                 else {
1577                         BadCond(Defect, "this is not between 0 and underflow\n");
1578                         printf("   threshold = %.17e .\n", UfThold);
1579                         }
1580                 }
1581         /*=============================================*/
1582         Milestone = 140;
1583         /*=============================================*/
1584         printf("\n");
1585         /* ...calculate Exp2 == exp(2) == 7.389056099... */
1586         X = Zero;
1587         I = 2;
1588         Y = Two * Three;
1589         Q = Zero;
1590         N = 0;
1591         do  {
1592                 Z = X;
1593                 I = I + 1;
1594                 Y = Y / (I + I);
1595                 R = Y + Q;
1596                 X = Z + R;
1597                 Q = (Z - X) + R;
1598                 } while(X > Z);
1599         Z = (OneAndHalf + One / Eight) + X / (OneAndHalf * ThirtyTwo);
1600         X = Z * Z;
1601         Exp2 = X * X;
1602         X = F9;
1603         Y = X - U1;
1604         printf("Testing X^((X + 1) / (X - 1)) vs. exp(2) = %.17e as X -> 1.\n",
1605                 Exp2);
1606         for(I = 1;;) {
1607                 Z = X - BInvrse;
1608                 Z = (X + One) / (Z - (One - BInvrse));
1609                 Q = POW(X, Z) - Exp2;
1610                 if (FABS(Q) > TwoForty * U2) {
1611                         N = 1;
1612                         V9 = (X - BInvrse) - (One - BInvrse);
1613                         BadCond(Defect, "Calculated");
1614                         printf(" %.17e for\n", POW(X,Z));
1615                         printf("\t(1 + (%.17e) ^ (%.17e);\n", V9, Z);
1616                         printf("\tdiffers from correct value by %.17e .\n", Q);
1617                         printf("\tThis much error may spoil financial\n");
1618                         printf("\tcalculations involving tiny interest rates.\n");
1619                         break;
1620                         }
1621                 else {
1622                         Z = (Y - X) * Two + Y;
1623                         X = Y;
1624                         Y = Z;
1625                         Z = One + (X - F9)*(X - F9);
1626                         if (Z > One && I < NoTrials) I++;
1627                         else  {
1628                                 if (X > One) {
1629                                         if (N == 0)
1630                                            printf("Accuracy seems adequate.\n");
1631                                         break;
1632                                         }
1633                                 else {
1634                                         X = One + U2;
1635                                         Y = U2 + U2;
1636                                         Y += X;
1637                                         I = 1;
1638                                         }
1639                                 }
1640                         }
1641                 }
1642         /*=============================================*/
1643         Milestone = 150;
1644         /*=============================================*/
1645         printf("Testing powers Z^Q at four nearly extreme values.\n");
1646         N = 0;
1647         Z = A1;
1648         Q = FLOOR(Half - LOG(C) / LOG(A1));
1649         Break = False;
1650         do  {
1651                 X = CInvrse;
1652                 Y = POW(Z, Q);
1653                 IsYeqX();
1654                 Q = - Q;
1655                 X = C;
1656                 Y = POW(Z, Q);
1657                 IsYeqX();
1658                 if (Z < One) Break = True;
1659                 else Z = AInvrse;
1660                 } while ( ! (Break));
1661         PrintIfNPositive();
1662         if (N == 0) printf(" ... no discrepancies found.\n");
1663         printf("\n");
1664         
1665         /*=============================================*/
1666         Milestone = 160;
1667         /*=============================================*/
1668         Pause();
1669         printf("Searching for Overflow threshold:\n");
1670         printf("This may generate an error.\n");
1671         Y = - CInvrse;
1672         V9 = HInvrse * Y;
1673         sigsave = sigfpe;
1674         if (setjmp(ovfl_buf)) { I = 0; V9 = Y; goto overflow; }
1675         do {
1676                 V = Y;
1677                 Y = V9;
1678                 V9 = HInvrse * Y;
1679                 } while(V9 < Y);
1680         I = 1;
1681 overflow:
1682         sigsave = 0;
1683         Z = V9;
1684         printf("Can `Z = -Y' overflow?\n");
1685         printf("Trying it on Y = %.17e .\n", Y);
1686         V9 = - Y;
1687         V0 = V9;
1688         if (V - Y == V + V0) printf("Seems O.K.\n");
1689         else {
1690                 printf("finds a ");
1691                 BadCond(Flaw, "-(-Y) differs from Y.\n");
1692                 }
1693         if (Z != Y) {
1694                 BadCond(Serious, "");
1695                 printf("overflow past %.17e\n\tshrinks to %.17e .\n", Y, Z);
1696                 }
1697         if (I) {
1698                 Y = V * (HInvrse * U2 - HInvrse);
1699                 Z = Y + ((One - HInvrse) * U2) * V;
1700                 if (Z < V0) Y = Z;
1701                 if (Y < V0) V = Y;
1702                 if (V0 - V < V0) V = V0;
1703                 }
1704         else {
1705                 V = Y * (HInvrse * U2 - HInvrse);
1706                 V = V + ((One - HInvrse) * U2) * Y;
1707                 }
1708         printf("Overflow threshold is V  = %.17e .\n", V);
1709         if (I) printf("Overflow saturates at V0 = %.17e .\n", V0);
1710         else printf("There is no saturation value because \
1711 the system traps on overflow.\n");
1712         V9 = V * One;
1713         printf("No Overflow should be signaled for V * 1 = %.17e\n", V9);
1714         V9 = V / One;
1715         printf("                           nor for V / 1 = %.17e .\n", V9);
1716         printf("Any overflow signal separating this * from the one\n");
1717         printf("above is a DEFECT.\n");
1718         /*=============================================*/
1719         Milestone = 170;
1720         /*=============================================*/
1721         if (!(-V < V && -V0 < V0 && -UfThold < V && UfThold < V)) {
1722                 BadCond(Failure, "Comparisons involving ");
1723                 printf("+-%g, +-%g\nand +-%g are confused by Overflow.",
1724                         V, V0, UfThold);
1725                 }
1726         /*=============================================*/
1727         Milestone = 175;
1728         /*=============================================*/
1729         printf("\n");
1730         for(Indx = 1; Indx <= 3; ++Indx) {
1731                 switch (Indx)  {
1732                         case 1: Z = UfThold; break;
1733                         case 2: Z = E0; break;
1734                         case 3: Z = PseudoZero; break;
1735                         }
1736                 if (Z != Zero) {
1737                         V9 = SQRT(Z);
1738                         Y = V9 * V9;
1739                         if (Y / (One - Radix * E9) < Z
1740                            || Y > (One + Radix * E9) * Z) { /* dgh: + E9 --> * E9 */
1741                                 if (V9 > U1) BadCond(Serious, "");
1742                                 else BadCond(Defect, "");
1743                                 printf("Comparison alleges that what prints as Z = %.17e\n", Z);
1744                                 printf(" is too far from sqrt(Z) ^ 2 = %.17e .\n", Y);
1745                                 }
1746                         }
1747                 }
1748         /*=============================================*/
1749         Milestone = 180;
1750         /*=============================================*/
1751         for(Indx = 1; Indx <= 2; ++Indx) {
1752                 if (Indx == 1) Z = V;
1753                 else Z = V0;
1754                 V9 = SQRT(Z);
1755                 X = (One - Radix * E9) * V9;
1756                 V9 = V9 * X;
1757                 if (((V9 < (One - Two * Radix * E9) * Z) || (V9 > Z))) {
1758                         Y = V9;
1759                         if (X < W) BadCond(Serious, "");
1760                         else BadCond(Defect, "");
1761                         printf("Comparison alleges that Z = %17e\n", Z);
1762                         printf(" is too far from sqrt(Z) ^ 2 (%.17e) .\n", Y);
1763                         }
1764                 }
1765         /*=============================================*/
1766         /*SPLIT
1767         }
1768 #include "paranoia.h"
1769 int part8(VOID){
1770 */
1771         Milestone = 190;
1772         /*=============================================*/
1773         Pause();
1774         X = UfThold * V;
1775         Y = Radix * Radix;
1776         if (X*Y < One || X > Y) {
1777                 if (X * Y < U1 || X > Y/U1) BadCond(Defect, "Badly");
1778                 else BadCond(Flaw, "");
1779                         
1780                 printf(" unbalanced range; UfThold * V = %.17e\n\t%s\n",
1781                         X, "is too far from 1.\n");
1782                 }
1783         /*=============================================*/
1784         Milestone = 200;
1785         /*=============================================*/
1786         for (Indx = 1; Indx <= 5; ++Indx)  {
1787                 X = F9;
1788                 switch (Indx)  {
1789                         case 2: X = One + U2; break;
1790                         case 3: X = V; break;
1791                         case 4: X = UfThold; break;
1792                         case 5: X = Radix;
1793                         }
1794                 Y = X;
1795                 sigsave = sigfpe;
1796                 if (setjmp(ovfl_buf))
1797                         printf("  X / X  traps when X = %g\n", X);
1798                 else {
1799                         V9 = (Y / X - Half) - Half;
1800                         if (V9 == Zero) continue;
1801                         if (V9 == - U1 && Indx < 5) BadCond(Flaw, "");
1802                         else BadCond(Serious, "");
1803                         printf("  X / X differs from 1 when X = %.17e\n", X);
1804                         printf("  instead, X / X - 1/2 - 1/2 = %.17e .\n", V9);
1805                         }
1806                 sigsave = 0;
1807                 }
1808         /*=============================================*/
1809         Milestone = 210;
1810         /*=============================================*/
1811         MyZero = Zero;
1812         printf("\n");
1813         printf("What message and/or values does Division by Zero produce?\n") ;
1814 #ifndef NOPAUSE
1815         printf("This can interupt your program.  You can ");
1816         printf("skip this part if you wish.\n");
1817         printf("Do you wish to compute 1 / 0? ");
1818         fflush(stdout);
1819         read (KEYBOARD, ch, 8);
1820         if ((ch[0] == 'Y') || (ch[0] == 'y')) {
1821 #endif
1822                 sigsave = sigfpe;
1823                 printf("    Trying to compute 1 / 0 produces ...");
1824                 if (!setjmp(ovfl_buf)) printf("  %.7e .\n", One / MyZero);
1825                 sigsave = 0;
1826 #ifndef NOPAUSE
1827                 }
1828         else printf("O.K.\n");
1829         printf("\nDo you wish to compute 0 / 0? ");
1830         fflush(stdout);
1831         read (KEYBOARD, ch, 80);
1832         if ((ch[0] == 'Y') || (ch[0] == 'y')) {
1833 #endif
1834                 sigsave = sigfpe;
1835                 printf("\n    Trying to compute 0 / 0 produces ...");
1836                 if (!setjmp(ovfl_buf)) printf("  %.7e .\n", Zero / MyZero);
1837                 sigsave = 0;
1838 #ifndef NOPAUSE
1839                 }
1840         else printf("O.K.\n");
1841 #endif
1842         /*=============================================*/
1843         Milestone = 220;
1844         /*=============================================*/
1845         Pause();
1846         printf("\n");
1847         {
1848                 static char *msg[] = {
1849                         "FAILUREs  encountered =",
1850                         "SERIOUS DEFECTs  discovered =",
1851                         "DEFECTs  discovered =",
1852                         "FLAWs  discovered =" };
1853                 int i;
1854                 for(i = 0; i < 4; i++) if (ErrCnt[i])
1855                         printf("The number of  %-29s %d.\n",
1856                                 msg[i], ErrCnt[i]);
1857                 }
1858         printf("\n");
1859         if ((ErrCnt[Failure] + ErrCnt[Serious] + ErrCnt[Defect]
1860                         + ErrCnt[Flaw]) > 0) {
1861                 if ((ErrCnt[Failure] + ErrCnt[Serious] + ErrCnt[
1862                         Defect] == 0) && (ErrCnt[Flaw] > 0)) {
1863                         printf("The arithmetic diagnosed seems ");
1864                         printf("Satisfactory though flawed.\n");
1865                         }
1866                 if ((ErrCnt[Failure] + ErrCnt[Serious] == 0)
1867                         && ( ErrCnt[Defect] > 0)) {
1868                         printf("The arithmetic diagnosed may be Acceptable\n");
1869                         printf("despite inconvenient Defects.\n");
1870                         }
1871                 if ((ErrCnt[Failure] + ErrCnt[Serious]) > 0) {
1872                         printf("The arithmetic diagnosed has ");
1873                         printf("unacceptable Serious Defects.\n");
1874                         }
1875                 if (ErrCnt[Failure] > 0) {
1876                         printf("Potentially fatal FAILURE may have spoiled this");
1877                         printf(" program's subsequent diagnoses.\n");
1878                         }
1879                 }
1880         else {
1881                 printf("No failures, defects nor flaws have been discovered.\n");
1882                 if (! ((RMult == Rounded) && (RDiv == Rounded)
1883                         && (RAddSub == Rounded) && (RSqrt == Rounded))) 
1884                         printf("The arithmetic diagnosed seems Satisfactory.\n");
1885                 else {
1886                         if (StickyBit >= One &&
1887                                 (Radix - Two) * (Radix - Nine - One) == Zero) {
1888                                 printf("Rounding appears to conform to ");
1889                                 printf("the proposed IEEE standard P");
1890                                 if ((Radix == Two) &&
1891                                          ((Precision - Four * Three * Two) *
1892                                           ( Precision - TwentySeven -
1893                                            TwentySeven + One) == Zero)) 
1894                                         printf("754");
1895                                 else printf("854");
1896                                 if (IEEE) printf(".\n");
1897                                 else {
1898                                         printf(",\nexcept for possibly Double Rounding");
1899                                         printf(" during Gradual Underflow.\n");
1900                                         }
1901                                 }
1902                         printf("The arithmetic diagnosed appears to be Excellent!\n");
1903                         }
1904                 }
1905         if (fpecount)
1906                 printf("\nA total of %d floating point exceptions were registered.\n",
1907                         fpecount);
1908         printf("END OF TEST.\n");
1909         return 0;
1910         }
1911
1912 /*SPLIT subs.c
1913 #include "paranoia.h"
1914 */
1915
1916  FLOAT
1917 Sign (FP X)
1918 #ifdef KR_headers
1919 FLOAT X;
1920 #endif
1921 { return X >= 0. ? 1.0 : -1.0; }
1922
1923  void
1924 Pause(VOID)
1925 {
1926 #ifndef NOPAUSE
1927         char ch[8];
1928
1929         printf("\nTo continue, press RETURN");
1930         fflush(stdout);
1931         read(KEYBOARD, ch, 8);
1932 #endif
1933         printf("\nDiagnosis resumes after milestone Number %d", Milestone);
1934         printf("          Page: %d\n\n", PageNo);
1935         ++Milestone;
1936         ++PageNo;
1937         }
1938
1939  void
1940 TstCond (INT K, INT Valid, CHARP T)
1941 #ifdef KR_headers
1942 int K, Valid;
1943 char *T;
1944 #endif
1945 { if (! Valid) { BadCond(K,T); printf(".\n"); } }
1946
1947  void
1948 BadCond(INT K, CHARP T)
1949 #ifdef KR_headers
1950 int K;
1951 char *T;
1952 #endif
1953 {
1954         static char *msg[] = { "FAILURE", "SERIOUS DEFECT", "DEFECT", "FLAW" };
1955
1956         ErrCnt [K] = ErrCnt [K] + 1;
1957         printf("%s:  %s", msg[K], T);
1958         }
1959
1960
1961  FLOAT
1962 Random(VOID)
1963 /*  Random computes
1964      X = (Random1 + Random9)^5
1965      Random1 = X - FLOOR(X) + 0.000005 * X;
1966    and returns the new value of Random1
1967 */
1968 {
1969         FLOAT X, Y;
1970         
1971         X = Random1 + Random9;
1972         Y = X * X;
1973         Y = Y * Y;
1974         X = X * Y;
1975         Y = X - FLOOR(X);
1976         Random1 = Y + X * 0.000005;
1977         return(Random1);
1978         }
1979
1980  void
1981 SqXMinX (INT ErrKind)
1982 #ifdef KR_headers
1983 int ErrKind;
1984 #endif
1985 {
1986         FLOAT XA, XB;
1987         
1988         XB = X * BInvrse;
1989         XA = X - XB;
1990         SqEr = ((SQRT(X * X) - XB) - XA) / OneUlp;
1991         if (SqEr != Zero) {
1992                 if (SqEr < MinSqEr) MinSqEr = SqEr;
1993                 if (SqEr > MaxSqEr) MaxSqEr = SqEr;
1994                 J = J + 1.0;
1995                 BadCond(ErrKind, "\n");
1996                 printf("sqrt( %.17e) - %.17e  = %.17e\n", X * X, X, OneUlp * SqEr);
1997                 printf("\tinstead of correct value 0 .\n");
1998                 }
1999         }
2000
2001  void
2002 NewD(VOID)
2003 {
2004         X = Z1 * Q;
2005         X = FLOOR(Half - X / Radix) * Radix + X;
2006         Q = (Q - X * Z) / Radix + X * X * (D / Radix);
2007         Z = Z - Two * X * D;
2008         if (Z <= Zero) {
2009                 Z = - Z;
2010                 Z1 = - Z1;
2011                 }
2012         D = Radix * D;
2013         }
2014
2015  void
2016 SR3750(VOID)
2017 {
2018         if (! ((X - Radix < Z2 - Radix) || (X - Z2 > W - Z2))) {
2019                 I = I + 1;
2020                 X2 = SQRT(X * D);
2021                 Y2 = (X2 - Z2) - (Y - Z2);
2022                 X2 = X8 / (Y - Half);
2023                 X2 = X2 - Half * X2 * X2;
2024                 SqEr = (Y2 + Half) + (Half - X2);
2025                 if (SqEr < MinSqEr) MinSqEr = SqEr;
2026                 SqEr = Y2 - X2;
2027                 if (SqEr > MaxSqEr) MaxSqEr = SqEr;
2028                 }
2029         }
2030
2031  void
2032 IsYeqX(VOID)
2033 {
2034         if (Y != X) {
2035                 if (N <= 0) {
2036                         if (Z == Zero && Q <= Zero)
2037                                 printf("WARNING:  computing\n");
2038                         else BadCond(Defect, "computing\n");
2039                         printf("\t(%.17e) ^ (%.17e)\n", Z, Q);
2040                         printf("\tyielded %.17e;\n", Y);
2041                         printf("\twhich compared unequal to correct %.17e ;\n",
2042                                 X);
2043                         printf("\t\tthey differ by %.17e .\n", Y - X);
2044                         }
2045                 N = N + 1; /* ... count discrepancies. */
2046                 }
2047         }
2048
2049  void
2050 SR3980(VOID)
2051 {
2052         do {
2053                 Q = (FLOAT) I;
2054                 Y = POW(Z, Q);
2055                 IsYeqX();
2056                 if (++I > M) break;
2057                 X = Z * X;
2058                 } while ( X < W );
2059         }
2060
2061  void
2062 PrintIfNPositive(VOID)
2063 {
2064         if (N > 0) printf("Similar discrepancies have occurred %d times.\n", N);
2065         }
2066
2067  void
2068 TstPtUf(VOID)
2069 {
2070         N = 0;
2071         if (Z != Zero) {
2072                 printf("Since comparison denies Z = 0, evaluating ");
2073                 printf("(Z + Z) / Z should be safe.\n");
2074                 sigsave = sigfpe;
2075                 if (setjmp(ovfl_buf)) goto very_serious;
2076                 Q9 = (Z + Z) / Z;
2077                 printf("What the machine gets for (Z + Z) / Z is  %.17e .\n",
2078                         Q9);
2079                 if (FABS(Q9 - Two) < Radix * U2) {
2080                         printf("This is O.K., provided Over/Underflow");
2081                         printf(" has NOT just been signaled.\n");
2082                         }
2083                 else {
2084                         if ((Q9 < One) || (Q9 > Two)) {
2085 very_serious:
2086                                 N = 1;
2087                                 ErrCnt [Serious] = ErrCnt [Serious] + 1;
2088                                 printf("This is a VERY SERIOUS DEFECT!\n");
2089                                 }
2090                         else {
2091                                 N = 1;
2092                                 ErrCnt [Defect] = ErrCnt [Defect] + 1;
2093                                 printf("This is a DEFECT!\n");
2094                                 }
2095                         }
2096                 sigsave = 0;
2097                 V9 = Z * One;
2098                 Random1 = V9;
2099                 V9 = One * Z;
2100                 Random2 = V9;
2101                 V9 = Z / One;
2102                 if ((Z == Random1) && (Z == Random2) && (Z == V9)) {
2103                         if (N > 0) Pause();
2104                         }
2105                 else {
2106                         N = 1;
2107                         BadCond(Defect, "What prints as Z = ");
2108                         printf("%.17e\n\tcompares different from  ", Z);
2109                         if (Z != Random1) printf("Z * 1 = %.17e ", Random1);
2110                         if (! ((Z == Random2)
2111                                 || (Random2 == Random1)))
2112                                 printf("1 * Z == %g\n", Random2);
2113                         if (! (Z == V9)) printf("Z / 1 = %.17e\n", V9);
2114                         if (Random2 != Random1) {
2115                                 ErrCnt [Defect] = ErrCnt [Defect] + 1;
2116                                 BadCond(Defect, "Multiplication does not commute!\n");
2117                                 printf("\tComparison alleges that 1 * Z = %.17e\n",
2118                                         Random2);
2119                                 printf("\tdiffers from Z * 1 = %.17e\n", Random1);
2120                                 }
2121                         Pause();
2122                         }
2123                 }
2124         }
2125
2126  void
2127 notify(CHARP s)
2128 #ifdef KR_headers
2129  char *s;
2130 #endif
2131 {
2132         printf("%s test appears to be inconsistent...\n", s);
2133         printf("   PLEASE NOTIFY KARPINKSI!\n");
2134         }
2135
2136 /*SPLIT msgs.c
2137 #include "paranoia.h"
2138 */
2139
2140  void
2141 msglist(CHARPP s)
2142 #ifdef KR_headers
2143 char **s;
2144 #endif
2145 { while(*s) printf("%s\n", *s++); }
2146
2147  void
2148 Instructions(VOID)
2149 {
2150   static char *instr[] = {
2151         "Lest this program stop prematurely, i.e. before displaying\n",
2152         "    `END OF TEST',\n",
2153         "try to persuade the computer NOT to terminate execution when an",
2154         "error like Over/Underflow or Division by Zero occurs, but rather",
2155         "to persevere with a surrogate value after, perhaps, displaying some",
2156         "warning.  If persuasion avails naught, don't despair but run this",
2157         "program anyway to see how many milestones it passes, and then",
2158         "amend it to make further progress.\n",
2159         "Answer questions with Y, y, N or n (unless otherwise indicated).\n",
2160         0};
2161
2162         msglist(instr);
2163         }
2164
2165  void
2166 Heading(VOID)
2167 {
2168   static char *head[] = {
2169         "Users are invited to help debug and augment this program so it will",
2170         "cope with unanticipated and newly uncovered arithmetic pathologies.\n",
2171         "Please send suggestions and interesting results to",
2172         "\tRichard Karpinski",
2173         "\tComputer Center U-76",
2174         "\tUniversity of California",
2175         "\tSan Francisco, CA 94143-0704, USA\n",
2176         "In doing so, please include the following information:",
2177 #ifdef Single
2178         "\tPrecision:\tsingle;",
2179 #else
2180         "\tPrecision:\tdouble;",
2181 #endif
2182         "\tVersion:\t10 February 1989;",
2183         "\tComputer:\n",
2184         "\tCompiler:\n",
2185         "\tOptimization level:\n",
2186         "\tOther relevant compiler options:",
2187         0};
2188
2189         msglist(head);
2190         }
2191
2192  void
2193 Characteristics(VOID)
2194 {
2195         static char *chars[] = {
2196          "Running this program should reveal these characteristics:",
2197         "     Radix = 1, 2, 4, 8, 10, 16, 100, 256 ...",
2198         "     Precision = number of significant digits carried.",
2199         "     U2 = Radix/Radix^Precision = One Ulp",
2200         "\t(OneUlpnit in the Last Place) of 1.000xxx .",
2201         "     U1 = 1/Radix^Precision = One Ulp of numbers a little less than 1.0 .",
2202         "     Adequacy of guard digits for Mult., Div. and Subt.",
2203         "     Whether arithmetic is chopped, correctly rounded, or something else",
2204         "\tfor Mult., Div., Add/Subt. and Sqrt.",
2205         "     Whether a Sticky Bit used correctly for rounding.",
2206         "     UnderflowThreshold = an underflow threshold.",
2207         "     E0 and PseudoZero tell whether underflow is abrupt, gradual, or fuzzy.",
2208         "     V = an overflow threshold, roughly.",
2209         "     V0  tells, roughly, whether  Infinity  is represented.",
2210         "     Comparisions are checked for consistency with subtraction",
2211         "\tand for contamination with pseudo-zeros.",
2212         "     Sqrt is tested.  Y^X is not tested.",
2213         "     Extra-precise subexpressions are revealed but NOT YET tested.",
2214         "     Decimal-Binary conversion is NOT YET tested for accuracy.",
2215         0};
2216
2217         msglist(chars);
2218         }
2219
2220  void
2221 History(VOID)
2222 { /* History */
2223  /* Converted from Brian Wichmann's Pascal version to C by Thos Sumner,
2224         with further massaging by David M. Gay. */
2225
2226   static char *hist[] = {
2227         "The program attempts to discriminate among",
2228         "   FLAWs, like lack of a sticky bit,",
2229         "   Serious DEFECTs, like lack of a guard digit, and",
2230         "   FAILUREs, like 2+2 == 5 .",
2231         "Failures may confound subsequent diagnoses.\n",
2232         "The diagnostic capabilities of this program go beyond an earlier",
2233         "program called `MACHAR', which can be found at the end of the",
2234         "book  `Software Manual for the Elementary Functions' (1980) by",
2235         "W. J. Cody and W. Waite. Although both programs try to discover",
2236         "the Radix, Precision and range (over/underflow thresholds)",
2237         "of the arithmetic, this program tries to cope with a wider variety",
2238         "of pathologies, and to say how well the arithmetic is implemented.",
2239         "\nThe program is based upon a conventional radix representation for",
2240         "floating-point numbers, but also allows logarithmic encoding",
2241         "as used by certain early WANG machines.\n",
2242         "BASIC version of this program (C) 1983 by Prof. W. M. Kahan;",
2243         "see source comments for more history.",
2244         0};
2245
2246         msglist(hist);
2247         }

UCC git Repository :: git.ucc.asn.au