📄 eparanoi.c
字号:
/* paranoia.c arithmetic tester
*
* This is an implementation of the PARANOIA program. It substitutes
* subroutine calls for ALL floating point arithmetic operations.
* This permits you to substitute your own experimental versions of
* arithmetic routines. It also defeats compiler optimizations,
* so for native arithmetic you can be pretty sure you are testing
* the arithmetic and not the compiler.
*
* This version of PARANOIA omits the display of division by zero.
* It also omits the test for extra precise subexpressions, since
* they cannot occur in this context. Otherwise it includes all the
* tests of the 27 Jan 86 distribution, plus a few additional tests.
* Commentary has been reduced to a minimum in order to make the program
* smaller.
*
* The original PARANOIA program, written by W. Kahan, C version
* by Thos Sumner and David Gay, can be downloaded free from the
* Internet NETLIB. An MSDOS disk can be obtained for $15 from:
* Richard Karpinski
* 6521 Raymond Street
* Oakland, CA 94609
*
* Steve Moshier, 28 Oct 88
* last rev: 23 May 92
*/
#define DEBUG 0
/* To use the native arithmetic of the computer, define NATIVE
* to be 1. To use your own supplied arithmetic routines, NATIVE is 0.
*/
#define NATIVE 0
/* gcc real.c interface */
#define L128DOUBLE 0
#include <stdio.h>
/* Data structure of floating point number. If NATIVE was
* selected above, you can define LDOUBLE 1 to test 80-bit long double
* precision or define it 0 to test 64-bit double precision.
*/
#define LDOUBLE 0
#if NATIVE
#define NE 1
#if LDOUBLE
#define FSIZE long double
#define FLOAT(x) FSIZE x[NE]
static FSIZE eone[NE] = {1.0L}; /* The constant 1.0 */
#define ZSQRT sqrtl
#define ZLOG logl
#define ZFLOOR floorl
#define ZPOW powl
long double sqrtl(), logl(), floorl(), powl();
#define FSETUP einit
#else /* not LDOUBLE */
#define FSIZE double
#define FLOAT(x) FSIZE x[NE]
static FSIZE eone[NE] = {1.0}; /* The constant 1.0 */
#define ZSQRT sqrt
#define ZLOG log
#define ZFLOOR floor
#define ZPOW pow
double sqrt(), log(), floor(), pow();
/* Coprocessor initialization,
* defeat underflow trap or what have you.
* This is required mainly on i386 and 68K processors.
*/
#define FSETUP dprec
#endif /* double, not LDOUBLE */
#else /* not NATIVE */
/* Setup for extended double type.
* Put NE = 10 for real.c operating with TFmode support (16-byte reals)
* Put NE = 6 for real.c operating with XFmode support (10- or 12-byte reals)
* The value of NE must agree with that in ehead.h, if ieee.c is used.
*/
#define NE 6
#define FSIZE unsigned short
#define FLOAT(x) unsigned short x[NE]
extern unsigned short eone[];
#define FSETUP einit
/* default for FSETUP */
/*
einit()
{}
*/
error(s)
char *s;
{
printf( "error: %s\n", s );
}
#endif /* not NATIVE */
#if L128DOUBLE
/* real.c interface */
#undef FSETUP
#define FSETUP efsetup
FLOAT(enone);
#define ONE enone
/* Use emov to convert from widest type to widest type, ... */
/*
#define ENTOE emov
#define ETOEN emov
*/
/* ... else choose e24toe, e53toe, etc. */
#define ENTOE e64toe
#define ETOEN etoe64
#define NNBITS 64
#define NIBITS ((NE-1)*16)
extern int rndprc;
efsetup()
{
rndprc = NNBITS;
ETOEN(eone, enone);
}
add(a,b,c)
FLOAT(a);
FLOAT(b);
FLOAT(c);
{
unsigned short aa[10], bb[10], cc[10];
ENTOE(a,aa);
ENTOE(b,bb);
eadd(aa,bb,cc);
ETOEN(cc,c);
}
sub(a,b,c)
FLOAT(a);
FLOAT(b);
FLOAT(c);
{
unsigned short aa[10], bb[10], cc[10];
ENTOE(a,aa);
ENTOE(b,bb);
esub(aa,bb,cc);
ETOEN(cc,c);
}
mul(a,b,c)
FLOAT(a);
FLOAT(b);
FLOAT(c);
{
unsigned short aa[10], bb[10], cc[10];
ENTOE(a,aa);
ENTOE(b,bb);
emul(aa,bb,cc);
ETOEN(cc,c);
}
div(a,b,c)
FLOAT(a);
FLOAT(b);
FLOAT(c);
{
unsigned short aa[10], bb[10], cc[10];
ENTOE(a,aa);
ENTOE(b,bb);
ediv(aa,bb,cc);
ETOEN(cc,c);
}
int cmp(a,b)
FLOAT(a);
FLOAT(b);
{
unsigned short aa[10], bb[10];
int c;
int ecmp();
ENTOE(a,aa);
ENTOE(b,bb);
c = ecmp(aa,bb);
return(c);
}
mov(a,b)
FLOAT(a);
FLOAT(b);
{
int i;
for( i=0; i<NE; i++ )
b[i] = a[i];
}
neg(a)
FLOAT(a);
{
unsigned short aa[10];
ENTOE(a,aa);
eneg(aa);
ETOEN(aa,a);
}
clear(a)
FLOAT(a);
{
int i;
for( i=0; i<NE; i++ )
a[i] = 0;
}
FABS(a)
FLOAT(a);
{
unsigned short aa[10];
ENTOE(a,aa);
eabs(aa);
ETOEN(aa,a);
}
FLOOR(a,b)
FLOAT(a);
FLOAT(b);
{
unsigned short aa[10], bb[10];
ENTOE(a,aa);
efloor(aa,bb);
ETOEN(bb,b);
}
LOG(a,b)
FLOAT(a);
FLOAT(b);
{
unsigned short aa[10], bb[10];
int rndsav;
ENTOE(a,aa);
rndsav = rndprc;
rndprc = NIBITS;
elog(aa,bb);
rndprc = rndsav;
ETOEN(bb,b);
}
POW(a,b,c)
FLOAT(a);
FLOAT(b);
FLOAT(c);
{
unsigned short aa[10], bb[10], cc[10];
int rndsav;
ENTOE(a,aa);
ENTOE(b,bb);
rndsav = rndprc;
rndprc = NIBITS;
epow(aa,bb,cc);
rndprc = rndsav;
ETOEN(cc,c);
}
SQRT(a,b)
FLOAT(a);
FLOAT(b);
{
unsigned short aa[10], bb[10];
ENTOE(a,aa);
esqrt(aa,bb);
ETOEN(bb,b);
}
FTOL(x,ip,f)
FLOAT(x);
long *ip;
FLOAT(f);
{
unsigned short xx[10], ff[10];
ENTOE(x,xx);
eifrac(xx,ip,ff);
ETOEN(ff,f);
}
LTOF(ip,x)
long *ip;
FLOAT(x);
{
unsigned short xx[10];
ltoe(ip,xx);
ETOEN(xx,x);
}
TOASC(a,b,c)
FLOAT(a);
int b;
char *c;
{
unsigned short xx[10];
ENTOE(a,xx);
etoasc(xx,b,c);
}
#else /* not L128DOUBLE */
#define ONE eone
/* Note all arguments of operation subroutines are pointers. */
/* c = b + a */
#define add(a,b,c) eadd(a,b,c)
/* c = b - a */
#define sub(a,b,c) esub(a,b,c)
/* c = b * a */
#define mul(a,b,c) emul(a,b,c)
/* c = b / a */
#define div(a,b,c) ediv(a,b,c)
/* 1 if a>b, 0 if a==b, -1 if a<b */
#define cmp(a,b) ecmp(a,b)
/* b = a */
#define mov(a,b) emov(a,b)
/* a = -a */
#define neg(a) eneg(a)
/* a = 0 */
#define clear(a) eclear(a)
#define FABS(x) eabs(x)
#define FLOOR(x,y) efloor(x,y)
#define LOG(x,y) elog(x,y)
#define POW(x,y,z) epow(x,y,z)
#define SQRT(x,y) esqrt(x,y)
/* x = &FLOAT input, i = &long integer part, f = &FLOAT fractional part */
#define FTOL(x,i,f) eifrac(x,i,f)
/* i = &long integer input, x = &FLOAT output */
#define LTOF(i,x) ltoe(i,x)
/* Convert FLOAT a to decimal ASCII string with b digits */
#define TOASC(a,b,c) etoasc(a,b,c)
#endif /* not L128DOUBLE */
/* The following subroutines are implementations of the above
* named functions, using the native or default arithmetic.
*/
#if NATIVE
eadd(a,b,c)
FSIZE *a, *b, *c;
{
*c = *b + *a;
}
esub(a,b,c)
FSIZE *a, *b, *c;
{
*c = *b - *a;
}
emul(a,b,c)
FSIZE *a, *b, *c;
{
*c = (*b) * (*a);
}
ediv(a,b,c)
FSIZE *a, *b, *c;
{
*c = (*b) / (*a);
}
/* Important note: comparison can be done by subracting
* or by a compare instruction that may or may not be
* equivalent to subtracting.
*/
ecmp(a,b)
FSIZE *a, *b;
{
if( (*a) > (*b) )
return( 1 );
if( (*a) < (*b) )
return( -1 );
if( (*a) != (*b) )
goto cmpf;
if( (*a) == (*b) )
return( 0 );
cmpf:
printf( "Compare fails\n" );
return(0);
}
emov( a, b )
FSIZE *a, *b;
{
*b = *a;
}
eneg( a )
FSIZE *a;
{
*a = -(*a);
}
eclear(a)
FSIZE *a;
{
*a = 0.0;
}
eabs(x)
FSIZE *x;
{
if( (*x) < 0.0 )
*x = -(*x);
}
efloor(x,y)
FSIZE *x, *y;
{
*y = (FSIZE )ZFLOOR( *x );
}
elog(x,y)
FSIZE *x, *y;
{
*y = (FSIZE )ZLOG( *x );
}
epow(x,y,z)
FSIZE *x, *y, *z;
{
*z = (FSIZE )ZPOW( *x, *y );
}
esqrt(x,y)
FSIZE *x, *y;
{
*y = (FSIZE )ZSQRT( *x );
}
eifrac(x,i,f)
FSIZE *x;
long *i;
FSIZE *f;
{
FSIZE y;
y = (FSIZE )ZFLOOR( *x );
if( y < 0.0 )
{
*f = y - *x;
*i = -y;
}
else
{
*f = *x - y;
*i = y;
}
}
ltoe(i,x)
long *i;
FSIZE *x;
{
*x = *i;
}
etoasc(a,str,n)
FSIZE *a;
char *str;
int n;
{
double x;
x = (double )(*a);
sprintf( str, " %.17e ", x );
}
/* default for FSETUP */
einit()
{}
#endif /* NATIVE */
FLOAT(Radix);
FLOAT(BInvrse);
FLOAT(RadixD2);
FLOAT(BMinusU2);
/*Small floating point constants.*/
FLOAT(Zero);
FLOAT(Half);
FLOAT(One);
FLOAT(Two);
FLOAT(Three);
FLOAT(Four);
FLOAT(Five);
FLOAT(Six);
FLOAT(Eight);
FLOAT(Nine);
FLOAT(Ten);
FLOAT(TwentySeven);
FLOAT(ThirtyTwo);
FLOAT(TwoForty);
FLOAT(MinusOne );
FLOAT(OneAndHalf);
/*Integer constants*/
int NoTrials = 20; /*Number of tests for commutativity. */
#define False 0
#define True 1
/* Definitions for declared types
Guard == (Yes, No);
Rounding == (Chopped, Rounded, Other);
Message == packed array [1..40] of char;
Class == (Flaw, Defect, Serious, Failure);
*/
#define Yes 1
#define No 0
#define Chopped 2
#define Rounded 1
#define Other 0
#define Flaw 3
#define Defect 2
#define Serious 1
#define Failure 0
typedef int Guard, Rounding, Class;
typedef char Message;
/* Declarations of Variables */
FLOAT(AInvrse);
FLOAT(A1);
FLOAT(C);
FLOAT(CInvrse);
FLOAT(D);
FLOAT(FourD);
FLOAT(E0);
FLOAT(E1);
FLOAT(Exp2);
FLOAT(E3);
FLOAT(MinSqEr);
FLOAT(SqEr);
FLOAT(MaxSqEr);
FLOAT(E9);
FLOAT(Third);
FLOAT(F6);
FLOAT(F9);
FLOAT(H);
FLOAT(HInvrse);
FLOAT(StickyBit);
FLOAT(J);
FLOAT(MyZero);
FLOAT(Precision);
FLOAT(Q);
FLOAT(Q9);
FLOAT(R);
FLOAT(Random9);
FLOAT(T);
FLOAT(Underflow);
FLOAT(S);
FLOAT(OneUlp);
FLOAT(UfThold);
FLOAT(U1);
FLOAT(U2);
FLOAT(V);
FLOAT(V0);
FLOAT(V9);
FLOAT(W);
FLOAT(X);
FLOAT(X1);
FLOAT(X2);
FLOAT(X8);
FLOAT(Random1);
FLOAT(Y);
FLOAT(YY1);
FLOAT(Y2);
FLOAT(Random2);
FLOAT(Z);
FLOAT(PseudoZero);
FLOAT(Z1);
FLOAT(Z2);
FLOAT(Z9);
static FLOAT(t);
FLOAT(t2);
FLOAT(Sqarg);
int ErrCnt[4];
int fpecount;
int Milestone;
int PageNo;
int I, M, N, N1, stkflg;
Guard GMult, GDiv, GAddSub;
Rounding RMult, RDiv, RAddSub, RSqrt;
int Break, Done, NotMonot, Monot, Anomaly, IEEE;
int SqRWrng, UfNGrad;
int k, k2;
int Indx;
char ch[8];
long lngint, lng2; /* intermediate for conversion between int and FLOAT */
/* Computed constants. */
/*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 */
show( x )
short x[];
{
int i;
char s[80];
/* Number of 16-bit groups to display */
#if NATIVE
#if LDOUBLE
#define NPRT (sizeof( long double )/2)
#else
#define NPRT (sizeof( double )/2)
#endif
#else
#define NPRT NE
#endif
TOASC( x, s, 70 );
printf( "%s\n", s );
for( i=0; i<NPRT; i++ )
printf( "%04x ", x[i] & 0xffff );
printf( "\n" );
}
/* define NOSIGNAL */
#ifndef NOSIGNAL
#include <signal.h>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -