File indexing completed on 2025-05-11 08:24:42
0001 #ifdef HAVE_CONFIG_H
0002 #include "config.h"
0003 #endif
0004
0005 #define CYGNUS
0006 #define NOMAIN
0007 #define NOSIGNAL
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136
0137
0138
0139
0140
0141
0142
0143
0144
0145
0146
0147
0148
0149
0150
0151
0152
0153
0154
0155
0156
0157
0158
0159
0160 #include <stdio.h>
0161 #include <string.h>
0162 #include <math.h>
0163 #include <stdlib.h>
0164
0165
0166
0167
0168
0169
0170
0171 #ifdef NEED_REENT
0172 #include <reent.h>
0173 struct _reent libm_reent = _REENT_INIT(libm_reent);
0174 struct _reent *_impure_ptr = &libm_reent;
0175 #endif
0176
0177 #ifndef NOSIGNAL
0178 #include <signal.h>
0179 #include <setjmp.h>
0180 #else
0181 #define longjmp(e,v)
0182 #define setjmp(e) 0
0183 #define jmp_buf int
0184 #endif
0185
0186 #ifdef SINGLE_PRECISION
0187 #define FLOAT float
0188 #define FABS(x) (float)fabs((double)(x))
0189 #define FLOOR(x) (float)floor((double)(x))
0190 #define LOG(x) (float)log((double)(x))
0191 #define POW(x,y) (float)pow((double)(x),(double)(y))
0192 #define SQRT(x) (float)sqrt((double)(x))
0193 #else
0194 #define FLOAT double
0195 #define FABS(x) fabs(x)
0196 #define FLOOR(x) floor(x)
0197 #define LOG(x) log(x)
0198 #define POW(x,y) pow(x,y)
0199 #define SQRT(x) sqrt(x)
0200 #endif
0201
0202 jmp_buf ovfl_buf;
0203
0204
0205 extern void _sigfpe(int);
0206 typedef void (*Sig_type) (int);
0207 FLOAT Sign (FLOAT), Random (void);
0208 extern void BadCond (int, char*);
0209 extern void SqXMinX (int);
0210 extern void TstCond (int, int, char*);
0211 extern void notify (char *);
0212
0213 extern void Characteristics (void);
0214 extern void Heading (void);
0215 extern void History (void);
0216 extern void Instructions (void);
0217 extern void IsYeqX (void);
0218 extern void NewD (void);
0219 extern void Pause (void);
0220 extern void PrintIfNPositive (void);
0221 extern void SR3750 (void);
0222 extern void SR3980 (void);
0223 extern void TstPtUf (void);
0224
0225 void msglist(char**);
0226
0227 Sig_type sigsave;
0228
0229 #define KEYBOARD 0
0230
0231 FLOAT Radix, BInvrse, RadixD2, BMinusU2;
0232
0233
0234 FLOAT Zero = 0.0;
0235 FLOAT Half = 0.5;
0236 FLOAT One = 1.0;
0237 FLOAT Two = 2.0;
0238 FLOAT Three = 3.0;
0239 FLOAT Four = 4.0;
0240 FLOAT Five = 5.0;
0241 FLOAT Eight = 8.0;
0242 FLOAT Nine = 9.0;
0243 FLOAT TwentySeven = 27.0;
0244 FLOAT ThirtyTwo = 32.0;
0245 FLOAT TwoForty = 240.0;
0246 FLOAT MinusOne = -1.0;
0247 FLOAT OneAndHalf = 1.5;
0248
0249
0250 int NoTrials = 20;
0251 #define False 0
0252 #define True 1
0253
0254
0255
0256
0257
0258
0259
0260
0261 #define Yes 1
0262 #define No 0
0263 #define Chopped 2
0264 #define Rounded 1
0265 #define Other 0
0266 #define Flaw 3
0267 #define Defect 2
0268 #define Serious 1
0269 #define Failure 0
0270 typedef int Guard, Rounding, Class;
0271 typedef char Message;
0272
0273
0274 int Indx;
0275 char ch[8];
0276 FLOAT AInvrse, A1;
0277 FLOAT C, CInvrse;
0278 FLOAT D, FourD;
0279 FLOAT E0, E1, Exp2, E3, MinSqEr;
0280 FLOAT SqEr, MaxSqEr, E9;
0281 FLOAT Third;
0282 FLOAT F6, F9;
0283 FLOAT HVar, HInvrse;
0284 int I;
0285 FLOAT StickyBit, J;
0286 FLOAT MyZero;
0287 FLOAT Precision;
0288 FLOAT Q, Q9;
0289 FLOAT R, Random9;
0290 FLOAT T, Underflow, S;
0291 FLOAT OneUlp, UfThold, U1, U2;
0292 FLOAT V, V0, V9;
0293 FLOAT WVar;
0294 FLOAT X, X1, X2, X8, Random1;
0295 FLOAT Y, Y1, Y2, Random2;
0296 FLOAT Z, PseudoZero, Z1, Z2, Z9;
0297 int ErrCnt[4];
0298 int fpecount;
0299 int Milestone;
0300 int PageNo;
0301 int M, N, N1;
0302 Guard GMult, GDiv, GAddSub;
0303 Rounding RMult, RDiv, RAddSub, RSqrt;
0304 int Break, Done, NotMonot, Monot, Anomaly, IEEE, SqRWrng, UfNGrad;
0305
0306
0307
0308
0309
0310
0311 int batchmode;
0312
0313
0314 char *temp;
0315 char *program_name;
0316 char *program_vers;
0317
0318 #ifndef VERSION
0319 #define VERSION "1.1 [cygnus]"
0320 #endif
0321
0322 #define basename(cp) ((temp=(char *)strrchr((cp), '/')) ? temp+1 : (cp))
0323
0324 #ifndef BATCHMODE
0325 # ifdef CYGNUS
0326 # define BATCHMODE
0327 # endif
0328 #endif
0329
0330
0331 void
0332 _sigfpe (x)
0333 int x;
0334 {
0335 fpecount++;
0336 printf ("\n* * * FLOATING-POINT ERROR %d * * *\n", x);
0337 fflush (stdout);
0338 if (sigsave) {
0339 #ifndef NOSIGNAL
0340 signal (SIGFPE, sigsave);
0341 #endif
0342 sigsave = 0;
0343 longjmp (ovfl_buf, 1);
0344 }
0345 exit (1);
0346 }
0347
0348 #ifdef NOMAIN
0349 #define main paranoia
0350 int paranoia(int, char**);
0351 #endif
0352
0353 int
0354 main (argc, argv)
0355 int argc;
0356 char **argv;
0357 {
0358
0359 Zero = 0;
0360 One = 1;
0361 Two = One + One;
0362 Three = Two + One;
0363 Four = Three + One;
0364 Five = Four + One;
0365 Eight = Four + Four;
0366 Nine = Three * Three;
0367 TwentySeven = Nine * Three;
0368 ThirtyTwo = Four * Eight;
0369 TwoForty = Four * Five * Three * Four;
0370 MinusOne = -One;
0371 Half = One / Two;
0372 OneAndHalf = One + Half;
0373 ErrCnt[Failure] = 0;
0374 ErrCnt[Serious] = 0;
0375 ErrCnt[Defect] = 0;
0376 ErrCnt[Flaw] = 0;
0377 PageNo = 1;
0378
0379 #ifdef BATCHMODE
0380 batchmode = 1;
0381 #else
0382 batchmode = 0;
0383 #endif
0384
0385 program_name = basename (argv[0]);
0386 program_vers = VERSION;
0387
0388 printf ("%s version %s\n", program_name, program_vers);
0389
0390
0391 Milestone = 0;
0392
0393 #ifndef NOSIGNAL
0394 signal (SIGFPE, _sigfpe);
0395 #endif
0396
0397 if (!batchmode) {
0398 Instructions ();
0399 Pause ();
0400 Heading ();
0401 Instructions ();
0402 Pause ();
0403 Heading ();
0404 Pause ();
0405 Characteristics ();
0406 Pause ();
0407 History ();
0408 Pause ();
0409 }
0410
0411
0412 Milestone = 7;
0413
0414 printf ("Program is now RUNNING tests on small integers:\n");
0415 TstCond (Failure, (Zero + Zero == Zero) && (One - One == Zero)
0416 && (One > Zero) && (One + One == Two),
0417 "0+0 != 0, 1-1 != 0, 1 <= 0, or 1+1 != 2");
0418 Z = -Zero;
0419 if (Z != 0.0) {
0420 ErrCnt[Failure] = ErrCnt[Failure] + 1;
0421 printf ("Comparison alleges that -0.0 is Non-zero!\n");
0422 U1 = 0.001;
0423 Radix = 1;
0424 TstPtUf ();
0425 }
0426 TstCond (Failure, (Three == Two + One) && (Four == Three + One)
0427 && (Four + Two * (-Two) == Zero)
0428 && (Four - Three - One == Zero),
0429 "3 != 2+1, 4 != 3+1, 4+2*(-2) != 0, or 4-3-1 != 0");
0430 TstCond (Failure, (MinusOne == (0 - One))
0431 && (MinusOne + One == Zero) && (One + MinusOne == Zero)
0432 && (MinusOne + FABS (One) == Zero)
0433 && (MinusOne + MinusOne * MinusOne == Zero),
0434 "-1+1 != 0, (-1)+abs(1) != 0, or -1+(-1)*(-1) != 0");
0435 TstCond (Failure, Half + MinusOne + Half == Zero,
0436 "1/2 + (-1) + 1/2 != 0");
0437
0438 Milestone = 10;
0439
0440 TstCond (Failure, (Nine == Three * Three)
0441 && (TwentySeven == Nine * Three) && (Eight == Four + Four)
0442 && (ThirtyTwo == Eight * Four)
0443 && (ThirtyTwo - TwentySeven - Four - One == Zero),
0444 "9 != 3*3, 27 != 9*3, 32 != 8*4, or 32-27-4-1 != 0");
0445 TstCond (Failure, (Five == Four + One) &&
0446 (TwoForty == Four * Five * Three * Four)
0447 && (TwoForty / Three - Four * Four * Five == Zero)
0448 && (TwoForty / Four - Five * Three * Four == Zero)
0449 && (TwoForty / Five - Four * Three * Four == Zero),
0450 "5 != 4+1, 240/3 != 80, 240/4 != 60, or 240/5 != 48");
0451 if (ErrCnt[Failure] == 0) {
0452 printf ("-1, 0, 1/2, 1, 2, 3, 4, 5, 9, 27, 32 & 240 are O.K.\n");
0453 printf ("\n");
0454 }
0455 printf ("Searching for Radix and Precision.\n");
0456 WVar = One;
0457 do {
0458 WVar = WVar + WVar;
0459 Y = WVar + One;
0460 Z = Y - WVar;
0461 Y = Z - One;
0462 }
0463 while (MinusOne + FABS (Y) < Zero);
0464
0465 Precision = Zero;
0466 Y = One;
0467 do {
0468 Radix = WVar + Y;
0469 Y = Y + Y;
0470 Radix = Radix - WVar;
0471 }
0472 while (Radix == Zero);
0473 if (Radix < Two)
0474 Radix = One;
0475 printf ("Radix = %f .\n", Radix);
0476 if (Radix != 1) {
0477 WVar = One;
0478 do {
0479 Precision = Precision + One;
0480 WVar = WVar * Radix;
0481 Y = WVar + One;
0482 }
0483 while ((Y - WVar) == One);
0484 }
0485
0486
0487 U1 = One / WVar;
0488 U2 = Radix * U1;
0489 printf ("Closest relative separation found is U1 = %.7e .\n\n", U1);
0490 printf ("Recalculating radix and precision\n ");
0491
0492
0493 E0 = Radix;
0494 E1 = U1;
0495 E9 = U2;
0496 E3 = Precision;
0497
0498 X = Four / Three;
0499 Third = X - One;
0500 F6 = Half - Third;
0501 X = F6 + F6;
0502 X = FABS (X - Third);
0503 if (X < U2)
0504 X = U2;
0505
0506
0507 do {
0508 U2 = X;
0509 Y = Half * U2 + ThirtyTwo * U2 * U2;
0510 Y = One + Y;
0511 X = Y - One;
0512 }
0513 while (!((U2 <= X) || (X <= Zero)));
0514
0515
0516 X = Two / Three;
0517 F6 = X - Half;
0518 Third = F6 + F6;
0519 X = Third - Half;
0520 X = FABS (X + F6);
0521 if (X < U1)
0522 X = U1;
0523
0524
0525 do {
0526 U1 = X;
0527 Y = Half * U1 + ThirtyTwo * U1 * U1;
0528 Y = Half - Y;
0529 X = Half + Y;
0530 Y = Half - X;
0531 X = Half + Y;
0532 }
0533 while (!((U1 <= X) || (X <= Zero)));
0534
0535 if (U1 == E1)
0536 printf ("confirms closest relative separation U1 .\n");
0537 else
0538 printf ("gets better closest relative separation U1 = %.7e .\n", U1);
0539 WVar = One / U1;
0540 F9 = (Half - U1) + Half;
0541 Radix = FLOOR (0.01 + U2 / U1);
0542 if (Radix == E0)
0543 printf ("Radix confirmed.\n");
0544 else
0545 printf ("MYSTERY: recalculated Radix = %.7e .\n", Radix);
0546 TstCond (Defect, Radix <= Eight + Eight,
0547 "Radix is too big: roundoff problems");
0548 TstCond (Flaw, (Radix == Two) || (Radix == 10)
0549 || (Radix == One), "Radix is not as good as 2 or 10");
0550
0551 Milestone = 20;
0552
0553 TstCond (Failure, F9 - Half < Half,
0554 "(1-U1)-1/2 < 1/2 is FALSE, prog. fails?");
0555 X = F9;
0556 I = 1;
0557 Y = X - Half;
0558 Z = Y - Half;
0559 TstCond (Failure, (X != One)
0560 || (Z == Zero), "Comparison is fuzzy,X=1 but X-1/2-1/2 != 0");
0561 X = One + U2;
0562 I = 0;
0563
0564 Milestone = 25;
0565
0566
0567 BMinusU2 = Radix - One;
0568 BMinusU2 = (BMinusU2 - U2) + One;
0569
0570 if (Radix != One) {
0571 X = -TwoForty * LOG (U1) / LOG (Radix);
0572 Y = FLOOR (Half + X);
0573 if (FABS (X - Y) * Four < One)
0574 X = Y;
0575 Precision = X / TwoForty;
0576 Y = FLOOR (Half + Precision);
0577 if (FABS (Precision - Y) * TwoForty < Half)
0578 Precision = Y;
0579 }
0580 if ((Precision != FLOOR (Precision)) || (Radix == One)) {
0581 printf ("Precision cannot be characterized by an Integer number\n");
0582 printf ("of significant digits but, by itself, this is a minor flaw.\n");
0583 }
0584 if (Radix == One)
0585 printf ("logarithmic encoding has precision characterized solely by U1.\n");
0586 else
0587 printf ("The number of significant digits of the Radix is %f .\n",
0588 Precision);
0589 TstCond (Serious, U2 * Nine * Nine * TwoForty < One,
0590 "Precision worse than 5 decimal figures ");
0591
0592 Milestone = 30;
0593
0594
0595 X = FABS (((Four / Three - One) - One / Four) * Three - One / Four);
0596 do {
0597 Z2 = X;
0598 X = (One + (Half * Z2 + ThirtyTwo * Z2 * Z2)) - One;
0599 }
0600 while (!((Z2 <= X) || (X <= Zero)));
0601 X = Y = Z = FABS ((Three / Four - Two / Three) * Three - One / Four);
0602 do {
0603 Z1 = Z;
0604 Z = (One / Two - ((One / Two - (Half * Z1 + ThirtyTwo * Z1 * Z1))
0605 + One / Two)) + One / Two;
0606 }
0607 while (!((Z1 <= Z) || (Z <= Zero)));
0608 do {
0609 do {
0610 Y1 = Y;
0611 Y = (Half - ((Half - (Half * Y1 + ThirtyTwo * Y1 * Y1)) + Half
0612 )) + Half;
0613 }
0614 while (!((Y1 <= Y) || (Y <= Zero)));
0615 X1 = X;
0616 X = ((Half * X1 + ThirtyTwo * X1 * X1) - F9) + F9;
0617 }
0618 while (!((X1 <= X) || (X <= Zero)));
0619 if ((X1 != Y1) || (X1 != Z1)) {
0620 BadCond (Serious, "Disagreements among the values X1, Y1, Z1,\n");
0621 printf ("respectively %.7e, %.7e, %.7e,\n", X1, Y1, Z1);
0622 printf ("are symptoms of inconsistencies introduced\n");
0623 printf ("by extra-precise evaluation of arithmetic subexpressions.\n");
0624 notify ("Possibly some part of this");
0625 if ((X1 == U1) || (Y1 == U1) || (Z1 == U1))
0626 printf (
0627 "That feature is not tested further by this program.\n");
0628 } else {
0629 if ((Z1 != U1) || (Z2 != U2)) {
0630 if ((Z1 >= U1) || (Z2 >= U2)) {
0631 BadCond (Failure, "");
0632 notify ("Precision");
0633 printf ("\tU1 = %.7e, Z1 - U1 = %.7e\n", U1, Z1 - U1);
0634 printf ("\tU2 = %.7e, Z2 - U2 = %.7e\n", U2, Z2 - U2);
0635 } else {
0636 if ((Z1 <= Zero) || (Z2 <= Zero)) {
0637 printf ("Because of unusual Radix = %f", Radix);
0638 printf (", or exact rational arithmetic a result\n");
0639 printf ("Z1 = %.7e, or Z2 = %.7e ", Z1, Z2);
0640 notify ("of an\nextra-precision");
0641 }
0642 if (Z1 != Z2 || Z1 > Zero) {
0643 X = Z1 / U1;
0644 Y = Z2 / U2;
0645 if (Y > X)
0646 X = Y;
0647 Q = -LOG (X);
0648 printf ("Some subexpressions appear to be calculated extra\n");
0649 printf ("precisely with about %g extra B-digits, i.e.\n",
0650 (Q / LOG (Radix)));
0651 printf ("roughly %g extra significant decimals.\n",
0652 Q / LOG (10.));
0653 }
0654 printf ("That feature is not tested further by this program.\n");
0655 }
0656 }
0657 }
0658 Pause ();
0659
0660 Milestone = 35;
0661
0662 if (Radix >= Two) {
0663 X = WVar / (Radix * Radix);
0664 Y = X + One;
0665 Z = Y - X;
0666 T = Z + U2;
0667 X = T - Z;
0668 TstCond (Failure, X == U2,
0669 "Subtraction is not normalized X=Y,X+Z != Y+Z!");
0670 if (X == U2)
0671 printf (
0672 "Subtraction appears to be normalized, as it should be.");
0673 }
0674 printf ("\nChecking for guard digit in *, /, and -.\n");
0675 Y = F9 * One;
0676 Z = One * F9;
0677 X = F9 - Half;
0678 Y = (Y - Half) - X;
0679 Z = (Z - Half) - X;
0680 X = One + U2;
0681 T = X * Radix;
0682 R = Radix * X;
0683 X = T - Radix;
0684 X = X - Radix * U2;
0685 T = R - Radix;
0686 T = T - Radix * U2;
0687 X = X * (Radix - One);
0688 T = T * (Radix - One);
0689 if ((X == Zero) && (Y == Zero) && (Z == Zero) && (T == Zero))
0690 GMult = Yes;
0691 else {
0692 GMult = No;
0693 TstCond (Serious, False,
0694 "* lacks a Guard Digit, so 1*X != X");
0695 }
0696 Z = Radix * U2;
0697 X = One + Z;
0698 Y = FABS ((X + Z) - X * X) - U2;
0699 X = One - U2;
0700 Z = FABS ((X - U2) - X * X) - U1;
0701 TstCond (Failure, (Y <= Zero)
0702 && (Z <= Zero), "* gets too many final digits wrong.\n");
0703 Y = One - U2;
0704 X = One + U2;
0705 Z = One / Y;
0706 Y = Z - X;
0707 X = One / Three;
0708 Z = Three / Nine;
0709 X = X - Z;
0710 T = Nine / TwentySeven;
0711 Z = Z - T;
0712 TstCond (Defect, X == Zero && Y == Zero && Z == Zero,
0713 "Division lacks a Guard Digit, so error can exceed 1 ulp\n\
0714 or 1/3 and 3/9 and 9/27 may disagree");
0715 Y = F9 / One;
0716 X = F9 - Half;
0717 Y = (Y - Half) - X;
0718 X = One + U2;
0719 T = X / One;
0720 X = T - X;
0721 if ((X == Zero) && (Y == Zero) && (Z == Zero))
0722 GDiv = Yes;
0723 else {
0724 GDiv = No;
0725 TstCond (Serious, False,
0726 "Division lacks a Guard Digit, so X/1 != X");
0727 }
0728 X = One / (One + U2);
0729 Y = X - Half - Half;
0730 TstCond (Serious, Y < Zero,
0731 "Computed value of 1/1.000..1 >= 1");
0732 X = One - U2;
0733 Y = One + Radix * U2;
0734 Z = X * Radix;
0735 T = Y * Radix;
0736 R = Z / Radix;
0737 StickyBit = T / Radix;
0738 X = R - X;
0739 Y = StickyBit - Y;
0740 TstCond (Failure, X == Zero && Y == Zero,
0741 "* and/or / gets too many last digits wrong");
0742 Y = One - U1;
0743 X = One - F9;
0744 Y = One - Y;
0745 T = Radix - U2;
0746 Z = Radix - BMinusU2;
0747 T = Radix - T;
0748 if ((X == U1) && (Y == U1) && (Z == U2) && (T == U2))
0749 GAddSub = Yes;
0750 else {
0751 GAddSub = No;
0752 TstCond (Serious, False,
0753 "- lacks Guard Digit, so cancellation is obscured");
0754 }
0755 if (F9 != One && F9 - One >= Zero) {
0756 BadCond (Serious, "comparison alleges (1-U1) < 1 although\n");
0757 printf (" subtraction yields (1-U1) - 1 = 0 , thereby vitiating\n");
0758 printf (" such precautions against division by zero as\n");
0759 printf (" ... if (X == 1.0) {.....} else {.../(X-1.0)...}\n");
0760 }
0761 if (GMult == Yes && GDiv == Yes && GAddSub == Yes)
0762 printf (
0763 " *, /, and - appear to have guard digits, as they should.\n");
0764
0765 Milestone = 40;
0766
0767 Pause ();
0768 printf ("Checking rounding on multiply, divide and add/subtract.\n");
0769 RMult = Other;
0770 RDiv = Other;
0771 RAddSub = Other;
0772 RadixD2 = Radix / Two;
0773 A1 = Two;
0774 Done = False;
0775 do {
0776 AInvrse = Radix;
0777 do {
0778 X = AInvrse;
0779 AInvrse = AInvrse / A1;
0780 }
0781 while (!(FLOOR (AInvrse) != AInvrse));
0782 Done = (X == One) || (A1 > Three);
0783 if (!Done)
0784 A1 = Nine + One;
0785 }
0786 while (!(Done));
0787 if (X == One)
0788 A1 = Radix;
0789 AInvrse = One / A1;
0790 X = A1;
0791 Y = AInvrse;
0792 Done = False;
0793 do {
0794 Z = X * Y - Half;
0795 TstCond (Failure, Z == Half,
0796 "X * (1/X) differs from 1");
0797 Done = X == Radix;
0798 X = Radix;
0799 Y = One / X;
0800 }
0801 while (!(Done));
0802 Y2 = One + U2;
0803 Y1 = One - U2;
0804 X = OneAndHalf - U2;
0805 Y = OneAndHalf + U2;
0806 Z = (X - U2) * Y2;
0807 T = Y * Y1;
0808 Z = Z - X;
0809 T = T - X;
0810 X = X * Y2;
0811 Y = (Y + U2) * Y1;
0812 X = X - OneAndHalf;
0813 Y = Y - OneAndHalf;
0814 if ((X == Zero) && (Y == Zero) && (Z == Zero) && (T <= Zero)) {
0815 X = (OneAndHalf + U2) * Y2;
0816 Y = OneAndHalf - U2 - U2;
0817 Z = OneAndHalf + U2 + U2;
0818 T = (OneAndHalf - U2) * Y1;
0819 X = X - (Z + U2);
0820 StickyBit = Y * Y1;
0821 S = Z * Y2;
0822 T = T - Y;
0823 Y = (U2 - Y) + StickyBit;
0824 Z = S - (Z + U2 + U2);
0825 StickyBit = (Y2 + U2) * Y1;
0826 Y1 = Y2 * Y1;
0827 StickyBit = StickyBit - Y2;
0828 Y1 = Y1 - Half;
0829 if ((X == Zero) && (Y == Zero) && (Z == Zero) && (T == Zero)
0830 && (StickyBit == Zero) && (Y1 == Half)) {
0831 RMult = Rounded;
0832 printf ("Multiplication appears to round correctly.\n");
0833 } else if ((X + U2 == Zero) && (Y < Zero) && (Z + U2 == Zero)
0834 && (T < Zero) && (StickyBit + U2 == Zero)
0835 && (Y1 < Half)) {
0836 RMult = Chopped;
0837 printf ("Multiplication appears to chop.\n");
0838 } else
0839 printf ("* is neither chopped nor correctly rounded.\n");
0840 if ((RMult == Rounded) && (GMult == No))
0841 notify ("Multiplication");
0842 } else
0843 printf ("* is neither chopped nor correctly rounded.\n");
0844
0845 Milestone = 45;
0846
0847 Y2 = One + U2;
0848 Y1 = One - U2;
0849 Z = OneAndHalf + U2 + U2;
0850 X = Z / Y2;
0851 T = OneAndHalf - U2 - U2;
0852 Y = (T - U2) / Y1;
0853 Z = (Z + U2) / Y2;
0854 X = X - OneAndHalf;
0855 Y = Y - T;
0856 T = T / Y1;
0857 Z = Z - (OneAndHalf + U2);
0858 T = (U2 - OneAndHalf) + T;
0859 if (!((X > Zero) || (Y > Zero) || (Z > Zero) || (T > Zero))) {
0860 X = OneAndHalf / Y2;
0861 Y = OneAndHalf - U2;
0862 Z = OneAndHalf + U2;
0863 X = X - Y;
0864 T = OneAndHalf / Y1;
0865 Y = Y / Y1;
0866 T = T - (Z + U2);
0867 Y = Y - Z;
0868 Z = Z / Y2;
0869 Y1 = (Y2 + U2) / Y2;
0870 Z = Z - OneAndHalf;
0871 Y2 = Y1 - Y2;
0872 Y1 = (F9 - U1) / F9;
0873 if ((X == Zero) && (Y == Zero) && (Z == Zero) && (T == Zero)
0874 && (Y2 == Zero) && (Y2 == Zero)
0875 && (Y1 - Half == F9 - Half)) {
0876 RDiv = Rounded;
0877 printf ("Division appears to round correctly.\n");
0878 if (GDiv == No)
0879 notify ("Division");
0880 } else if ((X < Zero) && (Y < Zero) && (Z < Zero) && (T < Zero)
0881 && (Y2 < Zero) && (Y1 - Half < F9 - Half)) {
0882 RDiv = Chopped;
0883 printf ("Division appears to chop.\n");
0884 }
0885 }
0886 if (RDiv == Other)
0887 printf ("/ is neither chopped nor correctly rounded.\n");
0888 BInvrse = One / Radix;
0889 TstCond (Failure, (BInvrse * Radix - Half == Half),
0890 "Radix * ( 1 / Radix ) differs from 1");
0891
0892 Milestone = 50;
0893
0894 TstCond (Failure, ((F9 + U1) - Half == Half)
0895 && ((BMinusU2 + U2) - One == Radix - One),
0896 "Incomplete carry-propagation in Addition");
0897 X = One - U1 * U1;
0898 Y = One + U2 * (One - U2);
0899 Z = F9 - Half;
0900 X = (X - Half) - Z;
0901 Y = Y - One;
0902 if ((X == Zero) && (Y == Zero)) {
0903 RAddSub = Chopped;
0904 printf ("Add/Subtract appears to be chopped.\n");
0905 }
0906 if (GAddSub == Yes) {
0907 X = (Half + U2) * U2;
0908 Y = (Half - U2) * U2;
0909 X = One + X;
0910 Y = One + Y;
0911 X = (One + U2) - X;
0912 Y = One - Y;
0913 if ((X == Zero) && (Y == Zero)) {
0914 X = (Half + U2) * U1;
0915 Y = (Half - U2) * U1;
0916 X = One - X;
0917 Y = One - Y;
0918 X = F9 - X;
0919 Y = One - Y;
0920 if ((X == Zero) && (Y == Zero)) {
0921 RAddSub = Rounded;
0922 printf ("Addition/Subtraction appears to round correctly.\n");
0923 if (GAddSub == No)
0924 notify ("Add/Subtract");
0925 } else
0926 printf ("Addition/Subtraction neither rounds nor chops.\n");
0927 } else
0928 printf ("Addition/Subtraction neither rounds nor chops.\n");
0929 } else
0930 printf ("Addition/Subtraction neither rounds nor chops.\n");
0931 S = One;
0932 X = One + Half * (One + Half);
0933 Y = (One + U2) * Half;
0934 Z = X - Y;
0935 T = Y - X;
0936 StickyBit = Z + T;
0937 if (StickyBit != Zero) {
0938 S = Zero;
0939 BadCond (Flaw, "(X - Y) + (Y - X) is non zero!\n");
0940 }
0941 StickyBit = Zero;
0942 if ((GMult == Yes) && (GDiv == Yes) && (GAddSub == Yes)
0943 && (RMult == Rounded) && (RDiv == Rounded)
0944 && (RAddSub == Rounded) && (FLOOR (RadixD2) == RadixD2)) {
0945 printf ("Checking for sticky bit.\n");
0946 X = (Half + U1) * U2;
0947 Y = Half * U2;
0948 Z = One + Y;
0949 T = One + X;
0950 if ((Z - One <= Zero) && (T - One >= U2)) {
0951 Z = T + Y;
0952 Y = Z - X;
0953 if ((Z - T >= U2) && (Y - T == Zero)) {
0954 X = (Half + U1) * U1;
0955 Y = Half * U1;
0956 Z = One - Y;
0957 T = One - X;
0958 if ((Z - One == Zero) && (T - F9 == Zero)) {
0959 Z = (Half - U1) * U1;
0960 T = F9 - Z;
0961 Q = F9 - Y;
0962 if ((T - F9 == Zero) && (F9 - U1 - Q == Zero)) {
0963 Z = (One + U2) * OneAndHalf;
0964 T = (OneAndHalf + U2) - Z + U2;
0965 X = One + Half / Radix;
0966 Y = One + Radix * U2;
0967 Z = X * Y;
0968 if (T == Zero && X + Radix * U2 - Z == Zero) {
0969 if (Radix != Two) {
0970 X = Two + U2;
0971 Y = X / Two;
0972 if ((Y - One == Zero))
0973 StickyBit = S;
0974 } else
0975 StickyBit = S;
0976 }
0977 }
0978 }
0979 }
0980 }
0981 }
0982 if (StickyBit == One)
0983 printf ("Sticky bit apparently used correctly.\n");
0984 else
0985 printf ("Sticky bit used incorrectly or not at all.\n");
0986 TstCond (Flaw, !(GMult == No || GDiv == No || GAddSub == No ||
0987 RMult == Other || RDiv == Other || RAddSub == Other),
0988 "lack(s) of guard digits or failure(s) to correctly round or chop\n\
0989 (noted above) count as one flaw in the final tally below");
0990
0991 Milestone = 60;
0992
0993 printf ("\n");
0994 printf ("Does Multiplication commute? ");
0995 printf ("Testing on %d random pairs.\n", NoTrials);
0996 Random9 = SQRT (3.0);
0997 Random1 = Third;
0998 I = 1;
0999 do {
1000 X = Random ();
1001 Y = Random ();
1002 Z9 = Y * X;
1003 Z = X * Y;
1004 Z9 = Z - Z9;
1005 I = I + 1;
1006 }
1007 while (!((I > NoTrials) || (Z9 != Zero)));
1008 if (I == NoTrials) {
1009 Random1 = One + Half / Three;
1010 Random2 = (U2 + U1) + One;
1011 Z = Random1 * Random2;
1012 Y = Random2 * Random1;
1013 Z9 = (One + Half / Three) * ((U2 + U1) + One) - (One + Half /
1014 Three) * ((U2 + U1) + One);
1015 }
1016 if (!((I == NoTrials) || (Z9 == Zero)))
1017 BadCond (Defect, "X * Y == Y * X trial fails.\n");
1018 else
1019 printf (" No failures found in %d integer pairs.\n", NoTrials);
1020
1021 Milestone = 70;
1022
1023 printf ("\nRunning test of square root(x).\n");
1024 TstCond (Failure, (Zero == SQRT (Zero))
1025 && (-Zero == SQRT (-Zero))
1026 && (One == SQRT (One)), "Square root of 0.0, -0.0 or 1.0 wrong");
1027 MinSqEr = Zero;
1028 MaxSqEr = Zero;
1029 J = Zero;
1030 X = Radix;
1031 OneUlp = U2;
1032 SqXMinX (Serious);
1033 X = BInvrse;
1034 OneUlp = BInvrse * U1;
1035 SqXMinX (Serious);
1036 X = U1;
1037 OneUlp = U1 * U1;
1038 SqXMinX (Serious);
1039 if (J != Zero)
1040 Pause ();
1041 printf ("Testing if sqrt(X * X) == X for %d Integers X.\n", NoTrials);
1042 J = Zero;
1043 X = Two;
1044 Y = Radix;
1045 if ((Radix != One))
1046 do {
1047 X = Y;
1048 Y = Radix * Y;
1049 }
1050 while (!((Y - X >= NoTrials)));
1051 OneUlp = X * U2;
1052 I = 1;
1053 while (I <= NoTrials) {
1054 X = X + One;
1055 SqXMinX (Defect);
1056 if (J > Zero)
1057 break;
1058 I = I + 1;
1059 }
1060 printf ("Test for sqrt monotonicity.\n");
1061 I = -1;
1062 X = BMinusU2;
1063 Y = Radix;
1064 Z = Radix + Radix * U2;
1065 NotMonot = False;
1066 Monot = False;
1067 while (!(NotMonot || Monot)) {
1068 I = I + 1;
1069 X = SQRT (X);
1070 Q = SQRT (Y);
1071 Z = SQRT (Z);
1072 if ((X > Q) || (Q > Z))
1073 NotMonot = True;
1074 else {
1075 Q = FLOOR (Q + Half);
1076 if ((I > 0) || (Radix == Q * Q))
1077 Monot = True;
1078 else if (I > 0) {
1079 if (I > 1)
1080 Monot = True;
1081 else {
1082 Y = Y * BInvrse;
1083 X = Y - U1;
1084 Z = Y + U1;
1085 }
1086 } else {
1087 Y = Q;
1088 X = Y - U2;
1089 Z = Y + U2;
1090 }
1091 }
1092 }
1093 if (Monot)
1094 printf ("sqrt has passed a test for Monotonicity.\n");
1095 else {
1096 BadCond (Defect, "");
1097 printf ("sqrt(X) is non-monotonic for X near %.7e .\n", Y);
1098 }
1099
1100 Milestone = 80;
1101
1102 MinSqEr = MinSqEr + Half;
1103 MaxSqEr = MaxSqEr - Half;
1104 Y = (SQRT (One + U2) - One) / U2;
1105 SqEr = (Y - One) + U2 / Eight;
1106 if (SqEr > MaxSqEr)
1107 MaxSqEr = SqEr;
1108 SqEr = Y + U2 / Eight;
1109 if (SqEr < MinSqEr)
1110 MinSqEr = SqEr;
1111 Y = ((SQRT (F9) - U2) - (One - U2)) / U1;
1112 SqEr = Y + U1 / Eight;
1113 if (SqEr > MaxSqEr)
1114 MaxSqEr = SqEr;
1115 SqEr = (Y + One) + U1 / Eight;
1116 if (SqEr < MinSqEr)
1117 MinSqEr = SqEr;
1118 OneUlp = U2;
1119 X = OneUlp;
1120 for (Indx = 1; Indx <= 3; ++Indx) {
1121 Y = SQRT ((X + U1 + X) + F9);
1122 Y = ((Y - U2) - ((One - U2) + X)) / OneUlp;
1123 Z = ((U1 - X) + F9) * Half * X * X / OneUlp;
1124 SqEr = (Y + Half) + Z;
1125 if (SqEr < MinSqEr)
1126 MinSqEr = SqEr;
1127 SqEr = (Y - Half) + Z;
1128 if (SqEr > MaxSqEr)
1129 MaxSqEr = SqEr;
1130 if (((Indx == 1) || (Indx == 3)))
1131 X = OneUlp * Sign (X) * FLOOR (Eight / (Nine * SQRT (OneUlp)));
1132 else {
1133 OneUlp = U1;
1134 X = -OneUlp;
1135 }
1136 }
1137
1138 Milestone = 85;
1139
1140 SqRWrng = False;
1141 Anomaly = False;
1142 RSqrt = Other;
1143 if (Radix != One) {
1144 printf ("Testing whether sqrt is rounded or chopped.\n");
1145 D = FLOOR (Half + POW (Radix, One + Precision - FLOOR (Precision)));
1146
1147 X = D / Radix;
1148 Y = D / A1;
1149 if ((X != FLOOR (X)) || (Y != FLOOR (Y))) {
1150 Anomaly = True;
1151 } else {
1152 X = Zero;
1153 Z2 = X;
1154 Y = One;
1155 Y2 = Y;
1156 Z1 = Radix - One;
1157 FourD = Four * D;
1158 do {
1159 if (Y2 > Z2) {
1160 Q = Radix;
1161 Y1 = Y;
1162 do {
1163 X1 = FABS (Q + FLOOR (Half - Q / Y1) * Y1);
1164 Q = Y1;
1165 Y1 = X1;
1166 }
1167 while (!(X1 <= Zero));
1168 if (Q <= One) {
1169 Z2 = Y2;
1170 Z = Y;
1171 }
1172 }
1173 Y = Y + Two;
1174 X = X + Eight;
1175 Y2 = Y2 + X;
1176 if (Y2 >= FourD)
1177 Y2 = Y2 - FourD;
1178 }
1179 while (!(Y >= D));
1180 X8 = FourD - Z2;
1181 Q = (X8 + Z * Z) / FourD;
1182 X8 = X8 / Eight;
1183 if (Q != FLOOR (Q))
1184 Anomaly = True;
1185 else {
1186 Break = False;
1187 do {
1188 X = Z1 * Z;
1189 X = X - FLOOR (X / Radix) * Radix;
1190 if (X == One)
1191 Break = True;
1192 else
1193 Z1 = Z1 - One;
1194 }
1195 while (!(Break || (Z1 <= Zero)));
1196 if ((Z1 <= Zero) && (!Break))
1197 Anomaly = True;
1198 else {
1199 if (Z1 > RadixD2)
1200 Z1 = Z1 - Radix;
1201 do {
1202 NewD ();
1203 }
1204 while (!(U2 * D >= F9));
1205 if (D * Radix - D != WVar - D)
1206 Anomaly = True;
1207 else {
1208 Z2 = D;
1209 I = 0;
1210 Y = D + (One + Z) * Half;
1211 X = D + Z + Q;
1212 SR3750 ();
1213 Y = D + (One - Z) * Half + D;
1214 X = D - Z + D;
1215 X = X + Q + X;
1216 SR3750 ();
1217 NewD ();
1218 if (D - Z2 != WVar - Z2)
1219 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)
1228 Anomaly = True;
1229 }
1230 }
1231 }
1232 }
1233 }
1234 if ((I == 0) || Anomaly) {
1235 BadCond (Failure, "Anomalous arithmetic with Integer < ");
1236 printf ("Radix^Precision = %.7e\n", WVar);
1237 printf (" fails test whether sqrt rounds or chops.\n");
1238 SqRWrng = True;
1239 }
1240 }
1241 if (!Anomaly) {
1242 if (!((MinSqEr < Zero) || (MaxSqEr > Zero))) {
1243 RSqrt = Rounded;
1244 printf ("Square root appears to be correctly rounded.\n");
1245 } else {
1246 if ((MaxSqEr + U2 > U2 - Half) || (MinSqEr > Half)
1247 || (MinSqEr + Radix < Half))
1248 SqRWrng = True;
1249 else {
1250 RSqrt = Chopped;
1251 printf ("Square root appears to be chopped.\n");
1252 }
1253 }
1254 }
1255 if (SqRWrng) {
1256 printf ("Square root is neither chopped nor correctly rounded.\n");
1257 printf ("Observed errors run from %.7e ", MinSqEr - Half);
1258 printf ("to %.7e ulps.\n", Half + MaxSqEr);
1259 TstCond (Serious, MaxSqEr - MinSqEr < Radix * Radix,
1260 "sqrt gets too many last digits wrong");
1261 }
1262
1263 Milestone = 90;
1264
1265 Pause ();
1266 printf ("Testing powers Z^i for small Integers Z and i.\n");
1267 N = 0;
1268
1269 I = 0;
1270 Z = -Zero;
1271 M = 3;
1272 Break = False;
1273 do {
1274 X = One;
1275 SR3980 ();
1276 if (I <= 10) {
1277 I = 1023;
1278 SR3980 ();
1279 }
1280 if (Z == MinusOne)
1281 Break = True;
1282 else {
1283 Z = MinusOne;
1284
1285 I = -4;
1286 }
1287 }
1288 while (!Break);
1289 PrintIfNPositive ();
1290 N1 = N;
1291 N = 0;
1292 Z = A1;
1293 M = (int) FLOOR (Two * LOG (WVar) / LOG (A1));
1294 Break = False;
1295 do {
1296 X = Z;
1297 I = 1;
1298 SR3980 ();
1299 if (Z == AInvrse)
1300 Break = True;
1301 else
1302 Z = AInvrse;
1303 }
1304 while (!(Break));
1305
1306 Milestone = 100;
1307
1308
1309
1310 M = NoTrials;
1311 Z = Three;
1312 do {
1313 X = Z;
1314 I = 1;
1315 SR3980 ();
1316 do {
1317 Z = Z + Two;
1318 }
1319 while (Three * FLOOR (Z / Three) == Z);
1320 }
1321 while (Z < Eight * Three);
1322 if (N > 0) {
1323 printf ("Errors like this may invalidate financial calculations\n");
1324 printf ("\tinvolving interest rates.\n");
1325 }
1326 PrintIfNPositive ();
1327 N += N1;
1328 if (N == 0)
1329 printf ("... no discrepancies found.\n");
1330 if (N > 0)
1331 Pause ();
1332 else
1333 printf ("\n");
1334
1335 Milestone = 110;
1336
1337 printf ("Seeking Underflow thresholds UfThold and E0.\n");
1338 D = U1;
1339 if (Precision != FLOOR (Precision)) {
1340 D = BInvrse;
1341 X = Precision;
1342 do {
1343 D = D * BInvrse;
1344 X = X - One;
1345 }
1346 while (X > Zero);
1347 }
1348 Y = One;
1349 Z = D;
1350
1351 do {
1352 C = Y;
1353 Y = Z;
1354 Z = Y * Y;
1355 }
1356 while ((Y > Z) && (Z + Z > Z));
1357 Y = C;
1358 Z = Y * D;
1359 do {
1360 C = Y;
1361 Y = Z;
1362 Z = Y * D;
1363 }
1364 while ((Y > Z) && (Z + Z > Z));
1365 if (Radix < Two)
1366 HInvrse = Two;
1367 else
1368 HInvrse = Radix;
1369 HVar = One / HInvrse;
1370
1371 CInvrse = One / C;
1372 E0 = C;
1373 Z = E0 * HVar;
1374
1375 do {
1376 Y = E0;
1377 E0 = Z;
1378 Z = E0 * HVar;
1379 }
1380 while ((E0 > Z) && (Z + Z > Z));
1381 UfThold = E0;
1382 E1 = Zero;
1383 Q = Zero;
1384 E9 = U2;
1385 S = One + E9;
1386 D = C * S;
1387 if (D <= C) {
1388 E9 = Radix * U2;
1389 S = One + E9;
1390 D = C * S;
1391 if (D <= C) {
1392 BadCond (Failure, "multiplication gets too many last digits wrong.\n");
1393 Underflow = E0;
1394 Y1 = Zero;
1395 PseudoZero = Z;
1396 Pause ();
1397 }
1398 } else {
1399 Underflow = D;
1400 PseudoZero = Underflow * HVar;
1401 UfThold = Zero;
1402 do {
1403 Y1 = Underflow;
1404 Underflow = PseudoZero;
1405 if (E1 + E1 <= E1) {
1406 Y2 = Underflow * HInvrse;
1407 E1 = FABS (Y1 - Y2);
1408 Q = Y1;
1409 if ((UfThold == Zero) && (Y1 != Y2))
1410 UfThold = Y1;
1411 }
1412 PseudoZero = PseudoZero * HVar;
1413 }
1414 while ((Underflow > PseudoZero)
1415 && (PseudoZero + PseudoZero > PseudoZero));
1416 }
1417
1418 if (PseudoZero != Zero) {
1419 printf ("\n");
1420 Z = PseudoZero;
1421
1422
1423
1424 if (PseudoZero <= Zero) {
1425 BadCond (Failure, "Positive expressions can underflow to an\n");
1426 printf ("allegedly negative value\n");
1427 printf ("PseudoZero that prints out as: %g .\n", PseudoZero);
1428 X = -PseudoZero;
1429 if (X <= Zero) {
1430 printf ("But -PseudoZero, which should be\n");
1431 printf ("positive, isn't; it prints out as %g .\n", X);
1432 }
1433 } else {
1434 BadCond (Flaw, "Underflow can stick at an allegedly positive\n");
1435 printf ("value PseudoZero that prints out as %g .\n", PseudoZero);
1436 }
1437 TstPtUf ();
1438 }
1439
1440 Milestone = 120;
1441
1442 if (CInvrse * Y > CInvrse * Y1) {
1443 S = HVar * S;
1444 E0 = Underflow;
1445 }
1446 if (!((E1 == Zero) || (E1 == E0))) {
1447 BadCond (Defect, "");
1448 if (E1 < E0) {
1449 printf ("Products underflow at a higher");
1450 printf (" threshold than differences.\n");
1451 if (PseudoZero == Zero)
1452 E0 = E1;
1453 } else {
1454 printf ("Difference underflows at a higher");
1455 printf (" threshold than products.\n");
1456 }
1457 }
1458 printf ("Smallest strictly positive number found is E0 = %g .\n", E0);
1459 Z = E0;
1460 TstPtUf ();
1461 Underflow = E0;
1462 if (N == 1)
1463 Underflow = Y;
1464 I = 4;
1465 if (E1 == Zero)
1466 I = 3;
1467 if (UfThold == Zero)
1468 I = I - 2;
1469 UfNGrad = True;
1470 switch (I) {
1471 case 1:
1472 UfThold = Underflow;
1473 if ((CInvrse * Q) != ((CInvrse * Y) * S)) {
1474 UfThold = Y;
1475 BadCond (Failure, "Either accuracy deteriorates as numbers\n");
1476 printf ("approach a threshold = %.17e\n", UfThold);
1477 printf (" coming down from %.17e\n", C);
1478 printf (" or else multiplication gets too many last digits wrong.\n");
1479 }
1480 Pause ();
1481 break;
1482
1483 case 2:
1484 BadCond (Failure, "Underflow confuses Comparison, which alleges that\n");
1485 printf ("Q == Y while denying that |Q - Y| == 0; these values\n");
1486 printf ("print out as Q = %.17e, Y = %.17e .\n", Q, Y2);
1487 printf ("|Q - Y| = %.17e .\n", FABS (Q - Y2));
1488 UfThold = Q;
1489 break;
1490
1491 case 3:
1492 X = X;
1493 break;
1494
1495 case 4:
1496 if ((Q == UfThold) && (E1 == E0)
1497 && (FABS (UfThold - E1 / E9) <= E1)) {
1498 UfNGrad = False;
1499 printf ("Underflow is gradual; it incurs Absolute Error =\n");
1500 printf ("(roundoff in UfThold) < E0.\n");
1501 Y = E0 * CInvrse;
1502 Y = Y * (OneAndHalf + U2);
1503 X = CInvrse * (One + U2);
1504 Y = Y / X;
1505 IEEE = (Y == E0);
1506 }
1507 }
1508 if (UfNGrad) {
1509 printf ("\n");
1510 sigsave = _sigfpe;
1511 if (setjmp (ovfl_buf)) {
1512 printf ("Underflow / UfThold failed!\n");
1513 R = HVar + HVar;
1514 } else
1515 R = SQRT (Underflow / UfThold);
1516 sigsave = 0;
1517 if (R <= HVar) {
1518 Z = R * UfThold;
1519 X = Z * (One + R * HVar * (One + HVar));
1520 } else {
1521 Z = UfThold;
1522 X = Z * (One + HVar * HVar * (One + HVar));
1523 }
1524 if (!((X == Z) || (X - Z != Zero))) {
1525 BadCond (Flaw, "");
1526 printf ("X = %.17e\n\tis not equal to Z = %.17e .\n", X, Z);
1527 Z9 = X - Z;
1528 printf ("yet X - Z yields %.17e .\n", Z9);
1529 printf (" Should this NOT signal Underflow, ");
1530 printf ("this is a SERIOUS DEFECT\nthat causes ");
1531 printf ("confusion when innocent statements like\n");
1532 printf (" if (X == Z) ... else");
1533 printf (" ... (f(X) - f(Z)) / (X - Z) ...\n");
1534 printf ("encounter Division by Zero although actually\n");
1535 sigsave = _sigfpe;
1536 if (setjmp (ovfl_buf))
1537 printf ("X / Z fails!\n");
1538 else
1539 printf ("X / Z = 1 + %g .\n", (X / Z - Half) - Half);
1540 sigsave = 0;
1541 }
1542 }
1543 printf ("The Underflow threshold is %.17e, %s\n", UfThold,
1544 " below which");
1545 printf ("calculation may suffer larger Relative error than ");
1546 printf ("merely roundoff.\n");
1547 Y2 = U1 * U1;
1548 Y = Y2 * Y2;
1549 Y2 = Y * U1;
1550 if (Y2 <= UfThold) {
1551 if (Y > E0) {
1552 BadCond (Defect, "");
1553 I = 5;
1554 } else {
1555 BadCond (Serious, "");
1556 I = 4;
1557 }
1558 printf ("Range is too narrow; U1^%d Underflows.\n", I);
1559 }
1560
1561 Milestone = 130;
1562
1563 Y = -FLOOR (Half - TwoForty * LOG (UfThold) / LOG (HInvrse)) / TwoForty;
1564 Y2 = Y + Y;
1565 printf ("Since underflow occurs below the threshold\n");
1566 printf ("UfThold = (%.17e) ^ (%.17e)\nonly underflow ", HInvrse, Y);
1567 printf ("should afflict the expression\n\t(%.17e) ^ (%.17e);\n",
1568 HInvrse, Y2);
1569 printf ("actually calculating yields:");
1570 if (setjmp (ovfl_buf)) {
1571 sigsave = 0;
1572 BadCond (Serious, "trap on underflow.\n");
1573 } else {
1574 sigsave = _sigfpe;
1575 V9 = POW (HInvrse, Y2);
1576 sigsave = 0;
1577 printf (" %.17e .\n", V9);
1578 if (!((V9 >= Zero) && (V9 <= (Radix + Radix + E9) * UfThold))) {
1579 BadCond (Serious, "this is not between 0 and underflow\n");
1580 printf (" threshold = %.17e .\n", UfThold);
1581 } else if (!(V9 > UfThold * (One + E9)))
1582 printf ("This computed value is O.K.\n");
1583 else {
1584 BadCond (Defect, "this is not between 0 and underflow\n");
1585 printf (" threshold = %.17e .\n", UfThold);
1586 }
1587 }
1588
1589 Milestone = 140;
1590
1591 printf ("\n");
1592
1593 X = Zero;
1594 I = 2;
1595 Y = Two * Three;
1596 Q = Zero;
1597 N = 0;
1598 do {
1599 Z = X;
1600 I = I + 1;
1601 Y = Y / (I + I);
1602 R = Y + Q;
1603 X = Z + R;
1604 Q = (Z - X) + R;
1605 }
1606 while (X > Z);
1607 Z = (OneAndHalf + One / Eight) + X / (OneAndHalf * ThirtyTwo);
1608 X = Z * Z;
1609 Exp2 = X * X;
1610 X = F9;
1611 Y = X - U1;
1612 printf ("Testing X^((X + 1) / (X - 1)) vs. exp(2) = %.17e as X -> 1.\n",
1613 Exp2);
1614 for (I = 1;;) {
1615 Z = X - BInvrse;
1616 Z = (X + One) / (Z - (One - BInvrse));
1617 Q = POW (X, Z) - Exp2;
1618 if (FABS (Q) > TwoForty * U2) {
1619 N = 1;
1620 V9 = (X - BInvrse) - (One - BInvrse);
1621 BadCond (Defect, "Calculated");
1622 printf (" %.17e for\n", POW (X, Z));
1623 printf ("\t(1 + (%.17e) ^ (%.17e);\n", V9, Z);
1624 printf ("\tdiffers from correct value by %.17e .\n", Q);
1625 printf ("\tThis much error may spoil financial\n");
1626 printf ("\tcalculations involving tiny interest rates.\n");
1627 break;
1628 } else {
1629 Z = (Y - X) * Two + Y;
1630 X = Y;
1631 Y = Z;
1632 Z = One + (X - F9) * (X - F9);
1633 if (Z > One && I < NoTrials)
1634 I++;
1635 else {
1636 if (X > One) {
1637 if (N == 0)
1638 printf ("Accuracy seems adequate.\n");
1639 break;
1640 } else {
1641 X = One + U2;
1642 Y = U2 + U2;
1643 Y += X;
1644 I = 1;
1645 }
1646 }
1647 }
1648 }
1649
1650 Milestone = 150;
1651
1652 printf ("Testing powers Z^Q at four nearly extreme values.\n");
1653 N = 0;
1654 Z = A1;
1655 Q = FLOOR (Half - LOG (C) / LOG (A1));
1656 Break = False;
1657 do {
1658 X = CInvrse;
1659 Y = POW (Z, Q);
1660 IsYeqX ();
1661 Q = -Q;
1662 X = C;
1663 Y = POW (Z, Q);
1664 IsYeqX ();
1665 if (Z < One)
1666 Break = True;
1667 else
1668 Z = AInvrse;
1669 }
1670 while (!(Break));
1671 PrintIfNPositive ();
1672 if (N == 0)
1673 printf (" ... no discrepancies found.\n");
1674 printf ("\n");
1675
1676
1677 Milestone = 160;
1678
1679 Pause ();
1680 printf ("Searching for Overflow threshold:\n");
1681 printf ("This may generate an error.\n");
1682 Y = -CInvrse;
1683 V9 = HInvrse * Y;
1684 sigsave = _sigfpe;
1685 if (setjmp (ovfl_buf)) {
1686 I = 0;
1687 V9 = Y;
1688 goto overflow;
1689 }
1690 do {
1691 V = Y;
1692 Y = V9;
1693 V9 = HInvrse * Y;
1694 }
1695 while (V9 < Y);
1696 I = 1;
1697 overflow:
1698 sigsave = 0;
1699 Z = V9;
1700 printf ("Can `Z = -Y' overflow?\n");
1701 printf ("Trying it on Y = %.17e .\n", Y);
1702 V9 = -Y;
1703 V0 = V9;
1704 if (V - Y == V + V0)
1705 printf ("Seems O.K.\n");
1706 else {
1707 printf ("finds a ");
1708 BadCond (Flaw, "-(-Y) differs from Y.\n");
1709 }
1710 if (Z != Y) {
1711 BadCond (Serious, "");
1712 printf ("overflow past %.17e\n\tshrinks to %.17e .\n", Y, Z);
1713 }
1714 if (I) {
1715 Y = V * (HInvrse * U2 - HInvrse);
1716 Z = Y + ((One - HInvrse) * U2) * V;
1717 if (Z < V0)
1718 Y = Z;
1719 if (Y < V0)
1720 V = Y;
1721 if (V0 - V < V0)
1722 V = V0;
1723 } else {
1724 V = Y * (HInvrse * U2 - HInvrse);
1725 V = V + ((One - HInvrse) * U2) * Y;
1726 }
1727 printf ("Overflow threshold is V = %.17e .\n", V);
1728 if (I)
1729 printf ("Overflow saturates at V0 = %.17e .\n", V0);
1730 else
1731 printf ("There is no saturation value because \
1732 the system traps on overflow.\n");
1733 V9 = V * One;
1734 printf ("No Overflow should be signaled for V * 1 = %.17e\n", V9);
1735 V9 = V / One;
1736 printf (" nor for V / 1 = %.17e .\n", V9);
1737 printf ("Any overflow signal separating this * from the one\n");
1738 printf ("above is a DEFECT.\n");
1739
1740 Milestone = 170;
1741
1742 if (!(-V < V && -V0 < V0 && -UfThold < V && UfThold < V)) {
1743 BadCond (Failure, "Comparisons involving ");
1744 printf ("+-%g, +-%g\nand +-%g are confused by Overflow.",
1745 V, V0, UfThold);
1746 }
1747
1748 Milestone = 175;
1749
1750 printf ("\n");
1751 for (Indx = 1; Indx <= 3; ++Indx) {
1752 switch (Indx) {
1753 case 1:
1754 Z = UfThold;
1755 break;
1756 case 2:
1757 Z = E0;
1758 break;
1759 case 3:
1760 Z = PseudoZero;
1761 break;
1762 }
1763 if (Z != Zero) {
1764 V9 = SQRT (Z);
1765 Y = V9 * V9;
1766 if (Y / (One - Radix * E9) < Z
1767 || Y > (One + Radix * E9) * Z) {
1768 if (V9 > U1)
1769 BadCond (Serious, "");
1770 else
1771 BadCond (Defect, "");
1772 printf ("Comparison alleges that what prints as Z = %.17e\n", Z);
1773 printf (" is too far from sqrt(Z) ^ 2 = %.17e .\n", Y);
1774 }
1775 }
1776 }
1777
1778 Milestone = 180;
1779
1780 for (Indx = 1; Indx <= 2; ++Indx) {
1781 if (Indx == 1)
1782 Z = V;
1783 else
1784 Z = V0;
1785 V9 = SQRT (Z);
1786 X = (One - Radix * E9) * V9;
1787 V9 = V9 * X;
1788 if (((V9 < (One - Two * Radix * E9) * Z) || (V9 > Z))) {
1789 Y = V9;
1790 if (X < WVar)
1791 BadCond (Serious, "");
1792 else
1793 BadCond (Defect, "");
1794 printf ("Comparison alleges that Z = %17e\n", Z);
1795 printf (" is too far from sqrt(Z) ^ 2 (%.17e) .\n", Y);
1796 }
1797 }
1798
1799 Milestone = 190;
1800
1801 Pause ();
1802 X = UfThold * V;
1803 Y = Radix * Radix;
1804 if (X * Y < One || X > Y) {
1805 if (X * Y < U1 || X > Y / U1)
1806 BadCond (Defect, "Badly");
1807 else
1808 BadCond (Flaw, "");
1809
1810 printf (" unbalanced range; UfThold * V = %.17e\n\t%s\n",
1811 X, "is too far from 1.\n");
1812 }
1813
1814 Milestone = 200;
1815
1816 for (Indx = 1; Indx <= 5; ++Indx) {
1817 X = F9;
1818 switch (Indx) {
1819 case 2:
1820 X = One + U2;
1821 break;
1822 case 3:
1823 X = V;
1824 break;
1825 case 4:
1826 X = UfThold;
1827 break;
1828 case 5:
1829 X = Radix;
1830 }
1831 Y = X;
1832 sigsave = _sigfpe;
1833 if (setjmp (ovfl_buf))
1834 printf (" X / X traps when X = %g\n", X);
1835 else {
1836 V9 = (Y / X - Half) - Half;
1837 if (V9 == Zero)
1838 continue;
1839 if (V9 == -U1 && Indx < 5)
1840 BadCond (Flaw, "");
1841 else
1842 BadCond (Serious, "");
1843 printf (" X / X differs from 1 when X = %.17e\n", X);
1844 printf (" instead, X / X - 1/2 - 1/2 = %.17e .\n", V9);
1845 }
1846 sigsave = 0;
1847 }
1848
1849 Milestone = 210;
1850
1851 MyZero = Zero;
1852 printf ("\n");
1853 printf ("What message and/or values does Division by Zero produce?\n");
1854 #ifndef BATCHMODE
1855 printf ("This can interupt your program. You can ");
1856 printf ("skip this part if you wish.\n");
1857 printf ("Do you wish to compute 1 / 0? ");
1858 fflush (stdout);
1859 read (KEYBOARD, ch, 8);
1860 if ((ch[0] == 'Y') || (ch[0] == 'y')) {
1861 #endif
1862 sigsave = _sigfpe;
1863 printf (" Trying to compute 1 / 0 produces ...");
1864 if (!setjmp (ovfl_buf))
1865 printf (" %.7e .\n", One / MyZero);
1866 sigsave = 0;
1867 #ifndef BATCHMODE
1868 } else
1869 printf ("O.K.\n");
1870 printf ("\nDo you wish to compute 0 / 0? ");
1871 fflush (stdout);
1872 read (KEYBOARD, ch, 80);
1873 if ((ch[0] == 'Y') || (ch[0] == 'y')) {
1874 #endif
1875 sigsave = _sigfpe;
1876 printf ("\n Trying to compute 0 / 0 produces ...");
1877 if (!setjmp (ovfl_buf))
1878 printf (" %.7e .\n", Zero / MyZero);
1879 sigsave = 0;
1880 #ifndef BATCHMODE
1881 } else
1882 printf ("O.K.\n");
1883 #endif
1884
1885 Milestone = 220;
1886
1887
1888 Pause ();
1889 printf ("\n");
1890 {
1891 static char *msg[] =
1892 {
1893 "FAILUREs encountered =",
1894 "SERIOUS DEFECTs discovered =",
1895 "DEFECTs discovered =",
1896 "FLAWs discovered ="};
1897 int i;
1898 for (i = 0; i < 4; i++)
1899 if (ErrCnt[i])
1900 printf ("The number of %-29s %d.\n",
1901 msg[i], ErrCnt[i]);
1902 }
1903
1904 printf ("\n");
1905 if ((ErrCnt[Failure] + ErrCnt[Serious] + ErrCnt[Defect]
1906 + ErrCnt[Flaw]) > 0) {
1907 if ((ErrCnt[Failure] + ErrCnt[Serious] + ErrCnt[
1908 Defect] == 0) && (ErrCnt[Flaw] > 0)) {
1909 printf ("The arithmetic diagnosed seems ");
1910 printf ("Satisfactory though flawed.\n");
1911 }
1912 if ((ErrCnt[Failure] + ErrCnt[Serious] == 0)
1913 && (ErrCnt[Defect] > 0)) {
1914 printf ("The arithmetic diagnosed may be Acceptable\n");
1915 printf ("despite inconvenient Defects.\n");
1916 }
1917 if ((ErrCnt[Failure] + ErrCnt[Serious]) > 0) {
1918 printf ("The arithmetic diagnosed has ");
1919 printf ("unacceptable Serious Defects.\n");
1920 }
1921 if (ErrCnt[Failure] > 0) {
1922 printf ("Potentially fatal FAILURE may have spoiled this");
1923 printf (" program's subsequent diagnoses.\n");
1924 }
1925 } else {
1926
1927 printf ("No failures, defects nor flaws have been discovered.\n");
1928 if (!((RMult == Rounded) && (RDiv == Rounded)
1929 && (RAddSub == Rounded) && (RSqrt == Rounded)))
1930 printf ("The arithmetic diagnosed seems Satisfactory.\n");
1931 else {
1932 if (StickyBit >= One &&
1933 (Radix - Two) * (Radix - Nine - One) == Zero) {
1934 printf ("Rounding appears to conform to ");
1935 printf ("the proposed IEEE standard P");
1936 if ((Radix == Two) &&
1937 ((Precision - Four * Three * Two) *
1938 (Precision - TwentySeven -
1939 TwentySeven + One) == Zero))
1940 printf ("754");
1941 else
1942 printf ("854");
1943 if (IEEE)
1944 printf (".\n");
1945 else {
1946 printf (",\nexcept for possibly Double Rounding");
1947 printf (" during Gradual Underflow.\n");
1948 }
1949 }
1950 printf ("The arithmetic diagnosed appears to be Excellent!\n");
1951 }
1952 }
1953
1954 if (fpecount)
1955 printf ("\nA total of %d floating point exceptions were registered.\n",
1956 fpecount);
1957 printf ("END OF TEST.\n");
1958 return 0;
1959 }
1960
1961 FLOAT
1962 Sign (X)
1963 FLOAT X;
1964 {
1965 return X >= 0. ? 1.0 : -1.0;
1966 }
1967
1968 void
1969 Pause ()
1970 {
1971 #ifndef BATCHMODE
1972 char ch[8];
1973
1974 printf ("\nTo continue, press RETURN");
1975 fflush (stdout);
1976 read (KEYBOARD, ch, 8);
1977 #endif
1978 #ifndef CYGNUS
1979 printf ("\nDiagnosis resumes after milestone Number %d", Milestone);
1980 printf (" Page: %d\n\n", PageNo);
1981 ++Milestone;
1982 ++PageNo;
1983 #endif
1984 }
1985
1986 void
1987 TstCond (K, Valid, T)
1988 int K, Valid;
1989 char *T;
1990 {
1991 #ifdef CYGNUS
1992 printf ("TEST: %s\n", T);
1993 #endif
1994 if (!Valid) {
1995 BadCond (K, T);
1996 printf (".\n");
1997 }
1998 #ifdef CYGNUS
1999 printf ("PASS: %s\n", T);
2000 #endif
2001 }
2002
2003 void
2004 BadCond (K, T)
2005 int K;
2006 char *T;
2007 {
2008 static char *msg[] =
2009 {"FAILURE", "SERIOUS DEFECT", "DEFECT", "FLAW"};
2010
2011 ErrCnt[K] = ErrCnt[K] + 1;
2012 #ifndef CYGNUS
2013 printf ("%s: %s", msg[K], T);
2014 #else
2015 printf ("ERROR: Severity: %s: %s", msg[K], T);
2016 #endif
2017 }
2018
2019
2020
2021
2022
2023
2024
2025 FLOAT
2026 Random ()
2027 {
2028 FLOAT X, Y;
2029
2030 X = Random1 + Random9;
2031 Y = X * X;
2032 Y = Y * Y;
2033 X = X * Y;
2034 Y = X - FLOOR (X);
2035 Random1 = Y + X * 0.000005;
2036 return (Random1);
2037 }
2038
2039 void
2040 SqXMinX (ErrKind)
2041 int ErrKind;
2042 {
2043 FLOAT XA, XB;
2044
2045 XB = X * BInvrse;
2046 XA = X - XB;
2047 SqEr = ((SQRT (X * X) - XB) - XA) / OneUlp;
2048 if (SqEr != Zero) {
2049 if (SqEr < MinSqEr)
2050 MinSqEr = SqEr;
2051 if (SqEr > MaxSqEr)
2052 MaxSqEr = SqEr;
2053 J = J + 1.0;
2054 BadCond (ErrKind, "\n");
2055 printf ("sqrt( %.17e) - %.17e = %.17e\n", X * X, X, OneUlp * SqEr);
2056 printf ("\tinstead of correct value 0 .\n");
2057 }
2058 }
2059
2060 void
2061 NewD ()
2062 {
2063 X = Z1 * Q;
2064 X = FLOOR (Half - X / Radix) * Radix + X;
2065 Q = (Q - X * Z) / Radix + X * X * (D / Radix);
2066 Z = Z - Two * X * D;
2067 if (Z <= Zero) {
2068 Z = -Z;
2069 Z1 = -Z1;
2070 }
2071 D = Radix * D;
2072 }
2073
2074 void
2075 SR3750 ()
2076 {
2077 if (!((X - Radix < Z2 - Radix) || (X - Z2 > WVar - Z2))) {
2078 I = I + 1;
2079 X2 = SQRT (X * D);
2080 Y2 = (X2 - Z2) - (Y - Z2);
2081 X2 = X8 / (Y - Half);
2082 X2 = X2 - Half * X2 * X2;
2083 SqEr = (Y2 + Half) + (Half - X2);
2084 if (SqEr < MinSqEr)
2085 MinSqEr = SqEr;
2086 SqEr = Y2 - X2;
2087 if (SqEr > MaxSqEr)
2088 MaxSqEr = SqEr;
2089 }
2090 }
2091
2092 void
2093 IsYeqX ()
2094 {
2095 if (Y != X) {
2096 if (N <= 0) {
2097 if (Z == Zero && Q <= Zero)
2098 printf ("WARNING: computing\n");
2099 else
2100 BadCond (Defect, "computing\n");
2101 printf ("\t(%.17e) ^ (%.17e)\n", Z, Q);
2102 printf ("\tyielded %.17e;\n", Y);
2103 printf ("\twhich compared unequal to correct %.17e ;\n",
2104 X);
2105 printf ("\t\tthey differ by %.17e .\n", Y - X);
2106 }
2107 N = N + 1;
2108 }
2109 }
2110
2111 void
2112 SR3980 ()
2113 {
2114 do {
2115 Q = (FLOAT) I;
2116 Y = POW (Z, Q);
2117 IsYeqX ();
2118 if (++I > M)
2119 break;
2120 X = Z * X;
2121 }
2122 while (X < WVar);
2123 }
2124
2125 void
2126 PrintIfNPositive ()
2127 {
2128 if (N > 0)
2129 printf ("Similar discrepancies have occurred %d times.\n", N);
2130 }
2131
2132 void
2133 TstPtUf ()
2134 {
2135 N = 0;
2136 if (Z != Zero) {
2137 printf ("Since comparison denies Z = 0, evaluating ");
2138 printf ("(Z + Z) / Z should be safe.\n");
2139 sigsave = _sigfpe;
2140 if (setjmp (ovfl_buf))
2141 goto very_serious;
2142 Q9 = (Z + Z) / Z;
2143 printf ("What the machine gets for (Z + Z) / Z is %.17e .\n",
2144 Q9);
2145 if (FABS (Q9 - Two) < Radix * U2) {
2146 printf ("This is O.K., provided Over/Underflow");
2147 printf (" has NOT just been signaled.\n");
2148 } else {
2149 if ((Q9 < One) || (Q9 > Two)) {
2150 very_serious:
2151 N = 1;
2152 ErrCnt[Serious] = ErrCnt[Serious] + 1;
2153 printf ("This is a VERY SERIOUS DEFECT!\n");
2154 } else {
2155 N = 1;
2156 ErrCnt[Defect] = ErrCnt[Defect] + 1;
2157 printf ("This is a DEFECT!\n");
2158 }
2159 }
2160 sigsave = 0;
2161 V9 = Z * One;
2162 Random1 = V9;
2163 V9 = One * Z;
2164 Random2 = V9;
2165 V9 = Z / One;
2166 if ((Z == Random1) && (Z == Random2) && (Z == V9)) {
2167 if (N > 0)
2168 Pause ();
2169 } else {
2170 N = 1;
2171 BadCond (Defect, "What prints as Z = ");
2172 printf ("%.17e\n\tcompares different from ", Z);
2173 if (Z != Random1)
2174 printf ("Z * 1 = %.17e ", Random1);
2175 if (!((Z == Random2)
2176 || (Random2 == Random1)))
2177 printf ("1 * Z == %g\n", Random2);
2178 if (!(Z == V9))
2179 printf ("Z / 1 = %.17e\n", V9);
2180 if (Random2 != Random1) {
2181 ErrCnt[Defect] = ErrCnt[Defect] + 1;
2182 BadCond (Defect, "Multiplication does not commute!\n");
2183 printf ("\tComparison alleges that 1 * Z = %.17e\n",
2184 Random2);
2185 printf ("\tdiffers from Z * 1 = %.17e\n", Random1);
2186 }
2187 Pause ();
2188 }
2189 }
2190 }
2191
2192 void
2193 notify (s)
2194 char *s;
2195 {
2196 printf ("%s test appears to be inconsistent...\n", s);
2197 printf (" PLEASE NOTIFY KARPINKSI!\n");
2198 }
2199
2200 void
2201 msglist (s)
2202 char **s;
2203 {
2204 while (*s)
2205 printf ("%s\n", *s++);
2206 }
2207
2208 void
2209 Instructions ()
2210 {
2211 static char *instr[] =
2212 {
2213 "Lest this program stop prematurely, i.e. before displaying\n",
2214 " `END OF TEST',\n",
2215 "try to persuade the computer NOT to terminate execution when an",
2216 "error like Over/Underflow or Division by Zero occurs, but rather",
2217 "to persevere with a surrogate value after, perhaps, displaying some",
2218 "warning. If persuasion avails naught, don't despair but run this",
2219 "program anyway to see how many milestones it passes, and then",
2220 "amend it to make further progress.\n",
2221 "Answer questions with Y, y, N or n (unless otherwise indicated).\n",
2222 0};
2223
2224 msglist (instr);
2225 }
2226
2227 void
2228 Heading ()
2229 {
2230 static char *head[] =
2231 {
2232 "Users are invited to help debug and augment this program so it will",
2233 "cope with unanticipated and newly uncovered arithmetic pathologies.\n",
2234 "Please send suggestions and interesting results to",
2235 "\tRichard Karpinski",
2236 "\tComputer Center U-76",
2237 "\tUniversity of California",
2238 "\tSan Francisco, CA 94143-0704, USA\n",
2239 "In doing so, please include the following information:",
2240 #ifdef SINGLE_PRECISION
2241 "\tPrecision:\tsingle;",
2242 #else
2243 "\tPrecision:\tdouble;",
2244 #endif
2245 "\tVersion:\t10 February 1989;",
2246 "\tComputer:\n",
2247 "\tCompiler:\n",
2248 "\tOptimization level:\n",
2249 "\tOther relevant compiler options:",
2250 0};
2251
2252 msglist (head);
2253 }
2254
2255 void
2256 Characteristics ()
2257 {
2258 static char *chars[] =
2259 {
2260 "Running this program should reveal these characteristics:",
2261 " Radix = 1, 2, 4, 8, 10, 16, 100, 256 ...",
2262 " Precision = number of significant digits carried.",
2263 " U2 = Radix/Radix^Precision = One Ulp",
2264 "\t(OneUlpnit in the Last Place) of 1.000xxx .",
2265 " U1 = 1/Radix^Precision = One Ulp of numbers a little less than 1.0 .",
2266 " Adequacy of guard digits for Mult., Div. and Subt.",
2267 " Whether arithmetic is chopped, correctly rounded, or something else",
2268 "\tfor Mult., Div., Add/Subt. and Sqrt.",
2269 " Whether a Sticky Bit used correctly for rounding.",
2270 " UnderflowThreshold = an underflow threshold.",
2271 " E0 and PseudoZero tell whether underflow is abrupt, gradual, or fuzzy.",
2272 " V = an overflow threshold, roughly.",
2273 " V0 tells, roughly, whether Infinity is represented.",
2274 " Comparisions are checked for consistency with subtraction",
2275 "\tand for contamination with pseudo-zeros.",
2276 " Sqrt is tested. Y^X is not tested.",
2277 " Extra-precise subexpressions are revealed but NOT YET tested.",
2278 " Decimal-Binary conversion is NOT YET tested for accuracy.",
2279 0};
2280
2281 msglist (chars);
2282 }
2283
2284 void
2285 History ()
2286 {
2287
2288
2289
2290 static char *hist[] =
2291 {
2292 "The program attempts to discriminate among",
2293 " FLAWs, like lack of a sticky bit,",
2294 " Serious DEFECTs, like lack of a guard digit, and",
2295 " FAILUREs, like 2+2 == 5 .",
2296 "Failures may confound subsequent diagnoses.\n",
2297 "The diagnostic capabilities of this program go beyond an earlier",
2298 "program called `MACHAR', which can be found at the end of the",
2299 "book `Software Manual for the Elementary Functions' (1980) by",
2300 "W. J. Cody and W. Waite. Although both programs try to discover",
2301 "the Radix, Precision and range (over/underflow thresholds)",
2302 "of the arithmetic, this program tries to cope with a wider variety",
2303 "of pathologies, and to say how well the arithmetic is implemented.",
2304 "\nThe program is based upon a conventional radix representation for",
2305 "floating-point numbers, but also allows logarithmic encoding",
2306 "as used by certain early WANG machines.\n",
2307 "BASIC version of this program (C) 1983 by Prof. W. M. Kahan;",
2308 "see source comments for more history.",
2309 0};
2310
2311 msglist (hist);
2312 }