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