OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gcc-4.2.2/] [contrib/] [paranoia.cc] - Diff between revs 154 and 816

Go to most recent revision | Only display areas with differences | Details | Blame | View Log

Rev 154 Rev 816
/*      A C version of Kahan's Floating Point Test "Paranoia"
/*      A C version of Kahan's Floating Point Test "Paranoia"
 
 
Thos Sumner, UCSF, Feb. 1985
Thos Sumner, UCSF, Feb. 1985
David Gay, BTL, Jan. 1986
David Gay, BTL, Jan. 1986
 
 
This is a rewrite from the Pascal version by
This is a rewrite from the Pascal version by
 
 
B. A. Wichmann, 18 Jan. 1985
B. A. Wichmann, 18 Jan. 1985
 
 
(and does NOT exhibit good C programming style).
(and does NOT exhibit good C programming style).
 
 
Adjusted to use Standard C headers 19 Jan. 1992 (dmg);
Adjusted to use Standard C headers 19 Jan. 1992 (dmg);
 
 
(C) Apr 19 1983 in BASIC version by:
(C) Apr 19 1983 in BASIC version by:
Professor W. M. Kahan,
Professor W. M. Kahan,
567 Evans Hall
567 Evans Hall
Electrical Engineering & Computer Science Dept.
Electrical Engineering & Computer Science Dept.
University of California
University of California
Berkeley, California 94720
Berkeley, California 94720
USA
USA
 
 
converted to Pascal by:
converted to Pascal by:
B. A. Wichmann
B. A. Wichmann
National Physical Laboratory
National Physical Laboratory
Teddington Middx
Teddington Middx
TW11 OLW
TW11 OLW
UK
UK
 
 
converted to C by:
converted to C by:
 
 
David M. Gay            and     Thos Sumner
David M. Gay            and     Thos Sumner
AT&T Bell Labs                  Computer Center, Rm. U-76
AT&T Bell Labs                  Computer Center, Rm. U-76
600 Mountain Avenue             University of California
600 Mountain Avenue             University of California
Murray Hill, NJ 07974           San Francisco, CA 94143
Murray Hill, NJ 07974           San Francisco, CA 94143
USA                             USA
USA                             USA
 
 
with simultaneous corrections to the Pascal source (reflected
with simultaneous corrections to the Pascal source (reflected
in the Pascal source available over netlib).
in the Pascal source available over netlib).
[A couple of bug fixes from dgh = sun!dhough incorporated 31 July 1986.]
[A couple of bug fixes from dgh = sun!dhough incorporated 31 July 1986.]
 
 
Reports of results on various systems from all the versions
Reports of results on various systems from all the versions
of Paranoia are being collected by Richard Karpinski at the
of Paranoia are being collected by Richard Karpinski at the
same address as Thos Sumner.  This includes sample outputs,
same address as Thos Sumner.  This includes sample outputs,
bug reports, and criticisms.
bug reports, and criticisms.
 
 
You may copy this program freely if you acknowledge its source.
You may copy this program freely if you acknowledge its source.
Comments on the Pascal version to NPL, please.
Comments on the Pascal version to NPL, please.
 
 
The following is from the introductory commentary from Wichmann's work:
The following is from the introductory commentary from Wichmann's work:
 
 
The BASIC program of Kahan is written in Microsoft BASIC using many
The BASIC program of Kahan is written in Microsoft BASIC using many
facilities which have no exact analogy in Pascal.  The Pascal
facilities which have no exact analogy in Pascal.  The Pascal
version below cannot therefore be exactly the same.  Rather than be
version below cannot therefore be exactly the same.  Rather than be
a minimal transcription of the BASIC program, the Pascal coding
a minimal transcription of the BASIC program, the Pascal coding
follows the conventional style of block-structured languages.  Hence
follows the conventional style of block-structured languages.  Hence
the Pascal version could be useful in producing versions in other
the Pascal version could be useful in producing versions in other
structured languages.
structured languages.
 
 
Rather than use identifiers of minimal length (which therefore have
Rather than use identifiers of minimal length (which therefore have
little mnemonic significance), the Pascal version uses meaningful
little mnemonic significance), the Pascal version uses meaningful
identifiers as follows [Note: A few changes have been made for C]:
identifiers as follows [Note: A few changes have been made for C]:
 
 
 
 
BASIC   C               BASIC   C               BASIC   C
BASIC   C               BASIC   C               BASIC   C
 
 
A                       J                       S    StickyBit
A                       J                       S    StickyBit
A1   AInverse           J0   NoErrors           T
A1   AInverse           J0   NoErrors           T
B    Radix                    [Failure]         T0   Underflow
B    Radix                    [Failure]         T0   Underflow
B1   BInverse           J1   NoErrors           T2   ThirtyTwo
B1   BInverse           J1   NoErrors           T2   ThirtyTwo
B2   RadixD2                  [SeriousDefect]   T5   OneAndHalf
B2   RadixD2                  [SeriousDefect]   T5   OneAndHalf
B9   BMinusU2           J2   NoErrors           T7   TwentySeven
B9   BMinusU2           J2   NoErrors           T7   TwentySeven
C                             [Defect]          T8   TwoForty
C                             [Defect]          T8   TwoForty
C1   CInverse           J3   NoErrors           U    OneUlp
C1   CInverse           J3   NoErrors           U    OneUlp
D                             [Flaw]            U0   UnderflowThreshold
D                             [Flaw]            U0   UnderflowThreshold
D4   FourD              K    PageNo             U1
D4   FourD              K    PageNo             U1
E0                      L    Milestone          U2
E0                      L    Milestone          U2
E1                      M                       V
E1                      M                       V
E2   Exp2               N                       V0
E2   Exp2               N                       V0
E3                      N1                      V8
E3                      N1                      V8
E5   MinSqEr            O    Zero               V9
E5   MinSqEr            O    Zero               V9
E6   SqEr               O1   One                W
E6   SqEr               O1   One                W
E7   MaxSqEr            O2   Two                X
E7   MaxSqEr            O2   Two                X
E8                      O3   Three              X1
E8                      O3   Three              X1
E9                      O4   Four               X8
E9                      O4   Four               X8
F1   MinusOne           O5   Five               X9   Random1
F1   MinusOne           O5   Five               X9   Random1
F2   Half               O8   Eight              Y
F2   Half               O8   Eight              Y
F3   Third              O9   Nine               Y1
F3   Third              O9   Nine               Y1
F6                      P    Precision          Y2
F6                      P    Precision          Y2
F9                      Q                       Y9   Random2
F9                      Q                       Y9   Random2
G1   GMult              Q8                      Z
G1   GMult              Q8                      Z
G2   GDiv               Q9                      Z0   PseudoZero
G2   GDiv               Q9                      Z0   PseudoZero
G3   GAddSub            R                       Z1
G3   GAddSub            R                       Z1
H                       R1   RMult              Z2
H                       R1   RMult              Z2
H1   HInverse           R2   RDiv               Z9
H1   HInverse           R2   RDiv               Z9
I                       R3   RAddSub
I                       R3   RAddSub
IO   NoTrials           R4   RSqrt
IO   NoTrials           R4   RSqrt
I3   IEEE               R9   Random9
I3   IEEE               R9   Random9
 
 
SqRWrng
SqRWrng
 
 
All the variables in BASIC are true variables and in consequence,
All the variables in BASIC are true variables and in consequence,
the program is more difficult to follow since the "constants" must
the program is more difficult to follow since the "constants" must
be determined (the glossary is very helpful).  The Pascal version
be determined (the glossary is very helpful).  The Pascal version
uses Real constants, but checks are added to ensure that the values
uses Real constants, but checks are added to ensure that the values
are correctly converted by the compiler.
are correctly converted by the compiler.
 
 
The major textual change to the Pascal version apart from the
The major textual change to the Pascal version apart from the
identifiersis that named procedures are used, inserting parameters
identifiersis that named procedures are used, inserting parameters
wherehelpful.  New procedures are also introduced.  The
wherehelpful.  New procedures are also introduced.  The
correspondence is as follows:
correspondence is as follows:
 
 
 
 
BASIC       Pascal
BASIC       Pascal
lines
lines
 
 
90- 140   Pause
90- 140   Pause
170- 250   Instructions
170- 250   Instructions
380- 460   Heading
380- 460   Heading
480- 670   Characteristics
480- 670   Characteristics
690- 870   History
690- 870   History
2940-2950   Random
2940-2950   Random
3710-3740   NewD
3710-3740   NewD
4040-4080   DoesYequalX
4040-4080   DoesYequalX
4090-4110   PrintIfNPositive
4090-4110   PrintIfNPositive
4640-4850   TestPartialUnderflow
4640-4850   TestPartialUnderflow
 
 
*/
*/
 
 
  /* This version of paranoia has been modified to work with GCC's internal
  /* This version of paranoia has been modified to work with GCC's internal
     software floating point emulation library, as a sanity check of same.
     software floating point emulation library, as a sanity check of same.
 
 
     I'm doing this in C++ so that I can do operator overloading and not
     I'm doing this in C++ so that I can do operator overloading and not
     have to modify so damned much of the existing code.  */
     have to modify so damned much of the existing code.  */
 
 
  extern "C" {
  extern "C" {
#include <stdio.h>
#include <stdio.h>
#include <stddef.h>
#include <stddef.h>
#include <limits.h>
#include <limits.h>
#include <string.h>
#include <string.h>
#include <stdlib.h>
#include <stdlib.h>
#include <math.h>
#include <math.h>
#include <unistd.h>
#include <unistd.h>
#include <float.h>
#include <float.h>
 
 
    /* This part is made all the more awful because many gcc headers are
    /* This part is made all the more awful because many gcc headers are
       not prepared at all to be parsed as C++.  The biggest stickler
       not prepared at all to be parsed as C++.  The biggest stickler
       here is const structure members.  So we include exactly the pieces
       here is const structure members.  So we include exactly the pieces
       that we need.  */
       that we need.  */
 
 
#define GTY(x)
#define GTY(x)
 
 
#include "ansidecl.h"
#include "ansidecl.h"
#include "auto-host.h"
#include "auto-host.h"
#include "hwint.h"
#include "hwint.h"
 
 
#undef EXTRA_MODES_FILE
#undef EXTRA_MODES_FILE
 
 
    struct rtx_def;
    struct rtx_def;
    typedef struct rtx_def *rtx;
    typedef struct rtx_def *rtx;
    struct rtvec_def;
    struct rtvec_def;
    typedef struct rtvec_def *rtvec;
    typedef struct rtvec_def *rtvec;
    union tree_node;
    union tree_node;
    typedef union tree_node *tree;
    typedef union tree_node *tree;
 
 
#define DEFTREECODE(SYM, STRING, TYPE, NARGS)   SYM,
#define DEFTREECODE(SYM, STRING, TYPE, NARGS)   SYM,
    enum tree_code {
    enum tree_code {
#include "tree.def"
#include "tree.def"
      LAST_AND_UNUSED_TREE_CODE
      LAST_AND_UNUSED_TREE_CODE
    };
    };
#undef DEFTREECODE
#undef DEFTREECODE
 
 
#define ENUM_BITFIELD(X) enum X
#define ENUM_BITFIELD(X) enum X
#define class klass
#define class klass
 
 
#include "real.h"
#include "real.h"
 
 
#undef class
#undef class
  }
  }
 
 
/* We never produce signals from the library.  Thus setjmp need do nothing.  */
/* We never produce signals from the library.  Thus setjmp need do nothing.  */
#undef setjmp
#undef setjmp
#define setjmp(x)  (0)
#define setjmp(x)  (0)
 
 
static bool verbose = false;
static bool verbose = false;
static int verbose_index = 0;
static int verbose_index = 0;
 
 
/* ====================================================================== */
/* ====================================================================== */
/* The implementation of the abstract floating point class based on gcc's
/* The implementation of the abstract floating point class based on gcc's
   real.c.  I.e. the object of this exercise.  Templated so that we can
   real.c.  I.e. the object of this exercise.  Templated so that we can
   all fp sizes.  */
   all fp sizes.  */
 
 
class real_c_float
class real_c_float
{
{
 public:
 public:
  static const enum machine_mode MODE = SFmode;
  static const enum machine_mode MODE = SFmode;
 
 
 private:
 private:
  static const int external_max = 128 / 32;
  static const int external_max = 128 / 32;
  static const int internal_max
  static const int internal_max
    = (sizeof (REAL_VALUE_TYPE) + sizeof (long) + 1) / sizeof (long);
    = (sizeof (REAL_VALUE_TYPE) + sizeof (long) + 1) / sizeof (long);
  long image[external_max < internal_max ? internal_max : external_max];
  long image[external_max < internal_max ? internal_max : external_max];
 
 
  void from_long(long);
  void from_long(long);
  void from_str(const char *);
  void from_str(const char *);
  void binop(int code, const real_c_float&);
  void binop(int code, const real_c_float&);
  void unop(int code);
  void unop(int code);
  bool cmp(int code, const real_c_float&) const;
  bool cmp(int code, const real_c_float&) const;
 
 
 public:
 public:
  real_c_float()
  real_c_float()
    { }
    { }
  real_c_float(long l)
  real_c_float(long l)
    { from_long(l); }
    { from_long(l); }
  real_c_float(const char *s)
  real_c_float(const char *s)
    { from_str(s); }
    { from_str(s); }
  real_c_float(const real_c_float &b)
  real_c_float(const real_c_float &b)
    { memcpy(image, b.image, sizeof(image)); }
    { memcpy(image, b.image, sizeof(image)); }
 
 
  const real_c_float& operator= (long l)
  const real_c_float& operator= (long l)
    { from_long(l); return *this; }
    { from_long(l); return *this; }
  const real_c_float& operator= (const char *s)
  const real_c_float& operator= (const char *s)
    { from_str(s); return *this; }
    { from_str(s); return *this; }
  const real_c_float& operator= (const real_c_float &b)
  const real_c_float& operator= (const real_c_float &b)
    { memcpy(image, b.image, sizeof(image)); return *this; }
    { memcpy(image, b.image, sizeof(image)); return *this; }
 
 
  const real_c_float& operator+= (const real_c_float &b)
  const real_c_float& operator+= (const real_c_float &b)
    { binop(PLUS_EXPR, b); return *this; }
    { binop(PLUS_EXPR, b); return *this; }
  const real_c_float& operator-= (const real_c_float &b)
  const real_c_float& operator-= (const real_c_float &b)
    { binop(MINUS_EXPR, b); return *this; }
    { binop(MINUS_EXPR, b); return *this; }
  const real_c_float& operator*= (const real_c_float &b)
  const real_c_float& operator*= (const real_c_float &b)
    { binop(MULT_EXPR, b); return *this; }
    { binop(MULT_EXPR, b); return *this; }
  const real_c_float& operator/= (const real_c_float &b)
  const real_c_float& operator/= (const real_c_float &b)
    { binop(RDIV_EXPR, b); return *this; }
    { binop(RDIV_EXPR, b); return *this; }
 
 
  real_c_float operator- () const
  real_c_float operator- () const
    { real_c_float r(*this); r.unop(NEGATE_EXPR); return r; }
    { real_c_float r(*this); r.unop(NEGATE_EXPR); return r; }
  real_c_float abs () const
  real_c_float abs () const
    { real_c_float r(*this); r.unop(ABS_EXPR); return r; }
    { real_c_float r(*this); r.unop(ABS_EXPR); return r; }
 
 
  bool operator <  (const real_c_float &b) const { return cmp(LT_EXPR, b); }
  bool operator <  (const real_c_float &b) const { return cmp(LT_EXPR, b); }
  bool operator <= (const real_c_float &b) const { return cmp(LE_EXPR, b); }
  bool operator <= (const real_c_float &b) const { return cmp(LE_EXPR, b); }
  bool operator == (const real_c_float &b) const { return cmp(EQ_EXPR, b); }
  bool operator == (const real_c_float &b) const { return cmp(EQ_EXPR, b); }
  bool operator != (const real_c_float &b) const { return cmp(NE_EXPR, b); }
  bool operator != (const real_c_float &b) const { return cmp(NE_EXPR, b); }
  bool operator >= (const real_c_float &b) const { return cmp(GE_EXPR, b); }
  bool operator >= (const real_c_float &b) const { return cmp(GE_EXPR, b); }
  bool operator >  (const real_c_float &b) const { return cmp(GT_EXPR, b); }
  bool operator >  (const real_c_float &b) const { return cmp(GT_EXPR, b); }
 
 
  const char * str () const;
  const char * str () const;
  const char * hex () const;
  const char * hex () const;
  long integer () const;
  long integer () const;
  int exp () const;
  int exp () const;
  void ldexp (int);
  void ldexp (int);
};
};
 
 
void
void
real_c_float::from_long (long l)
real_c_float::from_long (long l)
{
{
  REAL_VALUE_TYPE f;
  REAL_VALUE_TYPE f;
 
 
  real_from_integer (&f, MODE, l, l < 0 ? -1 : 0, 0);
  real_from_integer (&f, MODE, l, l < 0 ? -1 : 0, 0);
  real_to_target (image, &f, MODE);
  real_to_target (image, &f, MODE);
}
}
 
 
void
void
real_c_float::from_str (const char *s)
real_c_float::from_str (const char *s)
{
{
  REAL_VALUE_TYPE f;
  REAL_VALUE_TYPE f;
  const char *p = s;
  const char *p = s;
 
 
  if (*p == '-' || *p == '+')
  if (*p == '-' || *p == '+')
    p++;
    p++;
  if (strcasecmp(p, "inf") == 0)
  if (strcasecmp(p, "inf") == 0)
    {
    {
      real_inf (&f);
      real_inf (&f);
      if (*s == '-')
      if (*s == '-')
        real_arithmetic (&f, NEGATE_EXPR, &f, NULL);
        real_arithmetic (&f, NEGATE_EXPR, &f, NULL);
    }
    }
  else if (strcasecmp(p, "nan") == 0)
  else if (strcasecmp(p, "nan") == 0)
    real_nan (&f, "", 1, MODE);
    real_nan (&f, "", 1, MODE);
  else
  else
    real_from_string (&f, s);
    real_from_string (&f, s);
 
 
  real_to_target (image, &f, MODE);
  real_to_target (image, &f, MODE);
}
}
 
 
void
void
real_c_float::binop (int code, const real_c_float &b)
real_c_float::binop (int code, const real_c_float &b)
{
{
  REAL_VALUE_TYPE ai, bi, ri;
  REAL_VALUE_TYPE ai, bi, ri;
 
 
  real_from_target (&ai, image, MODE);
  real_from_target (&ai, image, MODE);
  real_from_target (&bi, b.image, MODE);
  real_from_target (&bi, b.image, MODE);
  real_arithmetic (&ri, code, &ai, &bi);
  real_arithmetic (&ri, code, &ai, &bi);
  real_to_target (image, &ri, MODE);
  real_to_target (image, &ri, MODE);
 
 
  if (verbose)
  if (verbose)
    {
    {
      char ab[64], bb[64], rb[64];
      char ab[64], bb[64], rb[64];
      const real_format *fmt = real_format_for_mode[MODE - QFmode];
      const real_format *fmt = real_format_for_mode[MODE - QFmode];
      const int digits = (fmt->p * fmt->log2_b + 3) / 4;
      const int digits = (fmt->p * fmt->log2_b + 3) / 4;
      char symbol_for_code;
      char symbol_for_code;
 
 
      real_from_target (&ri, image, MODE);
      real_from_target (&ri, image, MODE);
      real_to_hexadecimal (ab, &ai, sizeof(ab), digits, 0);
      real_to_hexadecimal (ab, &ai, sizeof(ab), digits, 0);
      real_to_hexadecimal (bb, &bi, sizeof(bb), digits, 0);
      real_to_hexadecimal (bb, &bi, sizeof(bb), digits, 0);
      real_to_hexadecimal (rb, &ri, sizeof(rb), digits, 0);
      real_to_hexadecimal (rb, &ri, sizeof(rb), digits, 0);
 
 
      switch (code)
      switch (code)
        {
        {
        case PLUS_EXPR:
        case PLUS_EXPR:
          symbol_for_code = '+';
          symbol_for_code = '+';
          break;
          break;
        case MINUS_EXPR:
        case MINUS_EXPR:
          symbol_for_code = '-';
          symbol_for_code = '-';
          break;
          break;
        case MULT_EXPR:
        case MULT_EXPR:
          symbol_for_code = '*';
          symbol_for_code = '*';
          break;
          break;
        case RDIV_EXPR:
        case RDIV_EXPR:
          symbol_for_code = '/';
          symbol_for_code = '/';
          break;
          break;
        default:
        default:
          abort ();
          abort ();
        }
        }
 
 
      fprintf (stderr, "%6d: %s %c %s = %s\n", verbose_index++,
      fprintf (stderr, "%6d: %s %c %s = %s\n", verbose_index++,
               ab, symbol_for_code, bb, rb);
               ab, symbol_for_code, bb, rb);
    }
    }
}
}
 
 
void
void
real_c_float::unop (int code)
real_c_float::unop (int code)
{
{
  REAL_VALUE_TYPE ai, ri;
  REAL_VALUE_TYPE ai, ri;
 
 
  real_from_target (&ai, image, MODE);
  real_from_target (&ai, image, MODE);
  real_arithmetic (&ri, code, &ai, NULL);
  real_arithmetic (&ri, code, &ai, NULL);
  real_to_target (image, &ri, MODE);
  real_to_target (image, &ri, MODE);
 
 
  if (verbose)
  if (verbose)
    {
    {
      char ab[64], rb[64];
      char ab[64], rb[64];
      const real_format *fmt = real_format_for_mode[MODE - QFmode];
      const real_format *fmt = real_format_for_mode[MODE - QFmode];
      const int digits = (fmt->p * fmt->log2_b + 3) / 4;
      const int digits = (fmt->p * fmt->log2_b + 3) / 4;
      const char *symbol_for_code;
      const char *symbol_for_code;
 
 
      real_from_target (&ri, image, MODE);
      real_from_target (&ri, image, MODE);
      real_to_hexadecimal (ab, &ai, sizeof(ab), digits, 0);
      real_to_hexadecimal (ab, &ai, sizeof(ab), digits, 0);
      real_to_hexadecimal (rb, &ri, sizeof(rb), digits, 0);
      real_to_hexadecimal (rb, &ri, sizeof(rb), digits, 0);
 
 
      switch (code)
      switch (code)
        {
        {
        case NEGATE_EXPR:
        case NEGATE_EXPR:
          symbol_for_code = "-";
          symbol_for_code = "-";
          break;
          break;
        case ABS_EXPR:
        case ABS_EXPR:
          symbol_for_code = "abs ";
          symbol_for_code = "abs ";
          break;
          break;
        default:
        default:
          abort ();
          abort ();
        }
        }
 
 
      fprintf (stderr, "%6d: %s%s = %s\n", verbose_index++,
      fprintf (stderr, "%6d: %s%s = %s\n", verbose_index++,
               symbol_for_code, ab, rb);
               symbol_for_code, ab, rb);
    }
    }
}
}
 
 
bool
bool
real_c_float::cmp (int code, const real_c_float &b) const
real_c_float::cmp (int code, const real_c_float &b) const
{
{
  REAL_VALUE_TYPE ai, bi;
  REAL_VALUE_TYPE ai, bi;
  bool ret;
  bool ret;
 
 
  real_from_target (&ai, image, MODE);
  real_from_target (&ai, image, MODE);
  real_from_target (&bi, b.image, MODE);
  real_from_target (&bi, b.image, MODE);
  ret = real_compare (code, &ai, &bi);
  ret = real_compare (code, &ai, &bi);
 
 
  if (verbose)
  if (verbose)
    {
    {
      char ab[64], bb[64];
      char ab[64], bb[64];
      const real_format *fmt = real_format_for_mode[MODE - QFmode];
      const real_format *fmt = real_format_for_mode[MODE - QFmode];
      const int digits = (fmt->p * fmt->log2_b + 3) / 4;
      const int digits = (fmt->p * fmt->log2_b + 3) / 4;
      const char *symbol_for_code;
      const char *symbol_for_code;
 
 
      real_to_hexadecimal (ab, &ai, sizeof(ab), digits, 0);
      real_to_hexadecimal (ab, &ai, sizeof(ab), digits, 0);
      real_to_hexadecimal (bb, &bi, sizeof(bb), digits, 0);
      real_to_hexadecimal (bb, &bi, sizeof(bb), digits, 0);
 
 
      switch (code)
      switch (code)
        {
        {
        case LT_EXPR:
        case LT_EXPR:
          symbol_for_code = "<";
          symbol_for_code = "<";
          break;
          break;
        case LE_EXPR:
        case LE_EXPR:
          symbol_for_code = "<=";
          symbol_for_code = "<=";
          break;
          break;
        case EQ_EXPR:
        case EQ_EXPR:
          symbol_for_code = "==";
          symbol_for_code = "==";
          break;
          break;
        case NE_EXPR:
        case NE_EXPR:
          symbol_for_code = "!=";
          symbol_for_code = "!=";
          break;
          break;
        case GE_EXPR:
        case GE_EXPR:
          symbol_for_code = ">=";
          symbol_for_code = ">=";
          break;
          break;
        case GT_EXPR:
        case GT_EXPR:
          symbol_for_code = ">";
          symbol_for_code = ">";
          break;
          break;
        default:
        default:
          abort ();
          abort ();
        }
        }
 
 
      fprintf (stderr, "%6d: %s %s %s = %s\n", verbose_index++,
      fprintf (stderr, "%6d: %s %s %s = %s\n", verbose_index++,
               ab, symbol_for_code, bb, (ret ? "true" : "false"));
               ab, symbol_for_code, bb, (ret ? "true" : "false"));
    }
    }
 
 
  return ret;
  return ret;
}
}
 
 
const char *
const char *
real_c_float::str() const
real_c_float::str() const
{
{
  REAL_VALUE_TYPE f;
  REAL_VALUE_TYPE f;
  const real_format *fmt = real_format_for_mode[MODE - QFmode];
  const real_format *fmt = real_format_for_mode[MODE - QFmode];
  const int digits = int(fmt->p * fmt->log2_b * .30102999566398119521 + 1);
  const int digits = int(fmt->p * fmt->log2_b * .30102999566398119521 + 1);
 
 
  real_from_target (&f, image, MODE);
  real_from_target (&f, image, MODE);
  char *buf = new char[digits + 10];
  char *buf = new char[digits + 10];
  real_to_decimal (buf, &f, digits+10, digits, 0);
  real_to_decimal (buf, &f, digits+10, digits, 0);
 
 
  return buf;
  return buf;
}
}
 
 
const char *
const char *
real_c_float::hex() const
real_c_float::hex() const
{
{
  REAL_VALUE_TYPE f;
  REAL_VALUE_TYPE f;
  const real_format *fmt = real_format_for_mode[MODE - QFmode];
  const real_format *fmt = real_format_for_mode[MODE - QFmode];
  const int digits = (fmt->p * fmt->log2_b + 3) / 4;
  const int digits = (fmt->p * fmt->log2_b + 3) / 4;
 
 
  real_from_target (&f, image, MODE);
  real_from_target (&f, image, MODE);
  char *buf = new char[digits + 10];
  char *buf = new char[digits + 10];
  real_to_hexadecimal (buf, &f, digits+10, digits, 0);
  real_to_hexadecimal (buf, &f, digits+10, digits, 0);
 
 
  return buf;
  return buf;
}
}
 
 
long
long
real_c_float::integer() const
real_c_float::integer() const
{
{
  REAL_VALUE_TYPE f;
  REAL_VALUE_TYPE f;
  real_from_target (&f, image, MODE);
  real_from_target (&f, image, MODE);
  return real_to_integer (&f);
  return real_to_integer (&f);
}
}
 
 
int
int
real_c_float::exp() const
real_c_float::exp() const
{
{
  REAL_VALUE_TYPE f;
  REAL_VALUE_TYPE f;
  real_from_target (&f, image, MODE);
  real_from_target (&f, image, MODE);
  return real_exponent (&f);
  return real_exponent (&f);
}
}
 
 
void
void
real_c_float::ldexp (int exp)
real_c_float::ldexp (int exp)
{
{
  REAL_VALUE_TYPE ai;
  REAL_VALUE_TYPE ai;
 
 
  real_from_target (&ai, image, MODE);
  real_from_target (&ai, image, MODE);
  real_ldexp (&ai, &ai, exp);
  real_ldexp (&ai, &ai, exp);
  real_to_target (image, &ai, MODE);
  real_to_target (image, &ai, MODE);
}
}
 
 
/* ====================================================================== */
/* ====================================================================== */
/* An implementation of the abstract floating point class that uses native
/* An implementation of the abstract floating point class that uses native
   arithmetic.  Exists for reference and debugging.  */
   arithmetic.  Exists for reference and debugging.  */
 
 
template<typename T>
template<typename T>
class native_float
class native_float
{
{
 private:
 private:
  // Force intermediate results back to memory.
  // Force intermediate results back to memory.
  volatile T image;
  volatile T image;
 
 
  static T from_str (const char *);
  static T from_str (const char *);
  static T do_abs (T);
  static T do_abs (T);
  static T verbose_binop (T, char, T, T);
  static T verbose_binop (T, char, T, T);
  static T verbose_unop (const char *, T, T);
  static T verbose_unop (const char *, T, T);
  static bool verbose_cmp (T, const char *, T, bool);
  static bool verbose_cmp (T, const char *, T, bool);
 
 
 public:
 public:
  native_float()
  native_float()
    { }
    { }
  native_float(long l)
  native_float(long l)
    { image = l; }
    { image = l; }
  native_float(const char *s)
  native_float(const char *s)
    { image = from_str(s); }
    { image = from_str(s); }
  native_float(const native_float &b)
  native_float(const native_float &b)
    { image = b.image; }
    { image = b.image; }
 
 
  const native_float& operator= (long l)
  const native_float& operator= (long l)
    { image = l; return *this; }
    { image = l; return *this; }
  const native_float& operator= (const char *s)
  const native_float& operator= (const char *s)
    { image = from_str(s); return *this; }
    { image = from_str(s); return *this; }
  const native_float& operator= (const native_float &b)
  const native_float& operator= (const native_float &b)
    { image = b.image; return *this; }
    { image = b.image; return *this; }
 
 
  const native_float& operator+= (const native_float &b)
  const native_float& operator+= (const native_float &b)
    {
    {
      image = verbose_binop(image, '+', b.image, image + b.image);
      image = verbose_binop(image, '+', b.image, image + b.image);
      return *this;
      return *this;
    }
    }
  const native_float& operator-= (const native_float &b)
  const native_float& operator-= (const native_float &b)
    {
    {
      image = verbose_binop(image, '-', b.image, image - b.image);
      image = verbose_binop(image, '-', b.image, image - b.image);
      return *this;
      return *this;
    }
    }
  const native_float& operator*= (const native_float &b)
  const native_float& operator*= (const native_float &b)
    {
    {
      image = verbose_binop(image, '*', b.image, image * b.image);
      image = verbose_binop(image, '*', b.image, image * b.image);
      return *this;
      return *this;
    }
    }
  const native_float& operator/= (const native_float &b)
  const native_float& operator/= (const native_float &b)
    {
    {
      image = verbose_binop(image, '/', b.image, image / b.image);
      image = verbose_binop(image, '/', b.image, image / b.image);
      return *this;
      return *this;
    }
    }
 
 
  native_float operator- () const
  native_float operator- () const
    {
    {
      native_float r;
      native_float r;
      r.image = verbose_unop("-", image, -image);
      r.image = verbose_unop("-", image, -image);
      return r;
      return r;
    }
    }
  native_float abs () const
  native_float abs () const
    {
    {
      native_float r;
      native_float r;
      r.image = verbose_unop("abs ", image, do_abs(image));
      r.image = verbose_unop("abs ", image, do_abs(image));
      return r;
      return r;
    }
    }
 
 
  bool operator <  (const native_float &b) const
  bool operator <  (const native_float &b) const
    { return verbose_cmp(image, "<", b.image, image <  b.image); }
    { return verbose_cmp(image, "<", b.image, image <  b.image); }
  bool operator <= (const native_float &b) const
  bool operator <= (const native_float &b) const
    { return verbose_cmp(image, "<=", b.image, image <= b.image); }
    { return verbose_cmp(image, "<=", b.image, image <= b.image); }
  bool operator == (const native_float &b) const
  bool operator == (const native_float &b) const
    { return verbose_cmp(image, "==", b.image, image == b.image); }
    { return verbose_cmp(image, "==", b.image, image == b.image); }
  bool operator != (const native_float &b) const
  bool operator != (const native_float &b) const
    { return verbose_cmp(image, "!=", b.image, image != b.image); }
    { return verbose_cmp(image, "!=", b.image, image != b.image); }
  bool operator >= (const native_float &b) const
  bool operator >= (const native_float &b) const
    { return verbose_cmp(image, ">=", b.image, image >= b.image); }
    { return verbose_cmp(image, ">=", b.image, image >= b.image); }
  bool operator >  (const native_float &b) const
  bool operator >  (const native_float &b) const
    { return verbose_cmp(image, ">", b.image, image > b.image); }
    { return verbose_cmp(image, ">", b.image, image > b.image); }
 
 
  const char * str () const;
  const char * str () const;
  const char * hex () const;
  const char * hex () const;
  long integer () const
  long integer () const
    { return long(image); }
    { return long(image); }
  int exp () const;
  int exp () const;
  void ldexp (int);
  void ldexp (int);
};
};
 
 
template<typename T>
template<typename T>
inline T
inline T
native_float<T>::from_str (const char *s)
native_float<T>::from_str (const char *s)
{
{
  return strtold (s, NULL);
  return strtold (s, NULL);
}
}
 
 
template<>
template<>
inline float
inline float
native_float<float>::from_str (const char *s)
native_float<float>::from_str (const char *s)
{
{
  return strtof (s, NULL);
  return strtof (s, NULL);
}
}
 
 
template<>
template<>
inline double
inline double
native_float<double>::from_str (const char *s)
native_float<double>::from_str (const char *s)
{
{
  return strtod (s, NULL);
  return strtod (s, NULL);
}
}
 
 
template<typename T>
template<typename T>
inline T
inline T
native_float<T>::do_abs (T image)
native_float<T>::do_abs (T image)
{
{
  return fabsl (image);
  return fabsl (image);
}
}
 
 
template<>
template<>
inline float
inline float
native_float<float>::do_abs (float image)
native_float<float>::do_abs (float image)
{
{
  return fabsf (image);
  return fabsf (image);
}
}
 
 
template<>
template<>
inline double
inline double
native_float<double>::do_abs (double image)
native_float<double>::do_abs (double image)
{
{
  return fabs (image);
  return fabs (image);
}
}
 
 
template<typename T>
template<typename T>
T
T
native_float<T>::verbose_binop (T a, char symbol, T b, T r)
native_float<T>::verbose_binop (T a, char symbol, T b, T r)
{
{
  if (verbose)
  if (verbose)
    {
    {
      const int digits = int(sizeof(T) * CHAR_BIT / 4) - 1;
      const int digits = int(sizeof(T) * CHAR_BIT / 4) - 1;
#ifdef NO_LONG_DOUBLE
#ifdef NO_LONG_DOUBLE
      fprintf (stderr, "%6d: %.*a %c %.*a = %.*a\n", verbose_index++,
      fprintf (stderr, "%6d: %.*a %c %.*a = %.*a\n", verbose_index++,
               digits, (double)a, symbol,
               digits, (double)a, symbol,
               digits, (double)b, digits, (double)r);
               digits, (double)b, digits, (double)r);
#else
#else
      fprintf (stderr, "%6d: %.*La %c %.*La = %.*La\n", verbose_index++,
      fprintf (stderr, "%6d: %.*La %c %.*La = %.*La\n", verbose_index++,
               digits, (long double)a, symbol,
               digits, (long double)a, symbol,
               digits, (long double)b, digits, (long double)r);
               digits, (long double)b, digits, (long double)r);
#endif
#endif
    }
    }
  return r;
  return r;
}
}
 
 
template<typename T>
template<typename T>
T
T
native_float<T>::verbose_unop (const char *symbol, T a, T r)
native_float<T>::verbose_unop (const char *symbol, T a, T r)
{
{
  if (verbose)
  if (verbose)
    {
    {
      const int digits = int(sizeof(T) * CHAR_BIT / 4) - 1;
      const int digits = int(sizeof(T) * CHAR_BIT / 4) - 1;
#ifdef NO_LONG_DOUBLE
#ifdef NO_LONG_DOUBLE
      fprintf (stderr, "%6d: %s%.*a = %.*a\n", verbose_index++,
      fprintf (stderr, "%6d: %s%.*a = %.*a\n", verbose_index++,
               symbol, digits, (double)a, digits, (double)r);
               symbol, digits, (double)a, digits, (double)r);
#else
#else
      fprintf (stderr, "%6d: %s%.*La = %.*La\n", verbose_index++,
      fprintf (stderr, "%6d: %s%.*La = %.*La\n", verbose_index++,
               symbol, digits, (long double)a, digits, (long double)r);
               symbol, digits, (long double)a, digits, (long double)r);
#endif
#endif
    }
    }
  return r;
  return r;
}
}
 
 
template<typename T>
template<typename T>
bool
bool
native_float<T>::verbose_cmp (T a, const char *symbol, T b, bool r)
native_float<T>::verbose_cmp (T a, const char *symbol, T b, bool r)
{
{
  if (verbose)
  if (verbose)
    {
    {
      const int digits = int(sizeof(T) * CHAR_BIT / 4) - 1;
      const int digits = int(sizeof(T) * CHAR_BIT / 4) - 1;
#ifndef NO_LONG_DOUBLE
#ifndef NO_LONG_DOUBLE
      fprintf (stderr, "%6d: %.*a %s %.*a = %s\n", verbose_index++,
      fprintf (stderr, "%6d: %.*a %s %.*a = %s\n", verbose_index++,
               digits, (double)a, symbol,
               digits, (double)a, symbol,
               digits, (double)b, (r ? "true" : "false"));
               digits, (double)b, (r ? "true" : "false"));
#else
#else
      fprintf (stderr, "%6d: %.*La %s %.*La = %s\n", verbose_index++,
      fprintf (stderr, "%6d: %.*La %s %.*La = %s\n", verbose_index++,
               digits, (long double)a, symbol,
               digits, (long double)a, symbol,
               digits, (long double)b, (r ? "true" : "false"));
               digits, (long double)b, (r ? "true" : "false"));
#endif
#endif
    }
    }
  return r;
  return r;
}
}
 
 
template<typename T>
template<typename T>
const char *
const char *
native_float<T>::str() const
native_float<T>::str() const
{
{
  char *buf = new char[50];
  char *buf = new char[50];
  const int digits = int(sizeof(T) * CHAR_BIT * .30102999566398119521 + 1);
  const int digits = int(sizeof(T) * CHAR_BIT * .30102999566398119521 + 1);
#ifndef NO_LONG_DOUBLE
#ifndef NO_LONG_DOUBLE
  sprintf (buf, "%.*e", digits - 1, (double) image);
  sprintf (buf, "%.*e", digits - 1, (double) image);
#else
#else
  sprintf (buf, "%.*Le", digits - 1, (long double) image);
  sprintf (buf, "%.*Le", digits - 1, (long double) image);
#endif
#endif
  return buf;
  return buf;
}
}
 
 
template<typename T>
template<typename T>
const char *
const char *
native_float<T>::hex() const
native_float<T>::hex() const
{
{
  char *buf = new char[50];
  char *buf = new char[50];
  const int digits = int(sizeof(T) * CHAR_BIT / 4);
  const int digits = int(sizeof(T) * CHAR_BIT / 4);
#ifndef NO_LONG_DOUBLE
#ifndef NO_LONG_DOUBLE
  sprintf (buf, "%.*a", digits - 1, (double) image);
  sprintf (buf, "%.*a", digits - 1, (double) image);
#else
#else
  sprintf (buf, "%.*La", digits - 1, (long double) image);
  sprintf (buf, "%.*La", digits - 1, (long double) image);
#endif
#endif
  return buf;
  return buf;
}
}
 
 
template<typename T>
template<typename T>
int
int
native_float<T>::exp() const
native_float<T>::exp() const
{
{
  int e;
  int e;
  frexp (image, &e);
  frexp (image, &e);
  return e;
  return e;
}
}
 
 
template<typename T>
template<typename T>
void
void
native_float<T>::ldexp (int exp)
native_float<T>::ldexp (int exp)
{
{
  image = ldexpl (image, exp);
  image = ldexpl (image, exp);
}
}
 
 
template<>
template<>
void
void
native_float<float>::ldexp (int exp)
native_float<float>::ldexp (int exp)
{
{
  image = ldexpf (image, exp);
  image = ldexpf (image, exp);
}
}
 
 
template<>
template<>
void
void
native_float<double>::ldexp (int exp)
native_float<double>::ldexp (int exp)
{
{
  image = ::ldexp (image, exp);
  image = ::ldexp (image, exp);
}
}
 
 
/* ====================================================================== */
/* ====================================================================== */
/* Some libm routines that Paranoia expects to be available.  */
/* Some libm routines that Paranoia expects to be available.  */
 
 
template<typename FLOAT>
template<typename FLOAT>
inline FLOAT
inline FLOAT
FABS (const FLOAT &f)
FABS (const FLOAT &f)
{
{
  return f.abs();
  return f.abs();
}
}
 
 
template<typename FLOAT, typename RHS>
template<typename FLOAT, typename RHS>
inline FLOAT
inline FLOAT
operator+ (const FLOAT &a, const RHS &b)
operator+ (const FLOAT &a, const RHS &b)
{
{
  return FLOAT(a) += FLOAT(b);
  return FLOAT(a) += FLOAT(b);
}
}
 
 
template<typename FLOAT, typename RHS>
template<typename FLOAT, typename RHS>
inline FLOAT
inline FLOAT
operator- (const FLOAT &a, const RHS &b)
operator- (const FLOAT &a, const RHS &b)
{
{
  return FLOAT(a) -= FLOAT(b);
  return FLOAT(a) -= FLOAT(b);
}
}
 
 
template<typename FLOAT, typename RHS>
template<typename FLOAT, typename RHS>
inline FLOAT
inline FLOAT
operator* (const FLOAT &a, const RHS &b)
operator* (const FLOAT &a, const RHS &b)
{
{
  return FLOAT(a) *= FLOAT(b);
  return FLOAT(a) *= FLOAT(b);
}
}
 
 
template<typename FLOAT, typename RHS>
template<typename FLOAT, typename RHS>
inline FLOAT
inline FLOAT
operator/ (const FLOAT &a, const RHS &b)
operator/ (const FLOAT &a, const RHS &b)
{
{
  return FLOAT(a) /= FLOAT(b);
  return FLOAT(a) /= FLOAT(b);
}
}
 
 
template<typename FLOAT>
template<typename FLOAT>
FLOAT
FLOAT
FLOOR (const FLOAT &f)
FLOOR (const FLOAT &f)
{
{
  /* ??? This is only correct when F is representable as an integer.  */
  /* ??? This is only correct when F is representable as an integer.  */
  long i = f.integer();
  long i = f.integer();
  FLOAT r;
  FLOAT r;
 
 
  r = i;
  r = i;
  if (i < 0 && f != r)
  if (i < 0 && f != r)
    r = i - 1;
    r = i - 1;
 
 
  return r;
  return r;
}
}
 
 
template<typename FLOAT>
template<typename FLOAT>
FLOAT
FLOAT
SQRT (const FLOAT &f)
SQRT (const FLOAT &f)
{
{
#if 0
#if 0
  FLOAT zero = long(0);
  FLOAT zero = long(0);
  FLOAT two = 2;
  FLOAT two = 2;
  FLOAT one = 1;
  FLOAT one = 1;
  FLOAT diff, diff2;
  FLOAT diff, diff2;
  FLOAT z, t;
  FLOAT z, t;
 
 
  if (f == zero)
  if (f == zero)
    return zero;
    return zero;
  if (f < zero)
  if (f < zero)
    return zero / zero;
    return zero / zero;
  if (f == one)
  if (f == one)
    return f;
    return f;
 
 
  z = f;
  z = f;
  z.ldexp (-f.exp() / 2);
  z.ldexp (-f.exp() / 2);
 
 
  diff2 = FABS (z * z - f);
  diff2 = FABS (z * z - f);
  if (diff2 > zero)
  if (diff2 > zero)
    while (1)
    while (1)
      {
      {
        t = (f / (two * z)) + (z / two);
        t = (f / (two * z)) + (z / two);
        diff = FABS (t * t - f);
        diff = FABS (t * t - f);
        if (diff >= diff2)
        if (diff >= diff2)
          break;
          break;
        z = t;
        z = t;
        diff2 = diff;
        diff2 = diff;
      }
      }
 
 
  return z;
  return z;
#elif defined(NO_LONG_DOUBLE)
#elif defined(NO_LONG_DOUBLE)
  double d;
  double d;
  char buf[64];
  char buf[64];
 
 
  d = strtod (f.hex(), NULL);
  d = strtod (f.hex(), NULL);
  d = sqrt (d);
  d = sqrt (d);
  sprintf(buf, "%.35a", d);
  sprintf(buf, "%.35a", d);
 
 
  return FLOAT(buf);
  return FLOAT(buf);
#else
#else
  long double ld;
  long double ld;
  char buf[64];
  char buf[64];
 
 
  ld = strtold (f.hex(), NULL);
  ld = strtold (f.hex(), NULL);
  ld = sqrtl (ld);
  ld = sqrtl (ld);
  sprintf(buf, "%.35La", ld);
  sprintf(buf, "%.35La", ld);
 
 
  return FLOAT(buf);
  return FLOAT(buf);
#endif
#endif
}
}
 
 
template<typename FLOAT>
template<typename FLOAT>
FLOAT
FLOAT
LOG (FLOAT x)
LOG (FLOAT x)
{
{
#if 0
#if 0
  FLOAT zero = long(0);
  FLOAT zero = long(0);
  FLOAT one = 1;
  FLOAT one = 1;
 
 
  if (x <= zero)
  if (x <= zero)
    return zero / zero;
    return zero / zero;
  if (x == one)
  if (x == one)
    return zero;
    return zero;
 
 
  int exp = x.exp() - 1;
  int exp = x.exp() - 1;
  x.ldexp(-exp);
  x.ldexp(-exp);
 
 
  FLOAT xm1 = x - one;
  FLOAT xm1 = x - one;
  FLOAT y = xm1;
  FLOAT y = xm1;
  long n = 2;
  long n = 2;
 
 
  FLOAT sum = xm1;
  FLOAT sum = xm1;
  while (1)
  while (1)
    {
    {
      y *= xm1;
      y *= xm1;
      FLOAT term = y / FLOAT (n);
      FLOAT term = y / FLOAT (n);
      FLOAT next = sum + term;
      FLOAT next = sum + term;
      if (next == sum)
      if (next == sum)
        break;
        break;
      sum = next;
      sum = next;
      if (++n == 1000)
      if (++n == 1000)
        break;
        break;
    }
    }
 
 
  if (exp)
  if (exp)
    sum += FLOAT (exp) * FLOAT(".69314718055994530941");
    sum += FLOAT (exp) * FLOAT(".69314718055994530941");
 
 
  return sum;
  return sum;
#elif defined (NO_LONG_DOUBLE)
#elif defined (NO_LONG_DOUBLE)
  double d;
  double d;
  char buf[64];
  char buf[64];
 
 
  d = strtod (x.hex(), NULL);
  d = strtod (x.hex(), NULL);
  d = log (d);
  d = log (d);
  sprintf(buf, "%.35a", d);
  sprintf(buf, "%.35a", d);
 
 
  return FLOAT(buf);
  return FLOAT(buf);
#else
#else
  long double ld;
  long double ld;
  char buf[64];
  char buf[64];
 
 
  ld = strtold (x.hex(), NULL);
  ld = strtold (x.hex(), NULL);
  ld = logl (ld);
  ld = logl (ld);
  sprintf(buf, "%.35La", ld);
  sprintf(buf, "%.35La", ld);
 
 
  return FLOAT(buf);
  return FLOAT(buf);
#endif
#endif
}
}
 
 
template<typename FLOAT>
template<typename FLOAT>
FLOAT
FLOAT
EXP (const FLOAT &x)
EXP (const FLOAT &x)
{
{
  /* Cheat.  */
  /* Cheat.  */
#ifdef NO_LONG_DOUBLE
#ifdef NO_LONG_DOUBLE
  double d;
  double d;
  char buf[64];
  char buf[64];
 
 
  d = strtod (x.hex(), NULL);
  d = strtod (x.hex(), NULL);
  d = exp (d);
  d = exp (d);
  sprintf(buf, "%.35a", d);
  sprintf(buf, "%.35a", d);
 
 
  return FLOAT(buf);
  return FLOAT(buf);
#else
#else
  long double ld;
  long double ld;
  char buf[64];
  char buf[64];
 
 
  ld = strtold (x.hex(), NULL);
  ld = strtold (x.hex(), NULL);
  ld = expl (ld);
  ld = expl (ld);
  sprintf(buf, "%.35La", ld);
  sprintf(buf, "%.35La", ld);
 
 
  return FLOAT(buf);
  return FLOAT(buf);
#endif
#endif
}
}
 
 
template<typename FLOAT>
template<typename FLOAT>
FLOAT
FLOAT
POW (const FLOAT &base, const FLOAT &exp)
POW (const FLOAT &base, const FLOAT &exp)
{
{
  /* Cheat.  */
  /* Cheat.  */
#ifdef NO_LONG_DOUBLE
#ifdef NO_LONG_DOUBLE
  double d1, d2;
  double d1, d2;
  char buf[64];
  char buf[64];
 
 
  d1 = strtod (base.hex(), NULL);
  d1 = strtod (base.hex(), NULL);
  d2 = strtod (exp.hex(), NULL);
  d2 = strtod (exp.hex(), NULL);
  d1 = pow (d1, d2);
  d1 = pow (d1, d2);
  sprintf(buf, "%.35a", d1);
  sprintf(buf, "%.35a", d1);
 
 
  return FLOAT(buf);
  return FLOAT(buf);
#else
#else
  long double ld1, ld2;
  long double ld1, ld2;
  char buf[64];
  char buf[64];
 
 
  ld1 = strtold (base.hex(), NULL);
  ld1 = strtold (base.hex(), NULL);
  ld2 = strtold (exp.hex(), NULL);
  ld2 = strtold (exp.hex(), NULL);
  ld1 = powl (ld1, ld2);
  ld1 = powl (ld1, ld2);
  sprintf(buf, "%.35La", ld1);
  sprintf(buf, "%.35La", ld1);
 
 
  return FLOAT(buf);
  return FLOAT(buf);
#endif
#endif
}
}
 
 
/* ====================================================================== */
/* ====================================================================== */
/* Real Paranoia begins again here.  We wrap the thing in a template so
/* Real Paranoia begins again here.  We wrap the thing in a template so
   that we can instantiate it for each floating point type we care for.  */
   that we can instantiate it for each floating point type we care for.  */
 
 
int NoTrials = 20;              /*Number of tests for commutativity. */
int NoTrials = 20;              /*Number of tests for commutativity. */
bool do_pause = false;
bool do_pause = false;
 
 
enum Guard { No, Yes };
enum Guard { No, Yes };
enum Rounding { Other, Rounded, Chopped };
enum Rounding { Other, Rounded, Chopped };
enum Class { Failure, Serious, Defect, Flaw };
enum Class { Failure, Serious, Defect, Flaw };
 
 
template<typename FLOAT>
template<typename FLOAT>
struct Paranoia
struct Paranoia
{
{
  FLOAT Radix, BInvrse, RadixD2, BMinusU2;
  FLOAT Radix, BInvrse, RadixD2, BMinusU2;
 
 
  /* Small floating point constants.  */
  /* Small floating point constants.  */
  FLOAT Zero;
  FLOAT Zero;
  FLOAT Half;
  FLOAT Half;
  FLOAT One;
  FLOAT One;
  FLOAT Two;
  FLOAT Two;
  FLOAT Three;
  FLOAT Three;
  FLOAT Four;
  FLOAT Four;
  FLOAT Five;
  FLOAT Five;
  FLOAT Eight;
  FLOAT Eight;
  FLOAT Nine;
  FLOAT Nine;
  FLOAT TwentySeven;
  FLOAT TwentySeven;
  FLOAT ThirtyTwo;
  FLOAT ThirtyTwo;
  FLOAT TwoForty;
  FLOAT TwoForty;
  FLOAT MinusOne;
  FLOAT MinusOne;
  FLOAT OneAndHalf;
  FLOAT OneAndHalf;
 
 
  /* Declarations of Variables.  */
  /* Declarations of Variables.  */
  int Indx;
  int Indx;
  char ch[8];
  char ch[8];
  FLOAT AInvrse, A1;
  FLOAT AInvrse, A1;
  FLOAT C, CInvrse;
  FLOAT C, CInvrse;
  FLOAT D, FourD;
  FLOAT D, FourD;
  FLOAT E0, E1, Exp2, E3, MinSqEr;
  FLOAT E0, E1, Exp2, E3, MinSqEr;
  FLOAT SqEr, MaxSqEr, E9;
  FLOAT SqEr, MaxSqEr, E9;
  FLOAT Third;
  FLOAT Third;
  FLOAT F6, F9;
  FLOAT F6, F9;
  FLOAT H, HInvrse;
  FLOAT H, HInvrse;
  int I;
  int I;
  FLOAT StickyBit, J;
  FLOAT StickyBit, J;
  FLOAT MyZero;
  FLOAT MyZero;
  FLOAT Precision;
  FLOAT Precision;
  FLOAT Q, Q9;
  FLOAT Q, Q9;
  FLOAT R, Random9;
  FLOAT R, Random9;
  FLOAT T, Underflow, S;
  FLOAT T, Underflow, S;
  FLOAT OneUlp, UfThold, U1, U2;
  FLOAT OneUlp, UfThold, U1, U2;
  FLOAT V, V0, V9;
  FLOAT V, V0, V9;
  FLOAT W;
  FLOAT W;
  FLOAT X, X1, X2, X8, Random1;
  FLOAT X, X1, X2, X8, Random1;
  FLOAT Y, Y1, Y2, Random2;
  FLOAT Y, Y1, Y2, Random2;
  FLOAT Z, PseudoZero, Z1, Z2, Z9;
  FLOAT Z, PseudoZero, Z1, Z2, Z9;
  int ErrCnt[4];
  int ErrCnt[4];
  int Milestone;
  int Milestone;
  int PageNo;
  int PageNo;
  int M, N, N1;
  int M, N, N1;
  Guard GMult, GDiv, GAddSub;
  Guard GMult, GDiv, GAddSub;
  Rounding RMult, RDiv, RAddSub, RSqrt;
  Rounding RMult, RDiv, RAddSub, RSqrt;
  int Break, Done, NotMonot, Monot, Anomaly, IEEE, SqRWrng, UfNGrad;
  int Break, Done, NotMonot, Monot, Anomaly, IEEE, SqRWrng, UfNGrad;
 
 
  /* Computed constants. */
  /* Computed constants. */
  /*U1  gap below 1.0, i.e, 1.0-U1 is next number below 1.0 */
  /*U1  gap below 1.0, i.e, 1.0-U1 is next number below 1.0 */
  /*U2  gap above 1.0, i.e, 1.0+U2 is next number above 1.0 */
  /*U2  gap above 1.0, i.e, 1.0+U2 is next number above 1.0 */
 
 
  int main ();
  int main ();
 
 
  FLOAT Sign (FLOAT);
  FLOAT Sign (FLOAT);
  FLOAT Random ();
  FLOAT Random ();
  void Pause ();
  void Pause ();
  void BadCond (int, const char *);
  void BadCond (int, const char *);
  void SqXMinX (int);
  void SqXMinX (int);
  void TstCond (int, int, const char *);
  void TstCond (int, int, const char *);
  void notify (const char *);
  void notify (const char *);
  void IsYeqX ();
  void IsYeqX ();
  void NewD ();
  void NewD ();
  void PrintIfNPositive ();
  void PrintIfNPositive ();
  void SR3750 ();
  void SR3750 ();
  void TstPtUf ();
  void TstPtUf ();
 
 
  // Pretend we're bss.
  // Pretend we're bss.
  Paranoia() { memset(this, 0, sizeof (*this)); }
  Paranoia() { memset(this, 0, sizeof (*this)); }
};
};
 
 
template<typename FLOAT>
template<typename FLOAT>
int
int
Paranoia<FLOAT>::main()
Paranoia<FLOAT>::main()
{
{
  /* First two assignments use integer right-hand sides. */
  /* First two assignments use integer right-hand sides. */
  Zero = long(0);
  Zero = long(0);
  One = long(1);
  One = long(1);
  Two = long(2);
  Two = long(2);
  Three = long(3);
  Three = long(3);
  Four = long(4);
  Four = long(4);
  Five = long(5);
  Five = long(5);
  Eight = long(8);
  Eight = long(8);
  Nine = long(9);
  Nine = long(9);
  TwentySeven = long(27);
  TwentySeven = long(27);
  ThirtyTwo = long(32);
  ThirtyTwo = long(32);
  TwoForty = long(240);
  TwoForty = long(240);
  MinusOne = long(-1);
  MinusOne = long(-1);
  Half = "0x1p-1";
  Half = "0x1p-1";
  OneAndHalf = "0x3p-1";
  OneAndHalf = "0x3p-1";
  ErrCnt[Failure] = 0;
  ErrCnt[Failure] = 0;
  ErrCnt[Serious] = 0;
  ErrCnt[Serious] = 0;
  ErrCnt[Defect] = 0;
  ErrCnt[Defect] = 0;
  ErrCnt[Flaw] = 0;
  ErrCnt[Flaw] = 0;
  PageNo = 1;
  PageNo = 1;
        /*=============================================*/
        /*=============================================*/
  Milestone = 7;
  Milestone = 7;
        /*=============================================*/
        /*=============================================*/
  printf ("Program is now RUNNING tests on small integers:\n");
  printf ("Program is now RUNNING tests on small integers:\n");
 
 
  TstCond (Failure, (Zero + Zero == Zero), "0+0 != 0");
  TstCond (Failure, (Zero + Zero == Zero), "0+0 != 0");
  TstCond (Failure, (One - One == Zero), "1-1 != 0");
  TstCond (Failure, (One - One == Zero), "1-1 != 0");
  TstCond (Failure, (One > Zero), "1 <= 0");
  TstCond (Failure, (One > Zero), "1 <= 0");
  TstCond (Failure, (One + One == Two), "1+1 != 2");
  TstCond (Failure, (One + One == Two), "1+1 != 2");
 
 
  Z = -Zero;
  Z = -Zero;
  if (Z != Zero)
  if (Z != Zero)
    {
    {
      ErrCnt[Failure] = ErrCnt[Failure] + 1;
      ErrCnt[Failure] = ErrCnt[Failure] + 1;
      printf ("Comparison alleges that -0.0 is Non-zero!\n");
      printf ("Comparison alleges that -0.0 is Non-zero!\n");
      U2 = "0.001";
      U2 = "0.001";
      Radix = 1;
      Radix = 1;
      TstPtUf ();
      TstPtUf ();
    }
    }
 
 
  TstCond (Failure, (Three == Two + One), "3 != 2+1");
  TstCond (Failure, (Three == Two + One), "3 != 2+1");
  TstCond (Failure, (Four == Three + One), "4 != 3+1");
  TstCond (Failure, (Four == Three + One), "4 != 3+1");
  TstCond (Failure, (Four + Two * (-Two) == Zero), "4 + 2*(-2) != 0");
  TstCond (Failure, (Four + Two * (-Two) == Zero), "4 + 2*(-2) != 0");
  TstCond (Failure, (Four - Three - One == Zero), "4-3-1 != 0");
  TstCond (Failure, (Four - Three - One == Zero), "4-3-1 != 0");
 
 
  TstCond (Failure, (MinusOne == (Zero - One)), "-1 != 0-1");
  TstCond (Failure, (MinusOne == (Zero - One)), "-1 != 0-1");
  TstCond (Failure, (MinusOne + One == Zero), "-1+1 != 0");
  TstCond (Failure, (MinusOne + One == Zero), "-1+1 != 0");
  TstCond (Failure, (One + MinusOne == Zero), "1+(-1) != 0");
  TstCond (Failure, (One + MinusOne == Zero), "1+(-1) != 0");
  TstCond (Failure, (MinusOne + FABS (One) == Zero), "-1+abs(1) != 0");
  TstCond (Failure, (MinusOne + FABS (One) == Zero), "-1+abs(1) != 0");
  TstCond (Failure, (MinusOne + MinusOne * MinusOne == Zero),
  TstCond (Failure, (MinusOne + MinusOne * MinusOne == Zero),
           "-1+(-1)*(-1) != 0");
           "-1+(-1)*(-1) != 0");
 
 
  TstCond (Failure, Half + MinusOne + Half == Zero, "1/2 + (-1) + 1/2 != 0");
  TstCond (Failure, Half + MinusOne + Half == Zero, "1/2 + (-1) + 1/2 != 0");
 
 
        /*=============================================*/
        /*=============================================*/
  Milestone = 10;
  Milestone = 10;
        /*=============================================*/
        /*=============================================*/
 
 
  TstCond (Failure, (Nine == Three * Three), "9 != 3*3");
  TstCond (Failure, (Nine == Three * Three), "9 != 3*3");
  TstCond (Failure, (TwentySeven == Nine * Three), "27 != 9*3");
  TstCond (Failure, (TwentySeven == Nine * Three), "27 != 9*3");
  TstCond (Failure, (Eight == Four + Four), "8 != 4+4");
  TstCond (Failure, (Eight == Four + Four), "8 != 4+4");
  TstCond (Failure, (ThirtyTwo == Eight * Four), "32 != 8*4");
  TstCond (Failure, (ThirtyTwo == Eight * Four), "32 != 8*4");
  TstCond (Failure, (ThirtyTwo - TwentySeven - Four - One == Zero),
  TstCond (Failure, (ThirtyTwo - TwentySeven - Four - One == Zero),
           "32-27-4-1 != 0");
           "32-27-4-1 != 0");
 
 
  TstCond (Failure, Five == Four + One, "5 != 4+1");
  TstCond (Failure, Five == Four + One, "5 != 4+1");
  TstCond (Failure, TwoForty == Four * Five * Three * Four, "240 != 4*5*3*4");
  TstCond (Failure, TwoForty == Four * Five * Three * Four, "240 != 4*5*3*4");
  TstCond (Failure, TwoForty / Three - Four * Four * Five == Zero,
  TstCond (Failure, TwoForty / Three - Four * Four * Five == Zero,
           "240/3 - 4*4*5 != 0");
           "240/3 - 4*4*5 != 0");
  TstCond (Failure, TwoForty / Four - Five * Three * Four == Zero,
  TstCond (Failure, TwoForty / Four - Five * Three * Four == Zero,
           "240/4 - 5*3*4 != 0");
           "240/4 - 5*3*4 != 0");
  TstCond (Failure, TwoForty / Five - Four * Three * Four == Zero,
  TstCond (Failure, TwoForty / Five - Four * Three * Four == Zero,
           "240/5 - 4*3*4 != 0");
           "240/5 - 4*3*4 != 0");
 
 
  if (ErrCnt[Failure] == 0)
  if (ErrCnt[Failure] == 0)
    {
    {
      printf ("-1, 0, 1/2, 1, 2, 3, 4, 5, 9, 27, 32 & 240 are O.K.\n");
      printf ("-1, 0, 1/2, 1, 2, 3, 4, 5, 9, 27, 32 & 240 are O.K.\n");
      printf ("\n");
      printf ("\n");
    }
    }
  printf ("Searching for Radix and Precision.\n");
  printf ("Searching for Radix and Precision.\n");
  W = One;
  W = One;
  do
  do
    {
    {
      W = W + W;
      W = W + W;
      Y = W + One;
      Y = W + One;
      Z = Y - W;
      Z = Y - W;
      Y = Z - One;
      Y = Z - One;
    }
    }
  while (MinusOne + FABS (Y) < Zero);
  while (MinusOne + FABS (Y) < Zero);
  /*.. now W is just big enough that |((W+1)-W)-1| >= 1 ... */
  /*.. now W is just big enough that |((W+1)-W)-1| >= 1 ... */
  Precision = Zero;
  Precision = Zero;
  Y = One;
  Y = One;
  do
  do
    {
    {
      Radix = W + Y;
      Radix = W + Y;
      Y = Y + Y;
      Y = Y + Y;
      Radix = Radix - W;
      Radix = Radix - W;
    }
    }
  while (Radix == Zero);
  while (Radix == Zero);
  if (Radix < Two)
  if (Radix < Two)
    Radix = One;
    Radix = One;
  printf ("Radix = %s .\n", Radix.str());
  printf ("Radix = %s .\n", Radix.str());
  if (Radix != One)
  if (Radix != One)
    {
    {
      W = One;
      W = One;
      do
      do
        {
        {
          Precision = Precision + One;
          Precision = Precision + One;
          W = W * Radix;
          W = W * Radix;
          Y = W + One;
          Y = W + One;
        }
        }
      while ((Y - W) == One);
      while ((Y - W) == One);
    }
    }
  /*... now W == Radix^Precision is barely too big to satisfy (W+1)-W == 1
  /*... now W == Radix^Precision is barely too big to satisfy (W+1)-W == 1
     ... */
     ... */
  U1 = One / W;
  U1 = One / W;
  U2 = Radix * U1;
  U2 = Radix * U1;
  printf ("Closest relative separation found is U1 = %s .\n\n", U1.str());
  printf ("Closest relative separation found is U1 = %s .\n\n", U1.str());
  printf ("Recalculating radix and precision\n ");
  printf ("Recalculating radix and precision\n ");
 
 
  /*save old values */
  /*save old values */
  E0 = Radix;
  E0 = Radix;
  E1 = U1;
  E1 = U1;
  E9 = U2;
  E9 = U2;
  E3 = Precision;
  E3 = Precision;
 
 
  X = Four / Three;
  X = Four / Three;
  Third = X - One;
  Third = X - One;
  F6 = Half - Third;
  F6 = Half - Third;
  X = F6 + F6;
  X = F6 + F6;
  X = FABS (X - Third);
  X = FABS (X - Third);
  if (X < U2)
  if (X < U2)
    X = U2;
    X = U2;
 
 
  /*... now X = (unknown no.) ulps of 1+... */
  /*... now X = (unknown no.) ulps of 1+... */
  do
  do
    {
    {
      U2 = X;
      U2 = X;
      Y = Half * U2 + ThirtyTwo * U2 * U2;
      Y = Half * U2 + ThirtyTwo * U2 * U2;
      Y = One + Y;
      Y = One + Y;
      X = Y - One;
      X = Y - One;
    }
    }
  while (!((U2 <= X) || (X <= Zero)));
  while (!((U2 <= X) || (X <= Zero)));
 
 
  /*... now U2 == 1 ulp of 1 + ... */
  /*... now U2 == 1 ulp of 1 + ... */
  X = Two / Three;
  X = Two / Three;
  F6 = X - Half;
  F6 = X - Half;
  Third = F6 + F6;
  Third = F6 + F6;
  X = Third - Half;
  X = Third - Half;
  X = FABS (X + F6);
  X = FABS (X + F6);
  if (X < U1)
  if (X < U1)
    X = U1;
    X = U1;
 
 
  /*... now  X == (unknown no.) ulps of 1 -... */
  /*... now  X == (unknown no.) ulps of 1 -... */
  do
  do
    {
    {
      U1 = X;
      U1 = X;
      Y = Half * U1 + ThirtyTwo * U1 * U1;
      Y = Half * U1 + ThirtyTwo * U1 * U1;
      Y = Half - Y;
      Y = Half - Y;
      X = Half + Y;
      X = Half + Y;
      Y = Half - X;
      Y = Half - X;
      X = Half + Y;
      X = Half + Y;
    }
    }
  while (!((U1 <= X) || (X <= Zero)));
  while (!((U1 <= X) || (X <= Zero)));
  /*... now U1 == 1 ulp of 1 - ... */
  /*... now U1 == 1 ulp of 1 - ... */
  if (U1 == E1)
  if (U1 == E1)
    printf ("confirms closest relative separation U1 .\n");
    printf ("confirms closest relative separation U1 .\n");
  else
  else
    printf ("gets better closest relative separation U1 = %s .\n", U1.str());
    printf ("gets better closest relative separation U1 = %s .\n", U1.str());
  W = One / U1;
  W = One / U1;
  F9 = (Half - U1) + Half;
  F9 = (Half - U1) + Half;
 
 
  Radix = FLOOR (FLOAT ("0.01") + U2 / U1);
  Radix = FLOOR (FLOAT ("0.01") + U2 / U1);
  if (Radix == E0)
  if (Radix == E0)
    printf ("Radix confirmed.\n");
    printf ("Radix confirmed.\n");
  else
  else
    printf ("MYSTERY: recalculated Radix = %s .\n", Radix.str());
    printf ("MYSTERY: recalculated Radix = %s .\n", Radix.str());
  TstCond (Defect, Radix <= Eight + Eight,
  TstCond (Defect, Radix <= Eight + Eight,
           "Radix is too big: roundoff problems");
           "Radix is too big: roundoff problems");
  TstCond (Flaw, (Radix == Two) || (Radix == 10)
  TstCond (Flaw, (Radix == Two) || (Radix == 10)
           || (Radix == One), "Radix is not as good as 2 or 10");
           || (Radix == One), "Radix is not as good as 2 or 10");
        /*=============================================*/
        /*=============================================*/
  Milestone = 20;
  Milestone = 20;
        /*=============================================*/
        /*=============================================*/
  TstCond (Failure, F9 - Half < Half,
  TstCond (Failure, F9 - Half < Half,
           "(1-U1)-1/2 < 1/2 is FALSE, prog. fails?");
           "(1-U1)-1/2 < 1/2 is FALSE, prog. fails?");
  X = F9;
  X = F9;
  I = 1;
  I = 1;
  Y = X - Half;
  Y = X - Half;
  Z = Y - Half;
  Z = Y - Half;
  TstCond (Failure, (X != One)
  TstCond (Failure, (X != One)
           || (Z == Zero), "Comparison is fuzzy,X=1 but X-1/2-1/2 != 0");
           || (Z == Zero), "Comparison is fuzzy,X=1 but X-1/2-1/2 != 0");
  X = One + U2;
  X = One + U2;
  I = 0;
  I = 0;
        /*=============================================*/
        /*=============================================*/
  Milestone = 25;
  Milestone = 25;
        /*=============================================*/
        /*=============================================*/
  /*... BMinusU2 = nextafter(Radix, 0) */
  /*... BMinusU2 = nextafter(Radix, 0) */
  BMinusU2 = Radix - One;
  BMinusU2 = Radix - One;
  BMinusU2 = (BMinusU2 - U2) + One;
  BMinusU2 = (BMinusU2 - U2) + One;
  /* Purify Integers */
  /* Purify Integers */
  if (Radix != One)
  if (Radix != One)
    {
    {
      X = -TwoForty * LOG (U1) / LOG (Radix);
      X = -TwoForty * LOG (U1) / LOG (Radix);
      Y = FLOOR (Half + X);
      Y = FLOOR (Half + X);
      if (FABS (X - Y) * Four < One)
      if (FABS (X - Y) * Four < One)
        X = Y;
        X = Y;
      Precision = X / TwoForty;
      Precision = X / TwoForty;
      Y = FLOOR (Half + Precision);
      Y = FLOOR (Half + Precision);
      if (FABS (Precision - Y) * TwoForty < Half)
      if (FABS (Precision - Y) * TwoForty < Half)
        Precision = Y;
        Precision = Y;
    }
    }
  if ((Precision != FLOOR (Precision)) || (Radix == One))
  if ((Precision != FLOOR (Precision)) || (Radix == One))
    {
    {
      printf ("Precision cannot be characterized by an Integer number\n");
      printf ("Precision cannot be characterized by an Integer number\n");
      printf
      printf
        ("of significant digits but, by itself, this is a minor flaw.\n");
        ("of significant digits but, by itself, this is a minor flaw.\n");
    }
    }
  if (Radix == One)
  if (Radix == One)
    printf
    printf
      ("logarithmic encoding has precision characterized solely by U1.\n");
      ("logarithmic encoding has precision characterized solely by U1.\n");
  else
  else
    printf ("The number of significant digits of the Radix is %s .\n",
    printf ("The number of significant digits of the Radix is %s .\n",
            Precision.str());
            Precision.str());
  TstCond (Serious, U2 * Nine * Nine * TwoForty < One,
  TstCond (Serious, U2 * Nine * Nine * TwoForty < One,
           "Precision worse than 5 decimal figures  ");
           "Precision worse than 5 decimal figures  ");
        /*=============================================*/
        /*=============================================*/
  Milestone = 30;
  Milestone = 30;
        /*=============================================*/
        /*=============================================*/
  /* Test for extra-precise subexpressions */
  /* Test for extra-precise subexpressions */
  X = FABS (((Four / Three - One) - One / Four) * Three - One / Four);
  X = FABS (((Four / Three - One) - One / Four) * Three - One / Four);
  do
  do
    {
    {
      Z2 = X;
      Z2 = X;
      X = (One + (Half * Z2 + ThirtyTwo * Z2 * Z2)) - One;
      X = (One + (Half * Z2 + ThirtyTwo * Z2 * Z2)) - One;
    }
    }
  while (!((Z2 <= X) || (X <= Zero)));
  while (!((Z2 <= X) || (X <= Zero)));
  X = Y = Z = FABS ((Three / Four - Two / Three) * Three - One / Four);
  X = Y = Z = FABS ((Three / Four - Two / Three) * Three - One / Four);
  do
  do
    {
    {
      Z1 = Z;
      Z1 = Z;
      Z = (One / Two - ((One / Two - (Half * Z1 + ThirtyTwo * Z1 * Z1))
      Z = (One / Two - ((One / Two - (Half * Z1 + ThirtyTwo * Z1 * Z1))
                        + One / Two)) + One / Two;
                        + One / Two)) + One / Two;
    }
    }
  while (!((Z1 <= Z) || (Z <= Zero)));
  while (!((Z1 <= Z) || (Z <= Zero)));
  do
  do
    {
    {
      do
      do
        {
        {
          Y1 = Y;
          Y1 = Y;
          Y =
          Y =
            (Half - ((Half - (Half * Y1 + ThirtyTwo * Y1 * Y1)) + Half)) +
            (Half - ((Half - (Half * Y1 + ThirtyTwo * Y1 * Y1)) + Half)) +
            Half;
            Half;
        }
        }
      while (!((Y1 <= Y) || (Y <= Zero)));
      while (!((Y1 <= Y) || (Y <= Zero)));
      X1 = X;
      X1 = X;
      X = ((Half * X1 + ThirtyTwo * X1 * X1) - F9) + F9;
      X = ((Half * X1 + ThirtyTwo * X1 * X1) - F9) + F9;
    }
    }
  while (!((X1 <= X) || (X <= Zero)));
  while (!((X1 <= X) || (X <= Zero)));
  if ((X1 != Y1) || (X1 != Z1))
  if ((X1 != Y1) || (X1 != Z1))
    {
    {
      BadCond (Serious, "Disagreements among the values X1, Y1, Z1,\n");
      BadCond (Serious, "Disagreements among the values X1, Y1, Z1,\n");
      printf ("respectively  %s,  %s,  %s,\n", X1.str(), Y1.str(), Z1.str());
      printf ("respectively  %s,  %s,  %s,\n", X1.str(), Y1.str(), Z1.str());
      printf ("are symptoms of inconsistencies introduced\n");
      printf ("are symptoms of inconsistencies introduced\n");
      printf ("by extra-precise evaluation of arithmetic subexpressions.\n");
      printf ("by extra-precise evaluation of arithmetic subexpressions.\n");
      notify ("Possibly some part of this");
      notify ("Possibly some part of this");
      if ((X1 == U1) || (Y1 == U1) || (Z1 == U1))
      if ((X1 == U1) || (Y1 == U1) || (Z1 == U1))
        printf ("That feature is not tested further by this program.\n");
        printf ("That feature is not tested further by this program.\n");
    }
    }
  else
  else
    {
    {
      if ((Z1 != U1) || (Z2 != U2))
      if ((Z1 != U1) || (Z2 != U2))
        {
        {
          if ((Z1 >= U1) || (Z2 >= U2))
          if ((Z1 >= U1) || (Z2 >= U2))
            {
            {
              BadCond (Failure, "");
              BadCond (Failure, "");
              notify ("Precision");
              notify ("Precision");
              printf ("\tU1 = %s, Z1 - U1 = %s\n", U1.str(), (Z1 - U1).str());
              printf ("\tU1 = %s, Z1 - U1 = %s\n", U1.str(), (Z1 - U1).str());
              printf ("\tU2 = %s, Z2 - U2 = %s\n", U2.str(), (Z2 - U2).str());
              printf ("\tU2 = %s, Z2 - U2 = %s\n", U2.str(), (Z2 - U2).str());
            }
            }
          else
          else
            {
            {
              if ((Z1 <= Zero) || (Z2 <= Zero))
              if ((Z1 <= Zero) || (Z2 <= Zero))
                {
                {
                  printf ("Because of unusual Radix = %s", Radix.str());
                  printf ("Because of unusual Radix = %s", Radix.str());
                  printf (", or exact rational arithmetic a result\n");
                  printf (", or exact rational arithmetic a result\n");
                  printf ("Z1 = %s, or Z2 = %s ", Z1.str(), Z2.str());
                  printf ("Z1 = %s, or Z2 = %s ", Z1.str(), Z2.str());
                  notify ("of an\nextra-precision");
                  notify ("of an\nextra-precision");
                }
                }
              if (Z1 != Z2 || Z1 > Zero)
              if (Z1 != Z2 || Z1 > Zero)
                {
                {
                  X = Z1 / U1;
                  X = Z1 / U1;
                  Y = Z2 / U2;
                  Y = Z2 / U2;
                  if (Y > X)
                  if (Y > X)
                    X = Y;
                    X = Y;
                  Q = -LOG (X);
                  Q = -LOG (X);
                  printf ("Some subexpressions appear to be calculated "
                  printf ("Some subexpressions appear to be calculated "
                          "extra precisely\n");
                          "extra precisely\n");
                  printf ("with about %s extra B-digits, i.e.\n",
                  printf ("with about %s extra B-digits, i.e.\n",
                          (Q / LOG (Radix)).str());
                          (Q / LOG (Radix)).str());
                  printf ("roughly %s extra significant decimals.\n",
                  printf ("roughly %s extra significant decimals.\n",
                          (Q / LOG (FLOAT (10))).str());
                          (Q / LOG (FLOAT (10))).str());
                }
                }
              printf
              printf
                ("That feature is not tested further by this program.\n");
                ("That feature is not tested further by this program.\n");
            }
            }
        }
        }
    }
    }
  Pause ();
  Pause ();
        /*=============================================*/
        /*=============================================*/
  Milestone = 35;
  Milestone = 35;
        /*=============================================*/
        /*=============================================*/
  if (Radix >= Two)
  if (Radix >= Two)
    {
    {
      X = W / (Radix * Radix);
      X = W / (Radix * Radix);
      Y = X + One;
      Y = X + One;
      Z = Y - X;
      Z = Y - X;
      T = Z + U2;
      T = Z + U2;
      X = T - Z;
      X = T - Z;
      TstCond (Failure, X == U2,
      TstCond (Failure, X == U2,
               "Subtraction is not normalized X=Y,X+Z != Y+Z!");
               "Subtraction is not normalized X=Y,X+Z != Y+Z!");
      if (X == U2)
      if (X == U2)
        printf ("Subtraction appears to be normalized, as it should be.");
        printf ("Subtraction appears to be normalized, as it should be.");
    }
    }
  printf ("\nChecking for guard digit in *, /, and -.\n");
  printf ("\nChecking for guard digit in *, /, and -.\n");
  Y = F9 * One;
  Y = F9 * One;
  Z = One * F9;
  Z = One * F9;
  X = F9 - Half;
  X = F9 - Half;
  Y = (Y - Half) - X;
  Y = (Y - Half) - X;
  Z = (Z - Half) - X;
  Z = (Z - Half) - X;
  X = One + U2;
  X = One + U2;
  T = X * Radix;
  T = X * Radix;
  R = Radix * X;
  R = Radix * X;
  X = T - Radix;
  X = T - Radix;
  X = X - Radix * U2;
  X = X - Radix * U2;
  T = R - Radix;
  T = R - Radix;
  T = T - Radix * U2;
  T = T - Radix * U2;
  X = X * (Radix - One);
  X = X * (Radix - One);
  T = T * (Radix - One);
  T = T * (Radix - One);
  if ((X == Zero) && (Y == Zero) && (Z == Zero) && (T == Zero))
  if ((X == Zero) && (Y == Zero) && (Z == Zero) && (T == Zero))
    GMult = Yes;
    GMult = Yes;
  else
  else
    {
    {
      GMult = No;
      GMult = No;
      TstCond (Serious, false, "* lacks a Guard Digit, so 1*X != X");
      TstCond (Serious, false, "* lacks a Guard Digit, so 1*X != X");
    }
    }
  Z = Radix * U2;
  Z = Radix * U2;
  X = One + Z;
  X = One + Z;
  Y = FABS ((X + Z) - X * X) - U2;
  Y = FABS ((X + Z) - X * X) - U2;
  X = One - U2;
  X = One - U2;
  Z = FABS ((X - U2) - X * X) - U1;
  Z = FABS ((X - U2) - X * X) - U1;
  TstCond (Failure, (Y <= Zero)
  TstCond (Failure, (Y <= Zero)
           && (Z <= Zero), "* gets too many final digits wrong.\n");
           && (Z <= Zero), "* gets too many final digits wrong.\n");
  Y = One - U2;
  Y = One - U2;
  X = One + U2;
  X = One + U2;
  Z = One / Y;
  Z = One / Y;
  Y = Z - X;
  Y = Z - X;
  X = One / Three;
  X = One / Three;
  Z = Three / Nine;
  Z = Three / Nine;
  X = X - Z;
  X = X - Z;
  T = Nine / TwentySeven;
  T = Nine / TwentySeven;
  Z = Z - T;
  Z = Z - T;
  TstCond (Defect, X == Zero && Y == Zero && Z == Zero,
  TstCond (Defect, X == Zero && Y == Zero && Z == Zero,
           "Division lacks a Guard Digit, so error can exceed 1 ulp\n"
           "Division lacks a Guard Digit, so error can exceed 1 ulp\n"
           "or  1/3  and  3/9  and  9/27 may disagree");
           "or  1/3  and  3/9  and  9/27 may disagree");
  Y = F9 / One;
  Y = F9 / One;
  X = F9 - Half;
  X = F9 - Half;
  Y = (Y - Half) - X;
  Y = (Y - Half) - X;
  X = One + U2;
  X = One + U2;
  T = X / One;
  T = X / One;
  X = T - X;
  X = T - X;
  if ((X == Zero) && (Y == Zero) && (Z == Zero))
  if ((X == Zero) && (Y == Zero) && (Z == Zero))
    GDiv = Yes;
    GDiv = Yes;
  else
  else
    {
    {
      GDiv = No;
      GDiv = No;
      TstCond (Serious, false, "Division lacks a Guard Digit, so X/1 != X");
      TstCond (Serious, false, "Division lacks a Guard Digit, so X/1 != X");
    }
    }
  X = One / (One + U2);
  X = One / (One + U2);
  Y = X - Half - Half;
  Y = X - Half - Half;
  TstCond (Serious, Y < Zero, "Computed value of 1/1.000..1 >= 1");
  TstCond (Serious, Y < Zero, "Computed value of 1/1.000..1 >= 1");
  X = One - U2;
  X = One - U2;
  Y = One + Radix * U2;
  Y = One + Radix * U2;
  Z = X * Radix;
  Z = X * Radix;
  T = Y * Radix;
  T = Y * Radix;
  R = Z / Radix;
  R = Z / Radix;
  StickyBit = T / Radix;
  StickyBit = T / Radix;
  X = R - X;
  X = R - X;
  Y = StickyBit - Y;
  Y = StickyBit - Y;
  TstCond (Failure, X == Zero && Y == Zero,
  TstCond (Failure, X == Zero && Y == Zero,
           "* and/or / gets too many last digits wrong");
           "* and/or / gets too many last digits wrong");
  Y = One - U1;
  Y = One - U1;
  X = One - F9;
  X = One - F9;
  Y = One - Y;
  Y = One - Y;
  T = Radix - U2;
  T = Radix - U2;
  Z = Radix - BMinusU2;
  Z = Radix - BMinusU2;
  T = Radix - T;
  T = Radix - T;
  if ((X == U1) && (Y == U1) && (Z == U2) && (T == U2))
  if ((X == U1) && (Y == U1) && (Z == U2) && (T == U2))
    GAddSub = Yes;
    GAddSub = Yes;
  else
  else
    {
    {
      GAddSub = No;
      GAddSub = No;
      TstCond (Serious, false,
      TstCond (Serious, false,
               "- lacks Guard Digit, so cancellation is obscured");
               "- lacks Guard Digit, so cancellation is obscured");
    }
    }
  if (F9 != One && F9 - One >= Zero)
  if (F9 != One && F9 - One >= Zero)
    {
    {
      BadCond (Serious, "comparison alleges  (1-U1) < 1  although\n");
      BadCond (Serious, "comparison alleges  (1-U1) < 1  although\n");
      printf ("  subtraction yields  (1-U1) - 1 = 0 , thereby vitiating\n");
      printf ("  subtraction yields  (1-U1) - 1 = 0 , thereby vitiating\n");
      printf ("  such precautions against division by zero as\n");
      printf ("  such precautions against division by zero as\n");
      printf ("  ...  if (X == 1.0) {.....} else {.../(X-1.0)...}\n");
      printf ("  ...  if (X == 1.0) {.....} else {.../(X-1.0)...}\n");
    }
    }
  if (GMult == Yes && GDiv == Yes && GAddSub == Yes)
  if (GMult == Yes && GDiv == Yes && GAddSub == Yes)
    printf
    printf
      ("     *, /, and - appear to have guard digits, as they should.\n");
      ("     *, /, and - appear to have guard digits, as they should.\n");
        /*=============================================*/
        /*=============================================*/
  Milestone = 40;
  Milestone = 40;
        /*=============================================*/
        /*=============================================*/
  Pause ();
  Pause ();
  printf ("Checking rounding on multiply, divide and add/subtract.\n");
  printf ("Checking rounding on multiply, divide and add/subtract.\n");
  RMult = Other;
  RMult = Other;
  RDiv = Other;
  RDiv = Other;
  RAddSub = Other;
  RAddSub = Other;
  RadixD2 = Radix / Two;
  RadixD2 = Radix / Two;
  A1 = Two;
  A1 = Two;
  Done = false;
  Done = false;
  do
  do
    {
    {
      AInvrse = Radix;
      AInvrse = Radix;
      do
      do
        {
        {
          X = AInvrse;
          X = AInvrse;
          AInvrse = AInvrse / A1;
          AInvrse = AInvrse / A1;
        }
        }
      while (!(FLOOR (AInvrse) != AInvrse));
      while (!(FLOOR (AInvrse) != AInvrse));
      Done = (X == One) || (A1 > Three);
      Done = (X == One) || (A1 > Three);
      if (!Done)
      if (!Done)
        A1 = Nine + One;
        A1 = Nine + One;
    }
    }
  while (!(Done));
  while (!(Done));
  if (X == One)
  if (X == One)
    A1 = Radix;
    A1 = Radix;
  AInvrse = One / A1;
  AInvrse = One / A1;
  X = A1;
  X = A1;
  Y = AInvrse;
  Y = AInvrse;
  Done = false;
  Done = false;
  do
  do
    {
    {
      Z = X * Y - Half;
      Z = X * Y - Half;
      TstCond (Failure, Z == Half, "X * (1/X) differs from 1");
      TstCond (Failure, Z == Half, "X * (1/X) differs from 1");
      Done = X == Radix;
      Done = X == Radix;
      X = Radix;
      X = Radix;
      Y = One / X;
      Y = One / X;
    }
    }
  while (!(Done));
  while (!(Done));
  Y2 = One + U2;
  Y2 = One + U2;
  Y1 = One - U2;
  Y1 = One - U2;
  X = OneAndHalf - U2;
  X = OneAndHalf - U2;
  Y = OneAndHalf + U2;
  Y = OneAndHalf + U2;
  Z = (X - U2) * Y2;
  Z = (X - U2) * Y2;
  T = Y * Y1;
  T = Y * Y1;
  Z = Z - X;
  Z = Z - X;
  T = T - X;
  T = T - X;
  X = X * Y2;
  X = X * Y2;
  Y = (Y + U2) * Y1;
  Y = (Y + U2) * Y1;
  X = X - OneAndHalf;
  X = X - OneAndHalf;
  Y = Y - OneAndHalf;
  Y = Y - OneAndHalf;
  if ((X == Zero) && (Y == Zero) && (Z == Zero) && (T <= Zero))
  if ((X == Zero) && (Y == Zero) && (Z == Zero) && (T <= Zero))
    {
    {
      X = (OneAndHalf + U2) * Y2;
      X = (OneAndHalf + U2) * Y2;
      Y = OneAndHalf - U2 - U2;
      Y = OneAndHalf - U2 - U2;
      Z = OneAndHalf + U2 + U2;
      Z = OneAndHalf + U2 + U2;
      T = (OneAndHalf - U2) * Y1;
      T = (OneAndHalf - U2) * Y1;
      X = X - (Z + U2);
      X = X - (Z + U2);
      StickyBit = Y * Y1;
      StickyBit = Y * Y1;
      S = Z * Y2;
      S = Z * Y2;
      T = T - Y;
      T = T - Y;
      Y = (U2 - Y) + StickyBit;
      Y = (U2 - Y) + StickyBit;
      Z = S - (Z + U2 + U2);
      Z = S - (Z + U2 + U2);
      StickyBit = (Y2 + U2) * Y1;
      StickyBit = (Y2 + U2) * Y1;
      Y1 = Y2 * Y1;
      Y1 = Y2 * Y1;
      StickyBit = StickyBit - Y2;
      StickyBit = StickyBit - Y2;
      Y1 = Y1 - Half;
      Y1 = Y1 - Half;
      if ((X == Zero) && (Y == Zero) && (Z == Zero) && (T == Zero)
      if ((X == Zero) && (Y == Zero) && (Z == Zero) && (T == Zero)
          && (StickyBit == Zero) && (Y1 == Half))
          && (StickyBit == Zero) && (Y1 == Half))
        {
        {
          RMult = Rounded;
          RMult = Rounded;
          printf ("Multiplication appears to round correctly.\n");
          printf ("Multiplication appears to round correctly.\n");
        }
        }
      else if ((X + U2 == Zero) && (Y < Zero) && (Z + U2 == Zero)
      else if ((X + U2 == Zero) && (Y < Zero) && (Z + U2 == Zero)
               && (T < Zero) && (StickyBit + U2 == Zero) && (Y1 < Half))
               && (T < Zero) && (StickyBit + U2 == Zero) && (Y1 < Half))
        {
        {
          RMult = Chopped;
          RMult = Chopped;
          printf ("Multiplication appears to chop.\n");
          printf ("Multiplication appears to chop.\n");
        }
        }
      else
      else
        printf ("* is neither chopped nor correctly rounded.\n");
        printf ("* is neither chopped nor correctly rounded.\n");
      if ((RMult == Rounded) && (GMult == No))
      if ((RMult == Rounded) && (GMult == No))
        notify ("Multiplication");
        notify ("Multiplication");
    }
    }
  else
  else
    printf ("* is neither chopped nor correctly rounded.\n");
    printf ("* is neither chopped nor correctly rounded.\n");
        /*=============================================*/
        /*=============================================*/
  Milestone = 45;
  Milestone = 45;
        /*=============================================*/
        /*=============================================*/
  Y2 = One + U2;
  Y2 = One + U2;
  Y1 = One - U2;
  Y1 = One - U2;
  Z = OneAndHalf + U2 + U2;
  Z = OneAndHalf + U2 + U2;
  X = Z / Y2;
  X = Z / Y2;
  T = OneAndHalf - U2 - U2;
  T = OneAndHalf - U2 - U2;
  Y = (T - U2) / Y1;
  Y = (T - U2) / Y1;
  Z = (Z + U2) / Y2;
  Z = (Z + U2) / Y2;
  X = X - OneAndHalf;
  X = X - OneAndHalf;
  Y = Y - T;
  Y = Y - T;
  T = T / Y1;
  T = T / Y1;
  Z = Z - (OneAndHalf + U2);
  Z = Z - (OneAndHalf + U2);
  T = (U2 - OneAndHalf) + T;
  T = (U2 - OneAndHalf) + T;
  if (!((X > Zero) || (Y > Zero) || (Z > Zero) || (T > Zero)))
  if (!((X > Zero) || (Y > Zero) || (Z > Zero) || (T > Zero)))
    {
    {
      X = OneAndHalf / Y2;
      X = OneAndHalf / Y2;
      Y = OneAndHalf - U2;
      Y = OneAndHalf - U2;
      Z = OneAndHalf + U2;
      Z = OneAndHalf + U2;
      X = X - Y;
      X = X - Y;
      T = OneAndHalf / Y1;
      T = OneAndHalf / Y1;
      Y = Y / Y1;
      Y = Y / Y1;
      T = T - (Z + U2);
      T = T - (Z + U2);
      Y = Y - Z;
      Y = Y - Z;
      Z = Z / Y2;
      Z = Z / Y2;
      Y1 = (Y2 + U2) / Y2;
      Y1 = (Y2 + U2) / Y2;
      Z = Z - OneAndHalf;
      Z = Z - OneAndHalf;
      Y2 = Y1 - Y2;
      Y2 = Y1 - Y2;
      Y1 = (F9 - U1) / F9;
      Y1 = (F9 - U1) / F9;
      if ((X == Zero) && (Y == Zero) && (Z == Zero) && (T == Zero)
      if ((X == Zero) && (Y == Zero) && (Z == Zero) && (T == Zero)
          && (Y2 == Zero) && (Y2 == Zero) && (Y1 - Half == F9 - Half))
          && (Y2 == Zero) && (Y2 == Zero) && (Y1 - Half == F9 - Half))
        {
        {
          RDiv = Rounded;
          RDiv = Rounded;
          printf ("Division appears to round correctly.\n");
          printf ("Division appears to round correctly.\n");
          if (GDiv == No)
          if (GDiv == No)
            notify ("Division");
            notify ("Division");
        }
        }
      else if ((X < Zero) && (Y < Zero) && (Z < Zero) && (T < Zero)
      else if ((X < Zero) && (Y < Zero) && (Z < Zero) && (T < Zero)
               && (Y2 < Zero) && (Y1 - Half < F9 - Half))
               && (Y2 < Zero) && (Y1 - Half < F9 - Half))
        {
        {
          RDiv = Chopped;
          RDiv = Chopped;
          printf ("Division appears to chop.\n");
          printf ("Division appears to chop.\n");
        }
        }
    }
    }
  if (RDiv == Other)
  if (RDiv == Other)
    printf ("/ is neither chopped nor correctly rounded.\n");
    printf ("/ is neither chopped nor correctly rounded.\n");
  BInvrse = One / Radix;
  BInvrse = One / Radix;
  TstCond (Failure, (BInvrse * Radix - Half == Half),
  TstCond (Failure, (BInvrse * Radix - Half == Half),
           "Radix * ( 1 / Radix ) differs from 1");
           "Radix * ( 1 / Radix ) differs from 1");
        /*=============================================*/
        /*=============================================*/
  Milestone = 50;
  Milestone = 50;
        /*=============================================*/
        /*=============================================*/
  TstCond (Failure, ((F9 + U1) - Half == Half)
  TstCond (Failure, ((F9 + U1) - Half == Half)
           && ((BMinusU2 + U2) - One == Radix - One),
           && ((BMinusU2 + U2) - One == Radix - One),
           "Incomplete carry-propagation in Addition");
           "Incomplete carry-propagation in Addition");
  X = One - U1 * U1;
  X = One - U1 * U1;
  Y = One + U2 * (One - U2);
  Y = One + U2 * (One - U2);
  Z = F9 - Half;
  Z = F9 - Half;
  X = (X - Half) - Z;
  X = (X - Half) - Z;
  Y = Y - One;
  Y = Y - One;
  if ((X == Zero) && (Y == Zero))
  if ((X == Zero) && (Y == Zero))
    {
    {
      RAddSub = Chopped;
      RAddSub = Chopped;
      printf ("Add/Subtract appears to be chopped.\n");
      printf ("Add/Subtract appears to be chopped.\n");
    }
    }
  if (GAddSub == Yes)
  if (GAddSub == Yes)
    {
    {
      X = (Half + U2) * U2;
      X = (Half + U2) * U2;
      Y = (Half - U2) * U2;
      Y = (Half - U2) * U2;
      X = One + X;
      X = One + X;
      Y = One + Y;
      Y = One + Y;
      X = (One + U2) - X;
      X = (One + U2) - X;
      Y = One - Y;
      Y = One - Y;
      if ((X == Zero) && (Y == Zero))
      if ((X == Zero) && (Y == Zero))
        {
        {
          X = (Half + U2) * U1;
          X = (Half + U2) * U1;
          Y = (Half - U2) * U1;
          Y = (Half - U2) * U1;
          X = One - X;
          X = One - X;
          Y = One - Y;
          Y = One - Y;
          X = F9 - X;
          X = F9 - X;
          Y = One - Y;
          Y = One - Y;
          if ((X == Zero) && (Y == Zero))
          if ((X == Zero) && (Y == Zero))
            {
            {
              RAddSub = Rounded;
              RAddSub = Rounded;
              printf ("Addition/Subtraction appears to round correctly.\n");
              printf ("Addition/Subtraction appears to round correctly.\n");
              if (GAddSub == No)
              if (GAddSub == No)
                notify ("Add/Subtract");
                notify ("Add/Subtract");
            }
            }
          else
          else
            printf ("Addition/Subtraction neither rounds nor chops.\n");
            printf ("Addition/Subtraction neither rounds nor chops.\n");
        }
        }
      else
      else
        printf ("Addition/Subtraction neither rounds nor chops.\n");
        printf ("Addition/Subtraction neither rounds nor chops.\n");
    }
    }
  else
  else
    printf ("Addition/Subtraction neither rounds nor chops.\n");
    printf ("Addition/Subtraction neither rounds nor chops.\n");
  S = One;
  S = One;
  X = One + Half * (One + Half);
  X = One + Half * (One + Half);
  Y = (One + U2) * Half;
  Y = (One + U2) * Half;
  Z = X - Y;
  Z = X - Y;
  T = Y - X;
  T = Y - X;
  StickyBit = Z + T;
  StickyBit = Z + T;
  if (StickyBit != Zero)
  if (StickyBit != Zero)
    {
    {
      S = Zero;
      S = Zero;
      BadCond (Flaw, "(X - Y) + (Y - X) is non zero!\n");
      BadCond (Flaw, "(X - Y) + (Y - X) is non zero!\n");
    }
    }
  StickyBit = Zero;
  StickyBit = Zero;
  if ((GMult == Yes) && (GDiv == Yes) && (GAddSub == Yes)
  if ((GMult == Yes) && (GDiv == Yes) && (GAddSub == Yes)
      && (RMult == Rounded) && (RDiv == Rounded)
      && (RMult == Rounded) && (RDiv == Rounded)
      && (RAddSub == Rounded) && (FLOOR (RadixD2) == RadixD2))
      && (RAddSub == Rounded) && (FLOOR (RadixD2) == RadixD2))
    {
    {
      printf ("Checking for sticky bit.\n");
      printf ("Checking for sticky bit.\n");
      X = (Half + U1) * U2;
      X = (Half + U1) * U2;
      Y = Half * U2;
      Y = Half * U2;
      Z = One + Y;
      Z = One + Y;
      T = One + X;
      T = One + X;
      if ((Z - One <= Zero) && (T - One >= U2))
      if ((Z - One <= Zero) && (T - One >= U2))
        {
        {
          Z = T + Y;
          Z = T + Y;
          Y = Z - X;
          Y = Z - X;
          if ((Z - T >= U2) && (Y - T == Zero))
          if ((Z - T >= U2) && (Y - T == Zero))
            {
            {
              X = (Half + U1) * U1;
              X = (Half + U1) * U1;
              Y = Half * U1;
              Y = Half * U1;
              Z = One - Y;
              Z = One - Y;
              T = One - X;
              T = One - X;
              if ((Z - One == Zero) && (T - F9 == Zero))
              if ((Z - One == Zero) && (T - F9 == Zero))
                {
                {
                  Z = (Half - U1) * U1;
                  Z = (Half - U1) * U1;
                  T = F9 - Z;
                  T = F9 - Z;
                  Q = F9 - Y;
                  Q = F9 - Y;
                  if ((T - F9 == Zero) && (F9 - U1 - Q == Zero))
                  if ((T - F9 == Zero) && (F9 - U1 - Q == Zero))
                    {
                    {
                      Z = (One + U2) * OneAndHalf;
                      Z = (One + U2) * OneAndHalf;
                      T = (OneAndHalf + U2) - Z + U2;
                      T = (OneAndHalf + U2) - Z + U2;
                      X = One + Half / Radix;
                      X = One + Half / Radix;
                      Y = One + Radix * U2;
                      Y = One + Radix * U2;
                      Z = X * Y;
                      Z = X * Y;
                      if (T == Zero && X + Radix * U2 - Z == Zero)
                      if (T == Zero && X + Radix * U2 - Z == Zero)
                        {
                        {
                          if (Radix != Two)
                          if (Radix != Two)
                            {
                            {
                              X = Two + U2;
                              X = Two + U2;
                              Y = X / Two;
                              Y = X / Two;
                              if ((Y - One == Zero))
                              if ((Y - One == Zero))
                                StickyBit = S;
                                StickyBit = S;
                            }
                            }
                          else
                          else
                            StickyBit = S;
                            StickyBit = S;
                        }
                        }
                    }
                    }
                }
                }
            }
            }
        }
        }
    }
    }
  if (StickyBit == One)
  if (StickyBit == One)
    printf ("Sticky bit apparently used correctly.\n");
    printf ("Sticky bit apparently used correctly.\n");
  else
  else
    printf ("Sticky bit used incorrectly or not at all.\n");
    printf ("Sticky bit used incorrectly or not at all.\n");
  TstCond (Flaw, !(GMult == No || GDiv == No || GAddSub == No ||
  TstCond (Flaw, !(GMult == No || GDiv == No || GAddSub == No ||
                   RMult == Other || RDiv == Other || RAddSub == Other),
                   RMult == Other || RDiv == Other || RAddSub == Other),
           "lack(s) of guard digits or failure(s) to correctly round or chop\n\
           "lack(s) of guard digits or failure(s) to correctly round or chop\n\
(noted above) count as one flaw in the final tally below");
(noted above) count as one flaw in the final tally below");
        /*=============================================*/
        /*=============================================*/
  Milestone = 60;
  Milestone = 60;
        /*=============================================*/
        /*=============================================*/
  printf ("\n");
  printf ("\n");
  printf ("Does Multiplication commute?  ");
  printf ("Does Multiplication commute?  ");
  printf ("Testing on %d random pairs.\n", NoTrials);
  printf ("Testing on %d random pairs.\n", NoTrials);
  Random9 = SQRT (FLOAT (3));
  Random9 = SQRT (FLOAT (3));
  Random1 = Third;
  Random1 = Third;
  I = 1;
  I = 1;
  do
  do
    {
    {
      X = Random ();
      X = Random ();
      Y = Random ();
      Y = Random ();
      Z9 = Y * X;
      Z9 = Y * X;
      Z = X * Y;
      Z = X * Y;
      Z9 = Z - Z9;
      Z9 = Z - Z9;
      I = I + 1;
      I = I + 1;
    }
    }
  while (!((I > NoTrials) || (Z9 != Zero)));
  while (!((I > NoTrials) || (Z9 != Zero)));
  if (I == NoTrials)
  if (I == NoTrials)
    {
    {
      Random1 = One + Half / Three;
      Random1 = One + Half / Three;
      Random2 = (U2 + U1) + One;
      Random2 = (U2 + U1) + One;
      Z = Random1 * Random2;
      Z = Random1 * Random2;
      Y = Random2 * Random1;
      Y = Random2 * Random1;
      Z9 = (One + Half / Three) * ((U2 + U1) + One) - (One + Half /
      Z9 = (One + Half / Three) * ((U2 + U1) + One) - (One + Half /
                                                       Three) * ((U2 + U1) +
                                                       Three) * ((U2 + U1) +
                                                                 One);
                                                                 One);
    }
    }
  if (!((I == NoTrials) || (Z9 == Zero)))
  if (!((I == NoTrials) || (Z9 == Zero)))
    BadCond (Defect, "X * Y == Y * X trial fails.\n");
    BadCond (Defect, "X * Y == Y * X trial fails.\n");
  else
  else
    printf ("     No failures found in %d integer pairs.\n", NoTrials);
    printf ("     No failures found in %d integer pairs.\n", NoTrials);
        /*=============================================*/
        /*=============================================*/
  Milestone = 70;
  Milestone = 70;
        /*=============================================*/
        /*=============================================*/
  printf ("\nRunning test of square root(x).\n");
  printf ("\nRunning test of square root(x).\n");
  TstCond (Failure, (Zero == SQRT (Zero))
  TstCond (Failure, (Zero == SQRT (Zero))
           && (-Zero == SQRT (-Zero))
           && (-Zero == SQRT (-Zero))
           && (One == SQRT (One)), "Square root of 0.0, -0.0 or 1.0 wrong");
           && (One == SQRT (One)), "Square root of 0.0, -0.0 or 1.0 wrong");
  MinSqEr = Zero;
  MinSqEr = Zero;
  MaxSqEr = Zero;
  MaxSqEr = Zero;
  J = Zero;
  J = Zero;
  X = Radix;
  X = Radix;
  OneUlp = U2;
  OneUlp = U2;
  SqXMinX (Serious);
  SqXMinX (Serious);
  X = BInvrse;
  X = BInvrse;
  OneUlp = BInvrse * U1;
  OneUlp = BInvrse * U1;
  SqXMinX (Serious);
  SqXMinX (Serious);
  X = U1;
  X = U1;
  OneUlp = U1 * U1;
  OneUlp = U1 * U1;
  SqXMinX (Serious);
  SqXMinX (Serious);
  if (J != Zero)
  if (J != Zero)
    Pause ();
    Pause ();
  printf ("Testing if sqrt(X * X) == X for %d Integers X.\n", NoTrials);
  printf ("Testing if sqrt(X * X) == X for %d Integers X.\n", NoTrials);
  J = Zero;
  J = Zero;
  X = Two;
  X = Two;
  Y = Radix;
  Y = Radix;
  if ((Radix != One))
  if ((Radix != One))
    do
    do
      {
      {
        X = Y;
        X = Y;
        Y = Radix * Y;
        Y = Radix * Y;
      }
      }
    while (!((Y - X >= NoTrials)));
    while (!((Y - X >= NoTrials)));
  OneUlp = X * U2;
  OneUlp = X * U2;
  I = 1;
  I = 1;
  while (I <= NoTrials)
  while (I <= NoTrials)
    {
    {
      X = X + One;
      X = X + One;
      SqXMinX (Defect);
      SqXMinX (Defect);
      if (J > Zero)
      if (J > Zero)
        break;
        break;
      I = I + 1;
      I = I + 1;
    }
    }
  printf ("Test for sqrt monotonicity.\n");
  printf ("Test for sqrt monotonicity.\n");
  I = -1;
  I = -1;
  X = BMinusU2;
  X = BMinusU2;
  Y = Radix;
  Y = Radix;
  Z = Radix + Radix * U2;
  Z = Radix + Radix * U2;
  NotMonot = false;
  NotMonot = false;
  Monot = false;
  Monot = false;
  while (!(NotMonot || Monot))
  while (!(NotMonot || Monot))
    {
    {
      I = I + 1;
      I = I + 1;
      X = SQRT (X);
      X = SQRT (X);
      Q = SQRT (Y);
      Q = SQRT (Y);
      Z = SQRT (Z);
      Z = SQRT (Z);
      if ((X > Q) || (Q > Z))
      if ((X > Q) || (Q > Z))
        NotMonot = true;
        NotMonot = true;
      else
      else
        {
        {
          Q = FLOOR (Q + Half);
          Q = FLOOR (Q + Half);
          if (!(I > 0 || Radix == Q * Q))
          if (!(I > 0 || Radix == Q * Q))
            Monot = true;
            Monot = true;
          else if (I > 0)
          else if (I > 0)
            {
            {
              if (I > 1)
              if (I > 1)
                Monot = true;
                Monot = true;
              else
              else
                {
                {
                  Y = Y * BInvrse;
                  Y = Y * BInvrse;
                  X = Y - U1;
                  X = Y - U1;
                  Z = Y + U1;
                  Z = Y + U1;
                }
                }
            }
            }
          else
          else
            {
            {
              Y = Q;
              Y = Q;
              X = Y - U2;
              X = Y - U2;
              Z = Y + U2;
              Z = Y + U2;
            }
            }
        }
        }
    }
    }
  if (Monot)
  if (Monot)
    printf ("sqrt has passed a test for Monotonicity.\n");
    printf ("sqrt has passed a test for Monotonicity.\n");
  else
  else
    {
    {
      BadCond (Defect, "");
      BadCond (Defect, "");
      printf ("sqrt(X) is non-monotonic for X near %s .\n", Y.str());
      printf ("sqrt(X) is non-monotonic for X near %s .\n", Y.str());
    }
    }
        /*=============================================*/
        /*=============================================*/
  Milestone = 110;
  Milestone = 110;
        /*=============================================*/
        /*=============================================*/
  printf ("Seeking Underflow thresholds UfThold and E0.\n");
  printf ("Seeking Underflow thresholds UfThold and E0.\n");
  D = U1;
  D = U1;
  if (Precision != FLOOR (Precision))
  if (Precision != FLOOR (Precision))
    {
    {
      D = BInvrse;
      D = BInvrse;
      X = Precision;
      X = Precision;
      do
      do
        {
        {
          D = D * BInvrse;
          D = D * BInvrse;
          X = X - One;
          X = X - One;
        }
        }
      while (X > Zero);
      while (X > Zero);
    }
    }
  Y = One;
  Y = One;
  Z = D;
  Z = D;
  /* ... D is power of 1/Radix < 1. */
  /* ... D is power of 1/Radix < 1. */
  do
  do
    {
    {
      C = Y;
      C = Y;
      Y = Z;
      Y = Z;
      Z = Y * Y;
      Z = Y * Y;
    }
    }
  while ((Y > Z) && (Z + Z > Z));
  while ((Y > Z) && (Z + Z > Z));
  Y = C;
  Y = C;
  Z = Y * D;
  Z = Y * D;
  do
  do
    {
    {
      C = Y;
      C = Y;
      Y = Z;
      Y = Z;
      Z = Y * D;
      Z = Y * D;
    }
    }
  while ((Y > Z) && (Z + Z > Z));
  while ((Y > Z) && (Z + Z > Z));
  if (Radix < Two)
  if (Radix < Two)
    HInvrse = Two;
    HInvrse = Two;
  else
  else
    HInvrse = Radix;
    HInvrse = Radix;
  H = One / HInvrse;
  H = One / HInvrse;
  /* ... 1/HInvrse == H == Min(1/Radix, 1/2) */
  /* ... 1/HInvrse == H == Min(1/Radix, 1/2) */
  CInvrse = One / C;
  CInvrse = One / C;
  E0 = C;
  E0 = C;
  Z = E0 * H;
  Z = E0 * H;
  /* ...1/Radix^(BIG Integer) << 1 << CInvrse == 1/C */
  /* ...1/Radix^(BIG Integer) << 1 << CInvrse == 1/C */
  do
  do
    {
    {
      Y = E0;
      Y = E0;
      E0 = Z;
      E0 = Z;
      Z = E0 * H;
      Z = E0 * H;
    }
    }
  while ((E0 > Z) && (Z + Z > Z));
  while ((E0 > Z) && (Z + Z > Z));
  UfThold = E0;
  UfThold = E0;
  E1 = Zero;
  E1 = Zero;
  Q = Zero;
  Q = Zero;
  E9 = U2;
  E9 = U2;
  S = One + E9;
  S = One + E9;
  D = C * S;
  D = C * S;
  if (D <= C)
  if (D <= C)
    {
    {
      E9 = Radix * U2;
      E9 = Radix * U2;
      S = One + E9;
      S = One + E9;
      D = C * S;
      D = C * S;
      if (D <= C)
      if (D <= C)
        {
        {
          BadCond (Failure,
          BadCond (Failure,
                   "multiplication gets too many last digits wrong.\n");
                   "multiplication gets too many last digits wrong.\n");
          Underflow = E0;
          Underflow = E0;
          Y1 = Zero;
          Y1 = Zero;
          PseudoZero = Z;
          PseudoZero = Z;
          Pause ();
          Pause ();
        }
        }
    }
    }
  else
  else
    {
    {
      Underflow = D;
      Underflow = D;
      PseudoZero = Underflow * H;
      PseudoZero = Underflow * H;
      UfThold = Zero;
      UfThold = Zero;
      do
      do
        {
        {
          Y1 = Underflow;
          Y1 = Underflow;
          Underflow = PseudoZero;
          Underflow = PseudoZero;
          if (E1 + E1 <= E1)
          if (E1 + E1 <= E1)
            {
            {
              Y2 = Underflow * HInvrse;
              Y2 = Underflow * HInvrse;
              E1 = FABS (Y1 - Y2);
              E1 = FABS (Y1 - Y2);
              Q = Y1;
              Q = Y1;
              if ((UfThold == Zero) && (Y1 != Y2))
              if ((UfThold == Zero) && (Y1 != Y2))
                UfThold = Y1;
                UfThold = Y1;
            }
            }
          PseudoZero = PseudoZero * H;
          PseudoZero = PseudoZero * H;
        }
        }
      while ((Underflow > PseudoZero)
      while ((Underflow > PseudoZero)
             && (PseudoZero + PseudoZero > PseudoZero));
             && (PseudoZero + PseudoZero > PseudoZero));
    }
    }
  /* Comment line 4530 .. 4560 */
  /* Comment line 4530 .. 4560 */
  if (PseudoZero != Zero)
  if (PseudoZero != Zero)
    {
    {
      printf ("\n");
      printf ("\n");
      Z = PseudoZero;
      Z = PseudoZero;
      /* ... Test PseudoZero for "phoney- zero" violates */
      /* ... Test PseudoZero for "phoney- zero" violates */
      /* ... PseudoZero < Underflow or PseudoZero < PseudoZero + PseudoZero
      /* ... PseudoZero < Underflow or PseudoZero < PseudoZero + PseudoZero
         ... */
         ... */
      if (PseudoZero <= Zero)
      if (PseudoZero <= Zero)
        {
        {
          BadCond (Failure, "Positive expressions can underflow to an\n");
          BadCond (Failure, "Positive expressions can underflow to an\n");
          printf ("allegedly negative value\n");
          printf ("allegedly negative value\n");
          printf ("PseudoZero that prints out as: %s .\n", PseudoZero.str());
          printf ("PseudoZero that prints out as: %s .\n", PseudoZero.str());
          X = -PseudoZero;
          X = -PseudoZero;
          if (X <= Zero)
          if (X <= Zero)
            {
            {
              printf ("But -PseudoZero, which should be\n");
              printf ("But -PseudoZero, which should be\n");
              printf ("positive, isn't; it prints out as  %s .\n", X.str());
              printf ("positive, isn't; it prints out as  %s .\n", X.str());
            }
            }
        }
        }
      else
      else
        {
        {
          BadCond (Flaw, "Underflow can stick at an allegedly positive\n");
          BadCond (Flaw, "Underflow can stick at an allegedly positive\n");
          printf ("value PseudoZero that prints out as %s .\n",
          printf ("value PseudoZero that prints out as %s .\n",
                  PseudoZero.str());
                  PseudoZero.str());
        }
        }
      TstPtUf ();
      TstPtUf ();
    }
    }
        /*=============================================*/
        /*=============================================*/
  Milestone = 120;
  Milestone = 120;
        /*=============================================*/
        /*=============================================*/
  if (CInvrse * Y > CInvrse * Y1)
  if (CInvrse * Y > CInvrse * Y1)
    {
    {
      S = H * S;
      S = H * S;
      E0 = Underflow;
      E0 = Underflow;
    }
    }
  if (!((E1 == Zero) || (E1 == E0)))
  if (!((E1 == Zero) || (E1 == E0)))
    {
    {
      BadCond (Defect, "");
      BadCond (Defect, "");
      if (E1 < E0)
      if (E1 < E0)
        {
        {
          printf ("Products underflow at a higher");
          printf ("Products underflow at a higher");
          printf (" threshold than differences.\n");
          printf (" threshold than differences.\n");
          if (PseudoZero == Zero)
          if (PseudoZero == Zero)
            E0 = E1;
            E0 = E1;
        }
        }
      else
      else
        {
        {
          printf ("Difference underflows at a higher");
          printf ("Difference underflows at a higher");
          printf (" threshold than products.\n");
          printf (" threshold than products.\n");
        }
        }
    }
    }
  printf ("Smallest strictly positive number found is E0 = %s .\n", E0.str());
  printf ("Smallest strictly positive number found is E0 = %s .\n", E0.str());
  Z = E0;
  Z = E0;
  TstPtUf ();
  TstPtUf ();
  Underflow = E0;
  Underflow = E0;
  if (N == 1)
  if (N == 1)
    Underflow = Y;
    Underflow = Y;
  I = 4;
  I = 4;
  if (E1 == Zero)
  if (E1 == Zero)
    I = 3;
    I = 3;
  if (UfThold == Zero)
  if (UfThold == Zero)
    I = I - 2;
    I = I - 2;
  UfNGrad = true;
  UfNGrad = true;
  switch (I)
  switch (I)
    {
    {
    case 1:
    case 1:
      UfThold = Underflow;
      UfThold = Underflow;
      if ((CInvrse * Q) != ((CInvrse * Y) * S))
      if ((CInvrse * Q) != ((CInvrse * Y) * S))
        {
        {
          UfThold = Y;
          UfThold = Y;
          BadCond (Failure, "Either accuracy deteriorates as numbers\n");
          BadCond (Failure, "Either accuracy deteriorates as numbers\n");
          printf ("approach a threshold = %s\n", UfThold.str());
          printf ("approach a threshold = %s\n", UfThold.str());
          printf (" coming down from %s\n", C.str());
          printf (" coming down from %s\n", C.str());
          printf
          printf
            (" or else multiplication gets too many last digits wrong.\n");
            (" or else multiplication gets too many last digits wrong.\n");
        }
        }
      Pause ();
      Pause ();
      break;
      break;
 
 
    case 2:
    case 2:
      BadCond (Failure,
      BadCond (Failure,
               "Underflow confuses Comparison, which alleges that\n");
               "Underflow confuses Comparison, which alleges that\n");
      printf ("Q == Y while denying that |Q - Y| == 0; these values\n");
      printf ("Q == Y while denying that |Q - Y| == 0; these values\n");
      printf ("print out as Q = %s, Y = %s .\n", Q.str(), Y2.str());
      printf ("print out as Q = %s, Y = %s .\n", Q.str(), Y2.str());
      printf ("|Q - Y| = %s .\n", FABS (Q - Y2).str());
      printf ("|Q - Y| = %s .\n", FABS (Q - Y2).str());
      UfThold = Q;
      UfThold = Q;
      break;
      break;
 
 
    case 3:
    case 3:
      X = X;
      X = X;
      break;
      break;
 
 
    case 4:
    case 4:
      if ((Q == UfThold) && (E1 == E0) && (FABS (UfThold - E1 / E9) <= E1))
      if ((Q == UfThold) && (E1 == E0) && (FABS (UfThold - E1 / E9) <= E1))
        {
        {
          UfNGrad = false;
          UfNGrad = false;
          printf ("Underflow is gradual; it incurs Absolute Error =\n");
          printf ("Underflow is gradual; it incurs Absolute Error =\n");
          printf ("(roundoff in UfThold) < E0.\n");
          printf ("(roundoff in UfThold) < E0.\n");
          Y = E0 * CInvrse;
          Y = E0 * CInvrse;
          Y = Y * (OneAndHalf + U2);
          Y = Y * (OneAndHalf + U2);
          X = CInvrse * (One + U2);
          X = CInvrse * (One + U2);
          Y = Y / X;
          Y = Y / X;
          IEEE = (Y == E0);
          IEEE = (Y == E0);
        }
        }
    }
    }
  if (UfNGrad)
  if (UfNGrad)
    {
    {
      printf ("\n");
      printf ("\n");
      if (setjmp (ovfl_buf))
      if (setjmp (ovfl_buf))
        {
        {
          printf ("Underflow / UfThold failed!\n");
          printf ("Underflow / UfThold failed!\n");
          R = H + H;
          R = H + H;
        }
        }
      else
      else
        R = SQRT (Underflow / UfThold);
        R = SQRT (Underflow / UfThold);
      if (R <= H)
      if (R <= H)
        {
        {
          Z = R * UfThold;
          Z = R * UfThold;
          X = Z * (One + R * H * (One + H));
          X = Z * (One + R * H * (One + H));
        }
        }
      else
      else
        {
        {
          Z = UfThold;
          Z = UfThold;
          X = Z * (One + H * H * (One + H));
          X = Z * (One + H * H * (One + H));
        }
        }
      if (!((X == Z) || (X - Z != Zero)))
      if (!((X == Z) || (X - Z != Zero)))
        {
        {
          BadCond (Flaw, "");
          BadCond (Flaw, "");
          printf ("X = %s\n\tis not equal to Z = %s .\n", X.str(), Z.str());
          printf ("X = %s\n\tis not equal to Z = %s .\n", X.str(), Z.str());
          Z9 = X - Z;
          Z9 = X - Z;
          printf ("yet X - Z yields %s .\n", Z9.str());
          printf ("yet X - Z yields %s .\n", Z9.str());
          printf ("    Should this NOT signal Underflow, ");
          printf ("    Should this NOT signal Underflow, ");
          printf ("this is a SERIOUS DEFECT\nthat causes ");
          printf ("this is a SERIOUS DEFECT\nthat causes ");
          printf ("confusion when innocent statements like\n");;
          printf ("confusion when innocent statements like\n");;
          printf ("    if (X == Z)  ...  else");
          printf ("    if (X == Z)  ...  else");
          printf ("  ... (f(X) - f(Z)) / (X - Z) ...\n");
          printf ("  ... (f(X) - f(Z)) / (X - Z) ...\n");
          printf ("encounter Division by Zero although actually\n");
          printf ("encounter Division by Zero although actually\n");
          if (setjmp (ovfl_buf))
          if (setjmp (ovfl_buf))
            printf ("X / Z fails!\n");
            printf ("X / Z fails!\n");
          else
          else
            printf ("X / Z = 1 + %s .\n", ((X / Z - Half) - Half).str());
            printf ("X / Z = 1 + %s .\n", ((X / Z - Half) - Half).str());
        }
        }
    }
    }
  printf ("The Underflow threshold is %s, below which\n", UfThold.str());
  printf ("The Underflow threshold is %s, below which\n", UfThold.str());
  printf ("calculation may suffer larger Relative error than ");
  printf ("calculation may suffer larger Relative error than ");
  printf ("merely roundoff.\n");
  printf ("merely roundoff.\n");
  Y2 = U1 * U1;
  Y2 = U1 * U1;
  Y = Y2 * Y2;
  Y = Y2 * Y2;
  Y2 = Y * U1;
  Y2 = Y * U1;
  if (Y2 <= UfThold)
  if (Y2 <= UfThold)
    {
    {
      if (Y > E0)
      if (Y > E0)
        {
        {
          BadCond (Defect, "");
          BadCond (Defect, "");
          I = 5;
          I = 5;
        }
        }
      else
      else
        {
        {
          BadCond (Serious, "");
          BadCond (Serious, "");
          I = 4;
          I = 4;
        }
        }
      printf ("Range is too narrow; U1^%d Underflows.\n", I);
      printf ("Range is too narrow; U1^%d Underflows.\n", I);
    }
    }
        /*=============================================*/
        /*=============================================*/
  Milestone = 130;
  Milestone = 130;
        /*=============================================*/
        /*=============================================*/
  Y = -FLOOR (Half - TwoForty * LOG (UfThold) / LOG (HInvrse)) / TwoForty;
  Y = -FLOOR (Half - TwoForty * LOG (UfThold) / LOG (HInvrse)) / TwoForty;
  Y2 = Y + Y;
  Y2 = Y + Y;
  printf ("Since underflow occurs below the threshold\n");
  printf ("Since underflow occurs below the threshold\n");
  printf ("UfThold = (%s) ^ (%s)\nonly underflow ", HInvrse.str(), Y.str());
  printf ("UfThold = (%s) ^ (%s)\nonly underflow ", HInvrse.str(), Y.str());
  printf ("should afflict the expression\n\t(%s) ^ (%s);\n",
  printf ("should afflict the expression\n\t(%s) ^ (%s);\n",
          HInvrse.str(), Y2.str());
          HInvrse.str(), Y2.str());
  printf ("actually calculating yields:");
  printf ("actually calculating yields:");
  if (setjmp (ovfl_buf))
  if (setjmp (ovfl_buf))
    {
    {
      BadCond (Serious, "trap on underflow.\n");
      BadCond (Serious, "trap on underflow.\n");
    }
    }
  else
  else
    {
    {
      V9 = POW (HInvrse, Y2);
      V9 = POW (HInvrse, Y2);
      printf (" %s .\n", V9.str());
      printf (" %s .\n", V9.str());
      if (!((V9 >= Zero) && (V9 <= (Radix + Radix + E9) * UfThold)))
      if (!((V9 >= Zero) && (V9 <= (Radix + Radix + E9) * UfThold)))
        {
        {
          BadCond (Serious, "this is not between 0 and underflow\n");
          BadCond (Serious, "this is not between 0 and underflow\n");
          printf ("   threshold = %s .\n", UfThold.str());
          printf ("   threshold = %s .\n", UfThold.str());
        }
        }
      else if (!(V9 > UfThold * (One + E9)))
      else if (!(V9 > UfThold * (One + E9)))
        printf ("This computed value is O.K.\n");
        printf ("This computed value is O.K.\n");
      else
      else
        {
        {
          BadCond (Defect, "this is not between 0 and underflow\n");
          BadCond (Defect, "this is not between 0 and underflow\n");
          printf ("   threshold = %s .\n", UfThold.str());
          printf ("   threshold = %s .\n", UfThold.str());
        }
        }
    }
    }
        /*=============================================*/
        /*=============================================*/
  Milestone = 160;
  Milestone = 160;
        /*=============================================*/
        /*=============================================*/
  Pause ();
  Pause ();
  printf ("Searching for Overflow threshold:\n");
  printf ("Searching for Overflow threshold:\n");
  printf ("This may generate an error.\n");
  printf ("This may generate an error.\n");
  Y = -CInvrse;
  Y = -CInvrse;
  V9 = HInvrse * Y;
  V9 = HInvrse * Y;
  if (setjmp (ovfl_buf))
  if (setjmp (ovfl_buf))
    {
    {
      I = 0;
      I = 0;
      V9 = Y;
      V9 = Y;
      goto overflow;
      goto overflow;
    }
    }
  do
  do
    {
    {
      V = Y;
      V = Y;
      Y = V9;
      Y = V9;
      V9 = HInvrse * Y;
      V9 = HInvrse * Y;
    }
    }
  while (V9 < Y);
  while (V9 < Y);
  I = 1;
  I = 1;
overflow:
overflow:
  Z = V9;
  Z = V9;
  printf ("Can `Z = -Y' overflow?\n");
  printf ("Can `Z = -Y' overflow?\n");
  printf ("Trying it on Y = %s .\n", Y.str());
  printf ("Trying it on Y = %s .\n", Y.str());
  V9 = -Y;
  V9 = -Y;
  V0 = V9;
  V0 = V9;
  if (V - Y == V + V0)
  if (V - Y == V + V0)
    printf ("Seems O.K.\n");
    printf ("Seems O.K.\n");
  else
  else
    {
    {
      printf ("finds a ");
      printf ("finds a ");
      BadCond (Flaw, "-(-Y) differs from Y.\n");
      BadCond (Flaw, "-(-Y) differs from Y.\n");
    }
    }
  if (Z != Y)
  if (Z != Y)
    {
    {
      BadCond (Serious, "");
      BadCond (Serious, "");
      printf ("overflow past %s\n\tshrinks to %s .\n", Y.str(), Z.str());
      printf ("overflow past %s\n\tshrinks to %s .\n", Y.str(), Z.str());
    }
    }
  if (I)
  if (I)
    {
    {
      Y = V * (HInvrse * U2 - HInvrse);
      Y = V * (HInvrse * U2 - HInvrse);
      Z = Y + ((One - HInvrse) * U2) * V;
      Z = Y + ((One - HInvrse) * U2) * V;
      if (Z < V0)
      if (Z < V0)
        Y = Z;
        Y = Z;
      if (Y < V0)
      if (Y < V0)
        V = Y;
        V = Y;
      if (V0 - V < V0)
      if (V0 - V < V0)
        V = V0;
        V = V0;
    }
    }
  else
  else
    {
    {
      V = Y * (HInvrse * U2 - HInvrse);
      V = Y * (HInvrse * U2 - HInvrse);
      V = V + ((One - HInvrse) * U2) * Y;
      V = V + ((One - HInvrse) * U2) * Y;
    }
    }
  printf ("Overflow threshold is V  = %s .\n", V.str());
  printf ("Overflow threshold is V  = %s .\n", V.str());
  if (I)
  if (I)
    printf ("Overflow saturates at V0 = %s .\n", V0.str());
    printf ("Overflow saturates at V0 = %s .\n", V0.str());
  else
  else
    printf ("There is no saturation value because "
    printf ("There is no saturation value because "
            "the system traps on overflow.\n");
            "the system traps on overflow.\n");
  V9 = V * One;
  V9 = V * One;
  printf ("No Overflow should be signaled for V * 1 = %s\n", V9.str());
  printf ("No Overflow should be signaled for V * 1 = %s\n", V9.str());
  V9 = V / One;
  V9 = V / One;
  printf ("                           nor for V / 1 = %s.\n", V9.str());
  printf ("                           nor for V / 1 = %s.\n", V9.str());
  printf ("Any overflow signal separating this * from the one\n");
  printf ("Any overflow signal separating this * from the one\n");
  printf ("above is a DEFECT.\n");
  printf ("above is a DEFECT.\n");
        /*=============================================*/
        /*=============================================*/
  Milestone = 170;
  Milestone = 170;
        /*=============================================*/
        /*=============================================*/
  if (!(-V < V && -V0 < V0 && -UfThold < V && UfThold < V))
  if (!(-V < V && -V0 < V0 && -UfThold < V && UfThold < V))
    {
    {
      BadCond (Failure, "Comparisons involving ");
      BadCond (Failure, "Comparisons involving ");
      printf ("+-%s, +-%s\nand +-%s are confused by Overflow.",
      printf ("+-%s, +-%s\nand +-%s are confused by Overflow.",
              V.str(), V0.str(), UfThold.str());
              V.str(), V0.str(), UfThold.str());
    }
    }
        /*=============================================*/
        /*=============================================*/
  Milestone = 175;
  Milestone = 175;
        /*=============================================*/
        /*=============================================*/
  printf ("\n");
  printf ("\n");
  for (Indx = 1; Indx <= 3; ++Indx)
  for (Indx = 1; Indx <= 3; ++Indx)
    {
    {
      switch (Indx)
      switch (Indx)
        {
        {
        case 1:
        case 1:
          Z = UfThold;
          Z = UfThold;
          break;
          break;
        case 2:
        case 2:
          Z = E0;
          Z = E0;
          break;
          break;
        case 3:
        case 3:
          Z = PseudoZero;
          Z = PseudoZero;
          break;
          break;
        }
        }
      if (Z != Zero)
      if (Z != Zero)
        {
        {
          V9 = SQRT (Z);
          V9 = SQRT (Z);
          Y = V9 * V9;
          Y = V9 * V9;
          if (Y / (One - Radix * E9) < Z || Y > (One + Radix * E9) * Z)
          if (Y / (One - Radix * E9) < Z || Y > (One + Radix * E9) * Z)
            {                   /* dgh: + E9 --> * E9 */
            {                   /* dgh: + E9 --> * E9 */
              if (V9 > U1)
              if (V9 > U1)
                BadCond (Serious, "");
                BadCond (Serious, "");
              else
              else
                BadCond (Defect, "");
                BadCond (Defect, "");
              printf ("Comparison alleges that what prints as Z = %s\n",
              printf ("Comparison alleges that what prints as Z = %s\n",
                      Z.str());
                      Z.str());
              printf (" is too far from sqrt(Z) ^ 2 = %s .\n", Y.str());
              printf (" is too far from sqrt(Z) ^ 2 = %s .\n", Y.str());
            }
            }
        }
        }
    }
    }
        /*=============================================*/
        /*=============================================*/
  Milestone = 180;
  Milestone = 180;
        /*=============================================*/
        /*=============================================*/
  for (Indx = 1; Indx <= 2; ++Indx)
  for (Indx = 1; Indx <= 2; ++Indx)
    {
    {
      if (Indx == 1)
      if (Indx == 1)
        Z = V;
        Z = V;
      else
      else
        Z = V0;
        Z = V0;
      V9 = SQRT (Z);
      V9 = SQRT (Z);
      X = (One - Radix * E9) * V9;
      X = (One - Radix * E9) * V9;
      V9 = V9 * X;
      V9 = V9 * X;
      if (((V9 < (One - Two * Radix * E9) * Z) || (V9 > Z)))
      if (((V9 < (One - Two * Radix * E9) * Z) || (V9 > Z)))
        {
        {
          Y = V9;
          Y = V9;
          if (X < W)
          if (X < W)
            BadCond (Serious, "");
            BadCond (Serious, "");
          else
          else
            BadCond (Defect, "");
            BadCond (Defect, "");
          printf ("Comparison alleges that Z = %s\n", Z.str());
          printf ("Comparison alleges that Z = %s\n", Z.str());
          printf (" is too far from sqrt(Z) ^ 2 (%s) .\n", Y.str());
          printf (" is too far from sqrt(Z) ^ 2 (%s) .\n", Y.str());
        }
        }
    }
    }
        /*=============================================*/
        /*=============================================*/
  Milestone = 190;
  Milestone = 190;
        /*=============================================*/
        /*=============================================*/
  Pause ();
  Pause ();
  X = UfThold * V;
  X = UfThold * V;
  Y = Radix * Radix;
  Y = Radix * Radix;
  if (X * Y < One || X > Y)
  if (X * Y < One || X > Y)
    {
    {
      if (X * Y < U1 || X > Y / U1)
      if (X * Y < U1 || X > Y / U1)
        BadCond (Defect, "Badly");
        BadCond (Defect, "Badly");
      else
      else
        BadCond (Flaw, "");
        BadCond (Flaw, "");
 
 
      printf (" unbalanced range; UfThold * V = %s\n\t%s\n",
      printf (" unbalanced range; UfThold * V = %s\n\t%s\n",
              X.str(), "is too far from 1.\n");
              X.str(), "is too far from 1.\n");
    }
    }
        /*=============================================*/
        /*=============================================*/
  Milestone = 200;
  Milestone = 200;
        /*=============================================*/
        /*=============================================*/
  for (Indx = 1; Indx <= 5; ++Indx)
  for (Indx = 1; Indx <= 5; ++Indx)
    {
    {
      X = F9;
      X = F9;
      switch (Indx)
      switch (Indx)
        {
        {
        case 2:
        case 2:
          X = One + U2;
          X = One + U2;
          break;
          break;
        case 3:
        case 3:
          X = V;
          X = V;
          break;
          break;
        case 4:
        case 4:
          X = UfThold;
          X = UfThold;
          break;
          break;
        case 5:
        case 5:
          X = Radix;
          X = Radix;
        }
        }
      Y = X;
      Y = X;
      if (setjmp (ovfl_buf))
      if (setjmp (ovfl_buf))
        printf ("  X / X  traps when X = %s\n", X.str());
        printf ("  X / X  traps when X = %s\n", X.str());
      else
      else
        {
        {
          V9 = (Y / X - Half) - Half;
          V9 = (Y / X - Half) - Half;
          if (V9 == Zero)
          if (V9 == Zero)
            continue;
            continue;
          if (V9 == -U1 && Indx < 5)
          if (V9 == -U1 && Indx < 5)
            BadCond (Flaw, "");
            BadCond (Flaw, "");
          else
          else
            BadCond (Serious, "");
            BadCond (Serious, "");
          printf ("  X / X differs from 1 when X = %s\n", X.str());
          printf ("  X / X differs from 1 when X = %s\n", X.str());
          printf ("  instead, X / X - 1/2 - 1/2 = %s .\n", V9.str());
          printf ("  instead, X / X - 1/2 - 1/2 = %s .\n", V9.str());
        }
        }
    }
    }
        /*=============================================*/
        /*=============================================*/
  Milestone = 210;
  Milestone = 210;
        /*=============================================*/
        /*=============================================*/
  MyZero = Zero;
  MyZero = Zero;
  printf ("\n");
  printf ("\n");
  printf ("What message and/or values does Division by Zero produce?\n");
  printf ("What message and/or values does Division by Zero produce?\n");
  printf ("    Trying to compute 1 / 0 produces ...");
  printf ("    Trying to compute 1 / 0 produces ...");
  if (!setjmp (ovfl_buf))
  if (!setjmp (ovfl_buf))
    printf ("  %s .\n", (One / MyZero).str());
    printf ("  %s .\n", (One / MyZero).str());
  printf ("\n    Trying to compute 0 / 0 produces ...");
  printf ("\n    Trying to compute 0 / 0 produces ...");
  if (!setjmp (ovfl_buf))
  if (!setjmp (ovfl_buf))
    printf ("  %s .\n", (Zero / MyZero).str());
    printf ("  %s .\n", (Zero / MyZero).str());
        /*=============================================*/
        /*=============================================*/
  Milestone = 220;
  Milestone = 220;
        /*=============================================*/
        /*=============================================*/
  Pause ();
  Pause ();
  printf ("\n");
  printf ("\n");
  {
  {
    static const char *msg[] = {
    static const char *msg[] = {
      "FAILUREs  encountered =",
      "FAILUREs  encountered =",
      "SERIOUS DEFECTs  discovered =",
      "SERIOUS DEFECTs  discovered =",
      "DEFECTs  discovered =",
      "DEFECTs  discovered =",
      "FLAWs  discovered ="
      "FLAWs  discovered ="
    };
    };
    int i;
    int i;
    for (i = 0; i < 4; i++)
    for (i = 0; i < 4; i++)
      if (ErrCnt[i])
      if (ErrCnt[i])
        printf ("The number of  %-29s %d.\n", msg[i], ErrCnt[i]);
        printf ("The number of  %-29s %d.\n", msg[i], ErrCnt[i]);
  }
  }
  printf ("\n");
  printf ("\n");
  if ((ErrCnt[Failure] + ErrCnt[Serious] + ErrCnt[Defect] + ErrCnt[Flaw]) > 0)
  if ((ErrCnt[Failure] + ErrCnt[Serious] + ErrCnt[Defect] + ErrCnt[Flaw]) > 0)
    {
    {
      if ((ErrCnt[Failure] + ErrCnt[Serious] + ErrCnt[Defect] == 0)
      if ((ErrCnt[Failure] + ErrCnt[Serious] + ErrCnt[Defect] == 0)
          && (ErrCnt[Flaw] > 0))
          && (ErrCnt[Flaw] > 0))
        {
        {
          printf ("The arithmetic diagnosed seems ");
          printf ("The arithmetic diagnosed seems ");
          printf ("Satisfactory though flawed.\n");
          printf ("Satisfactory though flawed.\n");
        }
        }
      if ((ErrCnt[Failure] + ErrCnt[Serious] == 0) && (ErrCnt[Defect] > 0))
      if ((ErrCnt[Failure] + ErrCnt[Serious] == 0) && (ErrCnt[Defect] > 0))
        {
        {
          printf ("The arithmetic diagnosed may be Acceptable\n");
          printf ("The arithmetic diagnosed may be Acceptable\n");
          printf ("despite inconvenient Defects.\n");
          printf ("despite inconvenient Defects.\n");
        }
        }
      if ((ErrCnt[Failure] + ErrCnt[Serious]) > 0)
      if ((ErrCnt[Failure] + ErrCnt[Serious]) > 0)
        {
        {
          printf ("The arithmetic diagnosed has ");
          printf ("The arithmetic diagnosed has ");
          printf ("unacceptable Serious Defects.\n");
          printf ("unacceptable Serious Defects.\n");
        }
        }
      if (ErrCnt[Failure] > 0)
      if (ErrCnt[Failure] > 0)
        {
        {
          printf ("Potentially fatal FAILURE may have spoiled this");
          printf ("Potentially fatal FAILURE may have spoiled this");
          printf (" program's subsequent diagnoses.\n");
          printf (" program's subsequent diagnoses.\n");
        }
        }
    }
    }
  else
  else
    {
    {
      printf ("No failures, defects nor flaws have been discovered.\n");
      printf ("No failures, defects nor flaws have been discovered.\n");
      if (!((RMult == Rounded) && (RDiv == Rounded)
      if (!((RMult == Rounded) && (RDiv == Rounded)
            && (RAddSub == Rounded) && (RSqrt == Rounded)))
            && (RAddSub == Rounded) && (RSqrt == Rounded)))
        printf ("The arithmetic diagnosed seems Satisfactory.\n");
        printf ("The arithmetic diagnosed seems Satisfactory.\n");
      else
      else
        {
        {
          if (StickyBit >= One &&
          if (StickyBit >= One &&
              (Radix - Two) * (Radix - Nine - One) == Zero)
              (Radix - Two) * (Radix - Nine - One) == Zero)
            {
            {
              printf ("Rounding appears to conform to ");
              printf ("Rounding appears to conform to ");
              printf ("the proposed IEEE standard P");
              printf ("the proposed IEEE standard P");
              if ((Radix == Two) &&
              if ((Radix == Two) &&
                  ((Precision - Four * Three * Two) *
                  ((Precision - Four * Three * Two) *
                   (Precision - TwentySeven - TwentySeven + One) == Zero))
                   (Precision - TwentySeven - TwentySeven + One) == Zero))
                printf ("754");
                printf ("754");
              else
              else
                printf ("854");
                printf ("854");
              if (IEEE)
              if (IEEE)
                printf (".\n");
                printf (".\n");
              else
              else
                {
                {
                  printf (",\nexcept for possibly Double Rounding");
                  printf (",\nexcept for possibly Double Rounding");
                  printf (" during Gradual Underflow.\n");
                  printf (" during Gradual Underflow.\n");
                }
                }
            }
            }
          printf ("The arithmetic diagnosed appears to be Excellent!\n");
          printf ("The arithmetic diagnosed appears to be Excellent!\n");
        }
        }
    }
    }
  printf ("END OF TEST.\n");
  printf ("END OF TEST.\n");
  return 0;
  return 0;
}
}
 
 
template<typename FLOAT>
template<typename FLOAT>
FLOAT
FLOAT
Paranoia<FLOAT>::Sign (FLOAT X)
Paranoia<FLOAT>::Sign (FLOAT X)
{
{
  return X >= FLOAT (long (0)) ? 1 : -1;
  return X >= FLOAT (long (0)) ? 1 : -1;
}
}
 
 
template<typename FLOAT>
template<typename FLOAT>
void
void
Paranoia<FLOAT>::Pause ()
Paranoia<FLOAT>::Pause ()
{
{
  if (do_pause)
  if (do_pause)
    {
    {
      fputs ("Press return...", stdout);
      fputs ("Press return...", stdout);
      fflush (stdout);
      fflush (stdout);
      getchar();
      getchar();
    }
    }
  printf ("\nDiagnosis resumes after milestone Number %d", Milestone);
  printf ("\nDiagnosis resumes after milestone Number %d", Milestone);
  printf ("          Page: %d\n\n", PageNo);
  printf ("          Page: %d\n\n", PageNo);
  ++Milestone;
  ++Milestone;
  ++PageNo;
  ++PageNo;
}
}
 
 
template<typename FLOAT>
template<typename FLOAT>
void
void
Paranoia<FLOAT>::TstCond (int K, int Valid, const char *T)
Paranoia<FLOAT>::TstCond (int K, int Valid, const char *T)
{
{
  if (!Valid)
  if (!Valid)
    {
    {
      BadCond (K, T);
      BadCond (K, T);
      printf (".\n");
      printf (".\n");
    }
    }
}
}
 
 
template<typename FLOAT>
template<typename FLOAT>
void
void
Paranoia<FLOAT>::BadCond (int K, const char *T)
Paranoia<FLOAT>::BadCond (int K, const char *T)
{
{
  static const char *msg[] = { "FAILURE", "SERIOUS DEFECT", "DEFECT", "FLAW" };
  static const char *msg[] = { "FAILURE", "SERIOUS DEFECT", "DEFECT", "FLAW" };
 
 
  ErrCnt[K] = ErrCnt[K] + 1;
  ErrCnt[K] = ErrCnt[K] + 1;
  printf ("%s:  %s", msg[K], T);
  printf ("%s:  %s", msg[K], T);
}
}
 
 
/* Random computes
/* Random computes
     X = (Random1 + Random9)^5
     X = (Random1 + Random9)^5
     Random1 = X - FLOOR(X) + 0.000005 * X;
     Random1 = X - FLOOR(X) + 0.000005 * X;
   and returns the new value of Random1.  */
   and returns the new value of Random1.  */
 
 
template<typename FLOAT>
template<typename FLOAT>
FLOAT
FLOAT
Paranoia<FLOAT>::Random ()
Paranoia<FLOAT>::Random ()
{
{
  FLOAT X, Y;
  FLOAT X, Y;
 
 
  X = Random1 + Random9;
  X = Random1 + Random9;
  Y = X * X;
  Y = X * X;
  Y = Y * Y;
  Y = Y * Y;
  X = X * Y;
  X = X * Y;
  Y = X - FLOOR (X);
  Y = X - FLOOR (X);
  Random1 = Y + X * FLOAT ("0.000005");
  Random1 = Y + X * FLOAT ("0.000005");
  return (Random1);
  return (Random1);
}
}
 
 
template<typename FLOAT>
template<typename FLOAT>
void
void
Paranoia<FLOAT>::SqXMinX (int ErrKind)
Paranoia<FLOAT>::SqXMinX (int ErrKind)
{
{
  FLOAT XA, XB;
  FLOAT XA, XB;
 
 
  XB = X * BInvrse;
  XB = X * BInvrse;
  XA = X - XB;
  XA = X - XB;
  SqEr = ((SQRT (X * X) - XB) - XA) / OneUlp;
  SqEr = ((SQRT (X * X) - XB) - XA) / OneUlp;
  if (SqEr != Zero)
  if (SqEr != Zero)
    {
    {
      if (SqEr < MinSqEr)
      if (SqEr < MinSqEr)
        MinSqEr = SqEr;
        MinSqEr = SqEr;
      if (SqEr > MaxSqEr)
      if (SqEr > MaxSqEr)
        MaxSqEr = SqEr;
        MaxSqEr = SqEr;
      J = J + 1;
      J = J + 1;
      BadCond (ErrKind, "\n");
      BadCond (ErrKind, "\n");
      printf ("sqrt(%s) - %s  = %s\n", (X * X).str(), X.str(),
      printf ("sqrt(%s) - %s  = %s\n", (X * X).str(), X.str(),
              (OneUlp * SqEr).str());
              (OneUlp * SqEr).str());
      printf ("\tinstead of correct value 0 .\n");
      printf ("\tinstead of correct value 0 .\n");
    }
    }
}
}
 
 
template<typename FLOAT>
template<typename FLOAT>
void
void
Paranoia<FLOAT>::NewD ()
Paranoia<FLOAT>::NewD ()
{
{
  X = Z1 * Q;
  X = Z1 * Q;
  X = FLOOR (Half - X / Radix) * Radix + X;
  X = FLOOR (Half - X / Radix) * Radix + X;
  Q = (Q - X * Z) / Radix + X * X * (D / Radix);
  Q = (Q - X * Z) / Radix + X * X * (D / Radix);
  Z = Z - Two * X * D;
  Z = Z - Two * X * D;
  if (Z <= Zero)
  if (Z <= Zero)
    {
    {
      Z = -Z;
      Z = -Z;
      Z1 = -Z1;
      Z1 = -Z1;
    }
    }
  D = Radix * D;
  D = Radix * D;
}
}
 
 
template<typename FLOAT>
template<typename FLOAT>
void
void
Paranoia<FLOAT>::SR3750 ()
Paranoia<FLOAT>::SR3750 ()
{
{
  if (!((X - Radix < Z2 - Radix) || (X - Z2 > W - Z2)))
  if (!((X - Radix < Z2 - Radix) || (X - Z2 > W - Z2)))
    {
    {
      I = I + 1;
      I = I + 1;
      X2 = SQRT (X * D);
      X2 = SQRT (X * D);
      Y2 = (X2 - Z2) - (Y - Z2);
      Y2 = (X2 - Z2) - (Y - Z2);
      X2 = X8 / (Y - Half);
      X2 = X8 / (Y - Half);
      X2 = X2 - Half * X2 * X2;
      X2 = X2 - Half * X2 * X2;
      SqEr = (Y2 + Half) + (Half - X2);
      SqEr = (Y2 + Half) + (Half - X2);
      if (SqEr < MinSqEr)
      if (SqEr < MinSqEr)
        MinSqEr = SqEr;
        MinSqEr = SqEr;
      SqEr = Y2 - X2;
      SqEr = Y2 - X2;
      if (SqEr > MaxSqEr)
      if (SqEr > MaxSqEr)
        MaxSqEr = SqEr;
        MaxSqEr = SqEr;
    }
    }
}
}
 
 
template<typename FLOAT>
template<typename FLOAT>
void
void
Paranoia<FLOAT>::IsYeqX ()
Paranoia<FLOAT>::IsYeqX ()
{
{
  if (Y != X)
  if (Y != X)
    {
    {
      if (N <= 0)
      if (N <= 0)
        {
        {
          if (Z == Zero && Q <= Zero)
          if (Z == Zero && Q <= Zero)
            printf ("WARNING:  computing\n");
            printf ("WARNING:  computing\n");
          else
          else
            BadCond (Defect, "computing\n");
            BadCond (Defect, "computing\n");
          printf ("\t(%s) ^ (%s)\n", Z.str(), Q.str());
          printf ("\t(%s) ^ (%s)\n", Z.str(), Q.str());
          printf ("\tyielded %s;\n", Y.str());
          printf ("\tyielded %s;\n", Y.str());
          printf ("\twhich compared unequal to correct %s ;\n", X.str());
          printf ("\twhich compared unequal to correct %s ;\n", X.str());
          printf ("\t\tthey differ by %s .\n", (Y - X).str());
          printf ("\t\tthey differ by %s .\n", (Y - X).str());
        }
        }
      N = N + 1;                /* ... count discrepancies. */
      N = N + 1;                /* ... count discrepancies. */
    }
    }
}
}
 
 
template<typename FLOAT>
template<typename FLOAT>
void
void
Paranoia<FLOAT>::PrintIfNPositive ()
Paranoia<FLOAT>::PrintIfNPositive ()
{
{
  if (N > 0)
  if (N > 0)
    printf ("Similar discrepancies have occurred %d times.\n", N);
    printf ("Similar discrepancies have occurred %d times.\n", N);
}
}
 
 
template<typename FLOAT>
template<typename FLOAT>
void
void
Paranoia<FLOAT>::TstPtUf ()
Paranoia<FLOAT>::TstPtUf ()
{
{
  N = 0;
  N = 0;
  if (Z != Zero)
  if (Z != Zero)
    {
    {
      printf ("Since comparison denies Z = 0, evaluating ");
      printf ("Since comparison denies Z = 0, evaluating ");
      printf ("(Z + Z) / Z should be safe.\n");
      printf ("(Z + Z) / Z should be safe.\n");
      if (setjmp (ovfl_buf))
      if (setjmp (ovfl_buf))
        goto very_serious;
        goto very_serious;
      Q9 = (Z + Z) / Z;
      Q9 = (Z + Z) / Z;
      printf ("What the machine gets for (Z + Z) / Z is %s .\n", Q9.str());
      printf ("What the machine gets for (Z + Z) / Z is %s .\n", Q9.str());
      if (FABS (Q9 - Two) < Radix * U2)
      if (FABS (Q9 - Two) < Radix * U2)
        {
        {
          printf ("This is O.K., provided Over/Underflow");
          printf ("This is O.K., provided Over/Underflow");
          printf (" has NOT just been signaled.\n");
          printf (" has NOT just been signaled.\n");
        }
        }
      else
      else
        {
        {
          if ((Q9 < One) || (Q9 > Two))
          if ((Q9 < One) || (Q9 > Two))
            {
            {
            very_serious:
            very_serious:
              N = 1;
              N = 1;
              ErrCnt[Serious] = ErrCnt[Serious] + 1;
              ErrCnt[Serious] = ErrCnt[Serious] + 1;
              printf ("This is a VERY SERIOUS DEFECT!\n");
              printf ("This is a VERY SERIOUS DEFECT!\n");
            }
            }
          else
          else
            {
            {
              N = 1;
              N = 1;
              ErrCnt[Defect] = ErrCnt[Defect] + 1;
              ErrCnt[Defect] = ErrCnt[Defect] + 1;
              printf ("This is a DEFECT!\n");
              printf ("This is a DEFECT!\n");
            }
            }
        }
        }
      V9 = Z * One;
      V9 = Z * One;
      Random1 = V9;
      Random1 = V9;
      V9 = One * Z;
      V9 = One * Z;
      Random2 = V9;
      Random2 = V9;
      V9 = Z / One;
      V9 = Z / One;
      if ((Z == Random1) && (Z == Random2) && (Z == V9))
      if ((Z == Random1) && (Z == Random2) && (Z == V9))
        {
        {
          if (N > 0)
          if (N > 0)
            Pause ();
            Pause ();
        }
        }
      else
      else
        {
        {
          N = 1;
          N = 1;
          BadCond (Defect, "What prints as Z = ");
          BadCond (Defect, "What prints as Z = ");
          printf ("%s\n\tcompares different from  ", Z.str());
          printf ("%s\n\tcompares different from  ", Z.str());
          if (Z != Random1)
          if (Z != Random1)
            printf ("Z * 1 = %s ", Random1.str());
            printf ("Z * 1 = %s ", Random1.str());
          if (!((Z == Random2) || (Random2 == Random1)))
          if (!((Z == Random2) || (Random2 == Random1)))
            printf ("1 * Z == %s\n", Random2.str());
            printf ("1 * Z == %s\n", Random2.str());
          if (!(Z == V9))
          if (!(Z == V9))
            printf ("Z / 1 = %s\n", V9.str());
            printf ("Z / 1 = %s\n", V9.str());
          if (Random2 != Random1)
          if (Random2 != Random1)
            {
            {
              ErrCnt[Defect] = ErrCnt[Defect] + 1;
              ErrCnt[Defect] = ErrCnt[Defect] + 1;
              BadCond (Defect, "Multiplication does not commute!\n");
              BadCond (Defect, "Multiplication does not commute!\n");
              printf ("\tComparison alleges that 1 * Z = %s\n", Random2.str());
              printf ("\tComparison alleges that 1 * Z = %s\n", Random2.str());
              printf ("\tdiffers from Z * 1 = %s\n", Random1.str());
              printf ("\tdiffers from Z * 1 = %s\n", Random1.str());
            }
            }
          Pause ();
          Pause ();
        }
        }
    }
    }
}
}
 
 
template<typename FLOAT>
template<typename FLOAT>
void
void
Paranoia<FLOAT>::notify (const char *s)
Paranoia<FLOAT>::notify (const char *s)
{
{
  printf ("%s test appears to be inconsistent...\n", s);
  printf ("%s test appears to be inconsistent...\n", s);
  printf ("   PLEASE NOTIFY KARPINKSI!\n");
  printf ("   PLEASE NOTIFY KARPINKSI!\n");
}
}
 
 
/* ====================================================================== */
/* ====================================================================== */
 
 
int main(int ac, char **av)
int main(int ac, char **av)
{
{
  setbuf(stdout, NULL);
  setbuf(stdout, NULL);
  setbuf(stderr, NULL);
  setbuf(stderr, NULL);
 
 
  while (1)
  while (1)
    switch (getopt (ac, av, "pvg:fdl"))
    switch (getopt (ac, av, "pvg:fdl"))
      {
      {
      case -1:
      case -1:
        return 0;
        return 0;
      case 'p':
      case 'p':
        do_pause = true;
        do_pause = true;
        break;
        break;
      case 'v':
      case 'v':
        verbose = true;
        verbose = true;
        break;
        break;
      case 'g':
      case 'g':
        {
        {
          static const struct {
          static const struct {
            const char *name;
            const char *name;
            const struct real_format *fmt;
            const struct real_format *fmt;
          } fmts[] = {
          } fmts[] = {
#define F(x) { #x, &x##_format }
#define F(x) { #x, &x##_format }
            F(ieee_single),
            F(ieee_single),
            F(ieee_double),
            F(ieee_double),
            F(ieee_extended_motorola),
            F(ieee_extended_motorola),
            F(ieee_extended_intel_96),
            F(ieee_extended_intel_96),
            F(ieee_extended_intel_128),
            F(ieee_extended_intel_128),
            F(ibm_extended),
            F(ibm_extended),
            F(ieee_quad),
            F(ieee_quad),
            F(vax_f),
            F(vax_f),
            F(vax_d),
            F(vax_d),
            F(vax_g),
            F(vax_g),
            F(i370_single),
            F(i370_single),
            F(i370_double),
            F(i370_double),
            F(c4x_single),
            F(c4x_single),
            F(c4x_extended),
            F(c4x_extended),
            F(real_internal),
            F(real_internal),
#undef F
#undef F
          };
          };
 
 
          int i, n = sizeof (fmts)/sizeof(*fmts);
          int i, n = sizeof (fmts)/sizeof(*fmts);
 
 
          for (i = 0; i < n; ++i)
          for (i = 0; i < n; ++i)
            if (strcmp (fmts[i].name, optarg) == 0)
            if (strcmp (fmts[i].name, optarg) == 0)
              break;
              break;
 
 
          if (i == n)
          if (i == n)
            {
            {
              printf ("Unknown implementation \"%s\"; "
              printf ("Unknown implementation \"%s\"; "
                      "available implementations:\n", optarg);
                      "available implementations:\n", optarg);
              for (i = 0; i < n; ++i)
              for (i = 0; i < n; ++i)
                printf ("\t%s\n", fmts[i].name);
                printf ("\t%s\n", fmts[i].name);
              return 1;
              return 1;
            }
            }
 
 
          // We cheat and use the same mode all the time, but vary
          // We cheat and use the same mode all the time, but vary
          // the format used for that mode.
          // the format used for that mode.
          real_format_for_mode[int(real_c_float::MODE) - int(QFmode)]
          real_format_for_mode[int(real_c_float::MODE) - int(QFmode)]
            = fmts[i].fmt;
            = fmts[i].fmt;
 
 
          Paranoia<real_c_float>().main();
          Paranoia<real_c_float>().main();
          break;
          break;
        }
        }
 
 
      case 'f':
      case 'f':
        Paranoia < native_float<float> >().main();
        Paranoia < native_float<float> >().main();
        break;
        break;
      case 'd':
      case 'd':
        Paranoia < native_float<double> >().main();
        Paranoia < native_float<double> >().main();
        break;
        break;
      case 'l':
      case 'l':
#ifndef NO_LONG_DOUBLE
#ifndef NO_LONG_DOUBLE
        Paranoia < native_float<long double> >().main();
        Paranoia < native_float<long double> >().main();
#endif
#endif
        break;
        break;
 
 
      case '?':
      case '?':
        puts ("-p\tpause between pages");
        puts ("-p\tpause between pages");
        puts ("-g<FMT>\treal.c implementation FMT");
        puts ("-g<FMT>\treal.c implementation FMT");
        puts ("-f\tnative float");
        puts ("-f\tnative float");
        puts ("-d\tnative double");
        puts ("-d\tnative double");
        puts ("-l\tnative long double");
        puts ("-l\tnative long double");
        return 0;
        return 0;
      }
      }
}
}
 
 
/* GCC stuff referenced by real.o.  */
/* GCC stuff referenced by real.o.  */
 
 
extern "C" void
extern "C" void
fancy_abort ()
fancy_abort ()
{
{
  abort ();
  abort ();
}
}
 
 
int target_flags = 0;
int target_flags = 0;
 
 
extern "C" int
extern "C" int
floor_log2_wide (unsigned HOST_WIDE_INT x)
floor_log2_wide (unsigned HOST_WIDE_INT x)
{
{
  int log = -1;
  int log = -1;
  while (x != 0)
  while (x != 0)
    log++,
    log++,
    x >>= 1;
    x >>= 1;
  return log;
  return log;
}
}
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.