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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [contrib/] [paranoia.cc] - Blame information for rev 841

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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