📄 eparanoi.c
字号:
#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 );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -