diff options
Diffstat (limited to 'test/math/eparanoi.c')
-rw-r--r-- | test/math/eparanoi.c | 3550 |
1 files changed, 0 insertions, 3550 deletions
diff --git a/test/math/eparanoi.c b/test/math/eparanoi.c deleted file mode 100644 index 84cab73f8..000000000 --- a/test/math/eparanoi.c +++ /dev/null @@ -1,3550 +0,0 @@ -/* 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> -#endif -#include <setjmp.h> -jmp_buf ovfl_buf; -/*typedef int (*Sig_type)();*/ -typedef void (*Sig_type)(); -Sig_type sigsave; - -/* Floating point exception receiver */ -void sigfpe() -{ -fpecount++; -printf( "\n* * * FLOATING-POINT ERROR * * *\n" ); -/* reinitialize the floating point unit */ -FSETUP(); -fflush(stdout); -if( sigsave ) - { -#ifndef NOSIGNAL - signal( SIGFPE, sigsave ); -#endif - sigsave = 0; - longjmp( ovfl_buf, 1 ); - } -abort(); -} - - -main() -{ - -/* Do coprocessor or other initializations */ -FSETUP(); - -printf( - "This version of paranoia omits test for extra precise subexpressions\n" ); -printf( "and includes a few additional tests.\n" ); - -clear(Zero); -printf( "0 = " ); -show( Zero ); -mov( ONE, One); -printf( "1 = " ); -show( One ); -add( One, One, Two ); -printf( "1+1 = " ); -show( Two ); -add( Two, One, Three ); -add( Three, One, Four ); -add( Four, One, Five ); -add( Five, One, Six ); -add( Four, Four, Eight ); -mul( Three, Three, Nine ); -add( Nine, One, Ten ); -mul( Nine, Three, TwentySeven ); -mul( Four, Eight, ThirtyTwo ); -mul( Four, Five, t ); -mul( t, Three, t ); -mul( t, Four, TwoForty ); -mov( One, MinusOne ); -neg( MinusOne ); -div( Two, One, Half ); -add( One, Half, OneAndHalf ); -ErrCnt[Failure] = 0; -ErrCnt[Serious] = 0; -ErrCnt[Defect] = 0; -ErrCnt[Flaw] = 0; -PageNo = 1; -#ifndef NOSIGNAL -signal( SIGFPE, sigfpe ); -#endif -printf("Program is now RUNNING tests on small integers:\n"); - -add( Zero, Zero, t ); -if( cmp( t, Zero ) != 0) - { - printf( "0+0 != 0\n" ); - ErrCnt[Failure] += 1; - } -sub( One, One, t ); -if( cmp( t, Zero ) != 0 ) - { - printf( "1-1 != 0\n" ); - ErrCnt[Failure] += 1; - } -if( cmp( One, Zero ) <= 0 ) - { - printf( "1 <= 0\n" ); - ErrCnt[Failure] += 1; - } -add( One, One, t ); -if( cmp( t, Two ) != 0 ) - { - printf( "1+1 != 2\n" ); - ErrCnt[Failure] += 1; - } -mov( Zero, Z ); -neg( Z ); -FLOOR( Z, t ); -if( cmp(t,Zero) != 0 ) - { - ErrCnt[Serious] += 1; - printf( "FLOOR(-0) should equal 0, is = " ); - show( t ); - } -if( cmp(Z, Zero) != 0) - { - ErrCnt[Failure] += 1; - printf("Comparison alleges that -0.0 is Non-zero!\n"); - } -else - { - div( TwoForty, One, U1 ); /* U1 = 0.001 */ - mov( One, Radix ); - TstPtUf(); - } -add( Two, One, t ); -if( cmp( t, Three ) != 0 ) - { - printf( "2+1 != 3\n" ); - ErrCnt[Failure] += 1; - } -add( Three, One, t ); -if( cmp( t, Four ) != 0 ) - { - printf( "3+1 != 4\n" ); - ErrCnt[Failure] += 1; - } -mov( Two, t ); -neg( t ); -mul( Two, t, t ); -add( Four, t, t ); -if( cmp( t, Zero ) != 0 ) - { - printf( "4+2*(-2) != 0\n" ); - ErrCnt[Failure] += 1; - } -sub( Three, Four, t ); -sub( One, t, t ); -if( cmp( t, Zero ) != 0 ) - { - printf( "4-3-1 != 0\n" ); - ErrCnt[Failure] += 1; - } - sub( One, Zero, t ); -if( cmp( t, MinusOne ) != 0 ) - { - printf( "-1 != 0-1\n" ); - ErrCnt[Failure] += 1; - } -add( One, MinusOne, t ); -if( cmp( t, Zero ) != 0 ) - { - printf( "1+(-1) != 0\n" ); - ErrCnt[Failure] += 1; - } -mov( One, t ); -FABS( t ); -add( MinusOne, t, t ); -if( cmp( t, Zero ) != 0 ) - { - printf( "-1+abs(1) != 0\n" ); - ErrCnt[Failure] += 1; - } -mul( MinusOne, MinusOne, t ); -add( MinusOne, t, t ); -if( cmp( t, Zero ) != 0 ) - { - printf( "-1+(-1)*(-1) != 0\n" ); - ErrCnt[Failure] += 1; - } -add( Half, MinusOne, t ); -add( Half, t, t ); -if( cmp( t, Zero ) != 0 ) - { - printf( "1/2 + (-1) + 1/2 != 0\n" ); - ErrCnt[Failure] += 1; - } -Milestone = 10; -mul( Three, Three, t ); -if( cmp( t, Nine ) != 0 ) - { - printf( "3*3 != 9\n" ); - ErrCnt[Failure] += 1; - } -mul( Nine, Three, t ); -if( cmp( t, TwentySeven ) != 0 ) - { - printf( "3*9 != 27\n" ); - ErrCnt[Failure] += 1; - } -add( Four, Four, t ); -if( cmp( t, Eight ) != 0 ) - { - printf( "4+4 != 8\n" ); - ErrCnt[Failure] += 1; - } -mul( Eight, Four, t ); -if( cmp( t, ThirtyTwo ) != 0 ) - { - printf( "8*4 != 32\n" ); - ErrCnt[Failure] += 1; - } -sub( TwentySeven, ThirtyTwo, t ); -sub( Four, t, t ); -sub( One, t, t ); -if( cmp( t, Zero ) != 0 ) - { - printf( "32-27-4-1 != 0\n" ); - ErrCnt[Failure] += 1; - } -add( Four, One, t ); -if( cmp( t, Five ) != 0 ) - { - printf( "4+1 != 5\n" ); - ErrCnt[Failure] += 1; - } -mul( Four, Five, t ); -mul( Three, t, t ); -mul( Four, t, t ); -if( cmp( t, TwoForty ) != 0 ) - { - printf( "4*5*3*4 != 240\n" ); - ErrCnt[Failure] += 1; - } -div( Three, TwoForty, t ); -mul( Four, Four, t2 ); -mul( Five, t2, t2 ); -sub( t2, t2, t ); -if( cmp( t, Zero ) != 0 ) - { - printf( "240/3 - 4*4*5 != 0\n" ); - ErrCnt[Failure] += 1; - } -div( Four, TwoForty, t ); -mul( Five, Three, t2 ); -mul( Four, t2, t2 ); -sub( t2, t, t ); -if( cmp( t, Zero ) != 0 ) - { - printf( "240/4 - 5*3*4 != 0\n" ); - ErrCnt[Failure] += 1; - } -div( Five, TwoForty, t ); -mul( Four, Three, t2 ); -mul( Four, t2, t2 ); -sub( t2, t, t ); -if( cmp( t, Zero ) != 0 ) - { - printf( "240/5 - 4*3*4 != 0\n" ); - ErrCnt[Failure] += 1; - } -if(ErrCnt[Failure] == 0) - { -printf("-1, 0, 1/2, 1, 2, 3, 4, 5, 9, 27, 32 & 240 are O.K.\n\n"); - } -printf("Searching for Radix and Precision.\n"); -mov( One, W ); -do - { - add( W, W, W ); - add( W, One, Y ); - sub( W, Y, Z ); - sub( One, Z, Y ); - mov( Y, t ); - FABS(t); - add( MinusOne, t, t ); - k = cmp( t, Zero ); - } -while( k < 0 ); -/*.. now W is just big enough that |((W+1)-W)-1| >= 1 ...*/ -mov( Zero, Precision ); -mov( One, Y ); -do - { - add( W, Y, Radix ); - add( Y, Y, Y ); - sub( W, Radix, Radix ); - k = cmp( Radix, Zero ); - } -while( k == 0); - -if( cmp(Radix, Two) < 0 ) - mov( One, Radix ); -printf("Radix = " ); -show( Radix ); -if( cmp(Radix, One) != 0) - { - mov( One, W ); - do - { - add( One, Precision, Precision ); - mul( W, Radix, W ); - add( W, One, Y ); - sub( W, Y, t ); - k = cmp( t, One ); - } - while( k == 0 ); - } -/* now W == Radix^Precision is barely too big to satisfy (W+1)-W == 1 */ -div( W, One, U1 ); -mul( Radix, U1, U2 ); -printf( "Closest relative separation found is U 1 = " ); -show( U1 ); -printf( "Recalculating radix and precision." ); - -/*save old values*/ -mov( Radix, E0 ); -mov( U1, E1 ); -mov( U2, E9 ); -mov( Precision, E3 ); - -div( Three, Four, X ); -sub( One, X, Third ); -sub( Third, Half, F6 ); -add( F6, F6, X ); -sub( Third, X, X ); -FABS( X ); -if( cmp(X, U2) < 0 ) - mov( U2, X ); - -/*... now X = (unknown no.) ulps of 1+...*/ -do - { - mov( X, U2 ); -/* Y = Half * U2 + ThirtyTwo * U2 * U2; */ - mul( ThirtyTwo, U2, t ); - mul( t, U2, t ); - mul( Half, U2, Y ); - add( t, Y, Y ); - add( One, Y, Y ); - sub( One, Y, X ); - k = cmp( U2, X ); - k2 = cmp( X, Zero ); - } -while ( ! ((k <= 0) || (k2 <= 0))); - -/*... now U2 == 1 ulp of 1 + ... */ -div( Three, Two, X ); -sub( Half, X, F6 ); -add( F6, F6, Third ); -sub( Half, Third, X ); -add( F6, X, X ); -FABS( X ); -if( cmp(X, U1) < 0 ) - mov( U1, X ); - -/*... now X == (unknown no.) ulps of 1 -... */ -do - { - mov( X, U1 ); - /* Y = Half * U1 + ThirtyTwo * U1 * U1;*/ - mul( ThirtyTwo, U1, t ); - mul( U1, t, t ); - mul( Half, U1, Y ); - add( t, Y, Y ); - sub( Y, Half, Y ); - add( Half, Y, X ); - sub( X, Half, Y ); - add( Half, Y, X ); - k = cmp( U1, X ); - k2 = cmp( X, Zero ); - } while ( ! ((k <= 0) || (k2 <= 0))); -/*... now U1 == 1 ulp of 1 - ... */ -if( cmp( U1, E1 ) == 0 ) - printf("confirms closest relative separation U1 .\n"); -else - { - printf("gets better closest relative separation U1 = " ); - show( U1 ); - } -div( U1, One, W ); -sub( U1, Half, F9 ); -add( F9, Half, F9 ); -div( U1, U2, t ); -div( TwoForty, One, t2 ); -add( t2, t, t ); -FLOOR( t, Radix ); -if( cmp(Radix, E0) == 0 ) - printf("Radix confirmed.\n"); -else - { - printf("MYSTERY: recalculated Radix = " ); - show( Radix ); - mov( E0, Radix ); - } -add( Eight, Eight, t ); -if( cmp( Radix, t ) > 0 ) - { - printf( "Radix is too big: roundoff problems\n" ); - ErrCnt[Defect] += 1; - } -k = 1; -if( cmp( Radix, Two ) == 0 ) - k = 0; -if( cmp( Radix, Ten ) == 0 ) - k = 0; -if( cmp( Radix, One ) == 0 ) - k = 0; -if( k != 0 ) - { - printf( "Radix is not as good as 2 or 10\n" ); - ErrCnt[Flaw] += 1; - } -/*=============================================*/ -Milestone = 20; -/*=============================================*/ -sub( Half, F9, t ); -if( cmp( t, Half ) >= 0 ) - { - printf( "(1-U1)-1/2 < 1/2 is FALSE, prog. fails?\n" ); - ErrCnt[Failure] += 1; - } -mov( F9, X ); -I = 1; -sub( Half, X, Y ); -sub( Half, Y, Z ); -if( (cmp( X, One ) == 0) && (cmp( Z, Zero) != 0) ) - { - printf( "Comparison is fuzzy ,X=1 but X-1/2-1/2 != 0\n" ); - ErrCnt[Failure] += 1; - } -add( One, U2, X ); -I = 0; -/*=============================================*/ -Milestone = 25; -/*=============================================*/ -/*... BMinusU2 = nextafter(Radix, 0) */ - -sub( One, Radix, BMinusU2 ); -sub( U2, BMinusU2, t ); -add( One, t, BMinusU2 ); -/* Purify Integers */ -if( cmp(Radix,One) != 0 ) - { -/*X = - TwoForty * LOG(U1) / LOG(Radix);*/ - LOG( U1, X ); - LOG( Radix, t ); - div( t, X, X ); - mul( TwoForty, X, X ); - neg( X ); - - add( Half, X, Y ); - FLOOR( Y, Y ); - sub( Y, X, t ); - FABS( t ); - mul( Four, t, t ); - if( cmp( t, One ) < 0 ) - mov( Y, X ); - div( TwoForty, X, Precision ); - add( Half, Precision, Y ); - FLOOR( Y, Y ); - sub( Y, Precision, t ); - FABS( t ); - mul( TwoForty, t, t ); - if( cmp( t, Half ) < 0 ) - mov( Y, Precision ); - } -FLOOR( Precision, t ); -if( (cmp( Precision, t ) != 0) || (cmp( Radix, One ) == 0) ) - { - printf("Precision cannot be characterized by an Integer number\n"); - printf("of significant digits but, by itself, this is a minor flaw.\n"); - } -if( cmp(Radix, One) == 0 ) - printf("logarithmic encoding has precision characterized solely by U1.\n"); -else - { - printf("The number of significant digits of the Radix is " ); - show( Precision ); - } -mul( U2, Nine, t ); -mul( Nine, t, t ); -mul( TwoForty, t, t ); -if( cmp( t, One ) >= 0 ) - { - printf( "Precision worse than 5 decimal figures\n" ); - ErrCnt[Serious] += 1; - } -/*=============================================*/ -Milestone = 30; -/*=============================================*/ -/* Test for extra-precise subepressions has been deleted. */ -Milestone = 35; -/*=============================================*/ -if( cmp(Radix,Two) >= 0 ) - { - mul( Radix, Radix, t ); - div( t, W, X ); - add( X, One, Y ); - sub( X, Y, Z ); - add( Z, U2, T ); - sub( Z, T, X ); - if( cmp( X, U2 ) != 0 ) - { - printf( "Subtraction is not normalized X=Y,X+Z != Y+Z!\n" ); - ErrCnt[Failure] += 1; - } - if( cmp(X,U2) == 0 ) - printf("Subtraction appears to be normalized, as it should be."); - } - -printf("\nChecking for guard digit in *, /, and -.\n"); -mul( F9, One, Y ); -mul( One, F9, Z ); -sub( Half, F9, X ); -sub( Half, Y, Y ); -sub( X, Y, Y ); -sub( Half, Z, Z ); -sub( X, Z, Z ); -add( One, U2, X ); -mul( X, Radix, T ); -mul( Radix, X, R ); -sub( Radix, T, X ); -mul( Radix, U2, t ); -sub( t, X, X ); -sub( Radix, R, T ); -mul( Radix, U2, t ); -sub( t, T, T ); -sub( One, Radix, t ); -mul( t, X, X ); -sub( One, Radix, t ); -mul( t, T, T ); - -k = cmp(X,Zero); -k |= cmp(Y,Zero); -k |= cmp(Z,Zero); -k |= cmp(T,Zero); -if( k == 0 ) - GMult = Yes; -else - { - GMult = No; - ErrCnt[Serious] += 1; - printf( "* lacks a Guard Digit, so 1*X != X\n" ); - } -mul( Radix, U2, Z ); -add( One, Z, X ); -add( X, Z, Y ); -mul( X, X, t ); -sub( t, Y, Y ); -FABS( Y ); -sub( U2, Y, Y ); -sub( U2, One, X ); -sub( U2, X, Z ); -mul( X, X, t ); -sub( t, Z, Z ); -FABS( Z ); -sub( U1, Z, Z ); -if( (cmp(Y,Zero) > 0) || (cmp(Z,Zero) > 0) ) - { - ErrCnt[Failure] += 1; - printf( "* gets too many final digits wrong.\n" ); - } -sub( U2, One, Y ); -add( One, U2, X ); -div( Y, One, Z ); -sub( X, Z, Y ); -div( Three, One, X ); -div( Nine, Three, Z ); -sub( Z, X, X ); -div( TwentySeven, Nine, T ); -sub( T, Z, Z ); -k = cmp( X, Zero ); -k |= cmp( Y, Zero ); -k |= cmp( Z, Zero ); -if( k ) - { - ErrCnt[Defect] += 1; -printf( "Division lacks a Guard Digit, so error can exceed 1 ulp\n" ); -printf( "or 1/3 and 3/9 and 9/27 may disagree\n" ); - } -div( One, F9, Y ); -sub( Half, F9, X ); -sub( Half, Y, Y ); -sub( X, Y, Y ); -add( One, U2, X ); -div( One, X, T ); -sub( X, T, X ); -k = cmp( X, Zero ); -k |= cmp( Y, Zero ); -k |= cmp( Z, Zero ); -if( k == 0 ) - GDiv = Yes; -else - { - GDiv = No; - ErrCnt[Serious] += 1; - printf( "Division lacks a Guard Digit, so X/1 != X\n" ); - } -add( One, U2, X ); -div( X, One, X ); -sub( Half, X, Y ); -sub( Half, Y, Y ); -if( cmp(Y,Zero) >= 0 ) - { - ErrCnt[Serious] += 1; - printf( "Computed value of 1/1.000..1 >= 1\n" ); - } -sub( U2, One, X ); -mul( Radix, U2, Y ); -add( One, Y, Y ); -mul( X, Radix, Z ); -mul( Y, Radix, T ); -div( Radix, Z, R ); -div( Radix, T, StickyBit ); -sub( X, R, X ); -sub( Y, StickyBit, Y ); -k = cmp( X, Zero ); -k |= cmp( Y, Zero ); -if( k ) - { - ErrCnt[Failure] += 1; - printf( "* and/or / gets too many last digits wrong\n" ); - } -sub( U1, One, Y ); -sub( F9, One, X ); -sub( Y, One, Y ); -sub( U2, Radix, T ); -sub( BMinusU2, Radix, Z ); -sub( T, Radix, T ); -k = cmp( X, U1 ); -k |= cmp( Y, U1 ); -k |= cmp( Z, U2 ); -k |= cmp( T, U2 ); -if( k == 0 ) - GAddSub = Yes; -else - { - GAddSub = No; - ErrCnt[Serious] += 1; - printf( "- lacks Guard Digit, so cancellation is obscured\n" ); - } -sub( One, F9, t ); -if( (cmp(F9,One) != 0) && (cmp(t,Zero) >= 0) ) - { - ErrCnt[Serious] += 1; - printf("comparison alleges (1-U1) < 1 although\n"); - printf(" subtration yields (1-U1) - 1 = 0 , thereby vitiating\n"); - printf(" such precautions against division by zero as\n"); - printf(" ... if (X == 1.0) {.....} else {.../(X-1.0)...}\n"); - } -if (GMult == Yes && GDiv == Yes && GAddSub == Yes) - printf(" *, /, and - appear to have guard digits, as they should.\n"); -/*=============================================*/ -Milestone = 40; -/*=============================================*/ -printf("Checking rounding on multiply, divide and add/subtract.\n"); -RMult = Other; -RDiv = Other; -RAddSub = Other; -div( Two, Radix, RadixD2 ); -mov( Two, A1 ); -Done = False; -do - { - mov( Radix, AInvrse ); - do - { - mov( AInvrse, X ); - div( A1, AInvrse, AInvrse ); - FLOOR( AInvrse, t ); - k = cmp( t, AInvrse ); - } - while( ! (k != 0 ) ); - k = cmp( X, One ); - k2 = cmp( A1, Three ); - Done = (k == 0) || (k2 > 0); - if(! Done) - add( Nine, One, A1 ); - } -while( ! (Done)); -if( cmp(X, One) == 0 ) - mov( Radix, A1 ); -div( A1, One, AInvrse ); -mov( A1, X ); -mov( AInvrse, Y ); -Done = False; -do - { - mul( X, Y, Z ); - sub( Half, Z, Z ); - if( cmp( Z, Half ) != 0 ) - { - ErrCnt[Failure] += 1; - printf( "X * (1/X) differs from 1\n" ); - } - k = cmp( X, Radix ); - Done = (k == 0); - mov( Radix, X ); - div( X, One, Y ); - } -while( ! (Done)); - -add( One, U2, Y2 ); -sub( U2, One, YY1 ); -sub( U2, OneAndHalf, X ); -add( OneAndHalf, U2, Y ); -sub( U2, X, Z ); -mul( Z, Y2, Z ); -mul( Y, YY1, T ); -sub( X, Z, Z ); -sub( X, T, T ); -mul( X, Y2, X ); -add( Y, U2, Y ); -mul( Y, YY1, Y ); -sub( OneAndHalf, X, X ); -sub( OneAndHalf, Y, Y ); -k = cmp( X, Zero ); -k |= cmp( Y, Zero ); -k |= cmp( Z, Zero ); -if( cmp( T, Zero ) > 0 ) - k = 1; -if( k == 0 ) - { - add( OneAndHalf, U2, X ); - mul( X, Y2, X ); - sub( U2, OneAndHalf, Y ); - sub( U2, Y, Y ); - add( OneAndHalf, U2, Z ); - add( U2, Z, Z ); - sub( U2, OneAndHalf, T ); - mul( T, YY1, T ); - add( Z, U2, t ); - sub( t, X, X ); - mul( Y, YY1, StickyBit ); - mul( Z, Y2, S ); - sub( Y, T, T ); - sub( Y, U2, Y ); - add( StickyBit, Y, Y ); -/* Z = S - (Z + U2 + U2); */ - add( Z, U2, t ); - add( t, U2, t ); - sub( t, S, Z ); - add( Y2, U2, t ); - mul( t, YY1, StickyBit ); - mul( Y2, YY1, YY1 ); - sub( Y2, StickyBit, StickyBit ); - sub( Half, YY1, YY1 ); - k = cmp( X, Zero ); - k |= cmp( Y, Zero ); - k |= cmp( Z, Zero ); - k |= cmp( T, Zero ); - k |= cmp( StickyBit, Zero ); - k |= cmp( YY1, Half ); - if( k == 0 ) - { - RMult = Rounded; - printf("Multiplication appears to round correctly.\n"); - } - else - { - add( X, U2, t ); - k = cmp( t, Zero ); - if( cmp( Y, Zero ) >= 0 ) - k |= 1; - add( Z, U2, t ); - k |= cmp( t, Zero ); - if( cmp( T, Zero ) >= 0 ) - k |= 1; - add( StickyBit, U2, t ); - k |= cmp( t, Zero ); - if( cmp(YY1, Half) >= 0 ) - k |= 1; - if( k == 0 ) - { - printf("Multiplication appears to chop.\n"); - } - else - { - printf("* is neither chopped nor correctly rounded.\n"); - } - if( (RMult == Rounded) && (GMult == No) ) - printf("Multiplication has inconsistent result"); - } - } -else - printf("* is neither chopped nor correctly rounded.\n"); - -/*============================= |