📄 eparanoi.c
字号:
sub( t, Y2, Y2 );
sub( Half, Y, X2 );
div( X2, X8, X2 );
mul( Half, X2, t );
mul( t, X2, t );
sub( t, X2, X2 );
/*SqEr = (Y2 + Half) + (Half - X2);*/
add( Y2, Half, SqEr );
sub( X2, Half, t );
add( t, SqEr, SqEr );
Showsq( -1 );
sub( X2, Y2, SqEr );
Showsq( 1 );
}
}
/* IsYeqX */
IsYeqX()
{
if( cmp(Y,X) != 0 )
{
if (N <= 0)
{
if( (cmp(Z,Zero) == 0) && (cmp(Q,Zero) <= 0) )
printf("WARNING: computing\n");
else
{
ErrCnt[Defect] += 1;
printf( "computing\n");
}
show( Z );
printf( "\tto the power " );
show( Q );
printf("\tyielded " );
show( Y );
printf("\twhich compared unequal to correct " );
show( X );
sub( X, Y, t );
printf("\t\tthey differ by " );
show( t );
}
N = N + 1; /* ... count discrepancies. */
}
}
/* SR3980 */
SR3980()
{
long li;
do
{
/*Q = (FLOAT) I;*/
li = I;
LTOF( &li, Q );
POW( Z, Q, Y );
IsYeqX();
if(++I > M)
break;
mul( Z, X, X );
}
while( cmp(X,W) < 0 );
}
/* PrintIfNPositive */
PrintIfNPositive()
{
if(N > 0)
printf("Similar discrepancies have occurred %d times.\n", N);
}
/* TstPtUf */
TstPtUf()
{
N = 0;
if( cmp(Z,Zero) != 0)
{
printf( "Z = " );
show(Z);
printf("Since comparison denies Z = 0, evaluating ");
printf("(Z + Z) / Z should be safe.\n");
sigsave = sigfpe;
if (setjmp(ovfl_buf))
goto very_serious;
add( Z, Z, Q9 );
div( Z, Q9, Q9 );
printf("What the machine gets for (Z + Z) / Z is " );
show( Q9 );
sub( Two, Q9, t );
FABS(t);
mul( Radix, U2, t2 );
if( cmp(t,t2) < 0 )
{
printf("This is O.K., provided Over/Underflow");
printf(" has NOT just been signaled.\n");
}
else
{
if( (cmp(Q9,One) < 0) || (cmp(Q9,Two) > 0) )
{
very_serious:
N = 1;
ErrCnt [Serious] = ErrCnt [Serious] + 1;
printf("This is a VERY SERIOUS DEFECT!\n");
}
else
{
N = 1;
ErrCnt[Defect] += 1;
printf("This is a DEFECT!\n");
}
}
mul( Z, One, V9 );
mov( V9, Random1 );
mul( One, Z, V9 );
mov( V9, Random2 );
div( One, Z, V9 );
if( (cmp(Z,Random1) == 0) && (cmp(Z,Random2) == 0)
&& (cmp(Z,V9) == 0) )
{
if (N > 0)
Pause();
}
else
{
N = 1;
ErrCnt[Defect] += 1;
printf( "What prints as Z = ");
show( Z );
printf( "\tcompares different from " );
if( cmp(Z,Random1) != 0)
{
printf("Z * 1 = " );
show( Random1 );
}
if( (cmp(Z,Random2) != 0)
|| (cmp(Random2,Random1) != 0) )
{
printf("1 * Z == " );
show( Random2 );
}
if( cmp(Z,V9) != 0 )
{
printf("Z / 1 = " );
show( V9 );
}
if( cmp(Random2,Random1) != 0 )
{
ErrCnt[Defect] += 1;
printf( "Multiplication does not commute!\n");
printf("\tComparison alleges that 1 * Z = " );
show(Random2);
printf("\tdiffers from Z * 1 = " );
show(Random1);
}
Pause();
}
}
}
Pause()
{
}
Sign( x, y )
FSIZE *x, *y;
{
if( cmp( x, Zero ) < 0 )
{
mov( One, y );
neg( y );
}
else
{
mov( One, y );
}
}
sqtest()
{
printf("\nRunning test of square root(x).\n");
RSqrt = Other;
k = 0;
SQRT( Zero, t );
k |= cmp( Zero, t );
mov( Zero, t );
neg(t);
SQRT( t, t2 );
k |= cmp( t, t2 );
SQRT( One, t );
k |= cmp( One, t );
if( k != 0 )
{
ErrCnt[Failure] += 1;
printf( "Square root of 0.0, -0.0 or 1.0 wrong\n");
}
mov( Zero, MinSqEr );
mov( Zero, MaxSqEr );
mov( Zero, J );
mov( Radix, X );
mov( U2, OneUlp );
SqXMinX( Serious );
mov( BInvrse, X );
mul( BInvrse, U1, OneUlp );
SqXMinX( Serious );
mov( U1, X );
mul( U1, U1, OneUlp );
SqXMinX( Serious );
if( cmp(J,Zero) != 0)
Pause();
printf("Testing if sqrt(X * X) == X for %d Integers X.\n", NoTrials);
mov( Zero, J );
mov( Two, X );
mov( Radix, Y );
if( cmp(Radix,One) != 0 )
{
lngint = NoTrials;
LTOF( &lngint, t );
FTOL( t, &lng2, X );
if( lngint != lng2 )
{
printf( "Integer conversion error\n" );
exit(1);
}
do
{
mov( Y, X );
mul( Radix, Y, Y );
sub( X, Y, t2 );
}
while( ! (cmp(t2,t) >= 0) );
}
mul( X, U2, OneUlp );
I = 1;
while(I < 10)
{
add( X, One, X );
SqXMinX( Defect );
if( cmp(J,Zero) > 0 )
break;
I = I + 1;
}
printf("Test for sqrt monotonicity.\n");
I = - 1;
mov( BMinusU2, X );
mov( Radix, Y );
mul( Radix, U2, Z );
add( Radix, Z, Z );
NotMonot = False;
Monot = False;
while( ! (NotMonot || Monot))
{
I = I + 1;
SQRT(X, X);
SQRT(Y,Q);
SQRT(Z,Z);
if( (cmp(X,Q) > 0) || (cmp(Q,Z) > 0) )
NotMonot = True;
else
{
add( Q, Half, Q );
FLOOR( Q, Q );
mul( Q, Q, t );
if( (I > 0) || (cmp(Radix,t) == 0) )
Monot = True;
else if (I > 0)
{
if(I > 1)
Monot = True;
else
{
mul( Y, BInvrse, Y );
sub( U1, Y, X );
add( Y, U1, Z );
}
}
else
{
mov( Q, Y );
sub( U2, Y, X );
add( Y, U2, Z );
}
}
}
if( Monot )
printf("sqrt has passed a test for Monotonicity.\n");
else
{
ErrCnt[Defect] += 1;
printf("sqrt(X) is non-monotonic for X near " );
show(Y);
}
/*=============================================*/
Milestone = 80;
/*=============================================*/
add( MinSqEr, Half, MinSqEr );
sub( Half, MaxSqEr, MaxSqEr);
/*Y = (SQRT(One + U2) - One) / U2;*/
add( One, U2, Sqarg );
SQRT( Sqarg, Y );
sub( One, Y, Y );
div( U2, Y, Y );
/*SqEr = (Y - One) + U2 / Eight;*/
sub( One, Y, t );
div( Eight, U2, SqEr );
add( t, SqEr, SqEr );
Showsq( 1 );
div( Eight, U2, SqEr );
add( Y, SqEr, SqEr );
Showsq( -1 );
/*Y = ((SQRT(F9) - U2) - (One - U2)) / U1;*/
mov( F9, Sqarg );
SQRT( Sqarg, Y );
sub( U2, Y, Y );
sub( U2, One, t );
sub( t, Y, Y );
div( U1, Y, Y );
div( Eight, U1, SqEr );
add( Y, SqEr, SqEr );
Showsq( 1 );
/*SqEr = (Y + One) + U1 / Eight;*/
div( Eight, U1, t );
add( Y, One, SqEr );
add( SqEr, t, SqEr );
Showsq( -1 );
mov( U2, OneUlp );
mov( OneUlp, X );
for( Indx = 1; Indx <= 3; ++Indx)
{
/*Y = SQRT((X + U1 + X) + F9);*/
add( X, U1, Y );
add( Y, X, Y );
add( Y, F9, Y );
mov( Y, Sqarg );
SQRT( Sqarg, Y );
/*Y = ((Y - U2) - ((One - U2) + X)) / OneUlp;*/
sub( U2, One, t );
add( t, X, t );
sub( U2, Y, Y );
sub( t, Y, Y );
div( OneUlp, Y, Y );
/*Z = ((U1 - X) + F9) * Half * X * X / OneUlp;*/
sub( X, U1, t );
add( t, F9, t );
mul( t, Half, t );
mul( t, X, t );
mul( t, X, t );
div( OneUlp, t, Z );
add( Y, Half, SqEr );
add( SqEr, Z, SqEr );
Showsq( -1 );
sub( Half, Y, SqEr );
add( SqEr, Z, SqEr );
Showsq( 1 );
if(((Indx == 1) || (Indx == 3)))
{
/*X = OneUlp * Sign (X) * FLOOR(Eight / (Nine * SQRT(OneUlp)));*/
mov( OneUlp, Sqarg );
SQRT( Sqarg, t );
mul( Nine, t, t );
div( t, Eight, t );
FLOOR( t, t );
Sign( X, t2 );
mul( t2, t, t );
mul( OneUlp, t, X );
}
else
{
mov( U1, OneUlp );
mov( OneUlp, X );
neg( X );
}
}
/*=============================================*/
Milestone = 85;
/*=============================================*/
SqRWrng = False;
Anomaly = False;
if( cmp(Radix,One) != 0 )
{
printf("Testing whether sqrt is rounded or chopped.\n");
/*D = FLOOR(Half + POW(Radix, One + Precision - FLOOR(Precision)));*/
FLOOR( Precision, t2 );
add( One, Precision, t );
sub( t2, t, t );
POW( Radix, t, D );
add( Half, D, D );
FLOOR( D, D );
/* ... == Radix^(1 + fract) if (Precision == Integer + fract. */
div( Radix, D, X );
div( A1, D, Y );
FLOOR( X, t );
FLOOR( Y, t2 );
if( (cmp(X,t) != 0) || (cmp(Y,t2) != 0) )
{
Anomaly = True;
printf( "Anomaly 1\n" );
}
else
{
mov( Zero, X );
mov( X, Z2 );
mov( One, Y );
mov( Y, Y2 );
sub( One, Radix, Z1 );
mul( Four, D, FourD );
do
{
if( cmp(Y2,Z2) >0 )
{
mov( Radix, Q );
mov( Y, YY1 );
do
{
/*X1 = FABS(Q + FLOOR(Half - Q / YY1) * YY1);*/
div( YY1, Q, t );
sub( t, Half, t );
FLOOR( t, t );
mul( t, YY1, t );
add( Q, t, X1 );
FABS( X1 );
mov( YY1, Q );
mov( X1, YY1 );
}
while( ! (cmp(X1,Zero) <= 0) );
if( cmp(Q,One) <= 0 )
{
mov( Y2, Z2 );
mov( Y, Z );
}
}
add( Y, Two, Y );
add( X, Eight, X );
add( Y2, X, Y2 );
if( cmp(Y2,FourD) >= 0 )
sub( FourD, Y2, Y2 );
}
while( ! (cmp(Y,D) >= 0) );
sub( Z2, FourD, X8 );
mul( Z, Z, Q );
add( X8, Q, Q );
div( FourD, Q, Q );
div( Eight, X8, X8 );
FLOOR( Q, t );
if( cmp(Q,t) != 0 )
{
Anomaly = True;
printf( "Anomaly 2\n" );
}
else
{
Break = False;
do
{
mul( Z1, Z, X );
/*X = X - FLOOR(X / Radix) * Radix;*/
div( Radix, X, t );
FLOOR( t, t );
mul( t, Radix, t );
sub( t, X, X );
if( cmp(X,One) == 0 )
Break = True;
else
sub( One, Z1, Z1 );
}
while( ! (Break || (cmp(Z1,Zero) <= 0)) );
if( (cmp(Z1,Zero) <= 0) && (! Break))
{
printf( "Anomaly 3\n" );
Anomaly = True;
}
else
{
if( cmp(Z1,RadixD2) > 0)
sub( Radix, Z1, Z1 );
do
{
NewD();
mul( U2, D, t );
}
while( ! (cmp(t,F9) >= 0) );
mul( D, Radix, t );
sub( D, t, t );
sub( D, W, t2 );
if (cmp(t,t2) != 0 )
{
printf( "Anomaly 4\n" );
Anomaly = True;
}
else
{
mov( D, Z2 );
I = 0;
add( One, Z, t );
mul( t, Half, t );
add( D, t, Y );
add( D, Z, X );
add( X, Q, X );
SR3750();
sub( Z, One, t );
mul( t, Half, t );
add( D, t, Y );
add( Y, D, Y );
sub( Z, D, X );
add( X, D, X );
add( X, Q, t );
add( t, X, X );
SR3750();
NewD();
sub( Z2, D, t );
sub( Z2, W, t2 );
if(cmp(t,t2) != 0 )
{
printf( "Anomaly 5\n" );
Anomaly = True;
}
else
{
/*Y = (D - Z2) + (Z2 + (One - Z) * Half);*/
sub( Z, One, t );
mul( t, Half, t );
add( Z2, t, t );
sub( Z2, D, Y );
add( Y, t, Y );
/*X = (D - Z2) + (Z2 - Z + Q);*/
sub( Z, Z2, t );
add( t, Q, t );
sub( Z2, D, X );
add( X, t, X );
SR3750();
add( One, Z, Y );
mul( Y, Half, Y );
mov( Q, X );
SR3750();
if(I == 0)
{
printf( "Anomaly 6\n" );
Anomaly = True;
}
}
}
}
}
}
if ((I == 0) || Anomaly)
{
ErrCnt[Failure] += 1;
printf( "Anomalous arithmetic with Integer < \n");
printf("Radix^Precision = " );
show( W );
printf(" fails test whether sqrt rounds or chops.\n");
SqRWrng = True;
}
}
if(! Anomaly)
{
if(! ((cmp(MinSqEr,Zero) < 0) || (cmp(MaxSqEr,Zero) > 0))) {
RSqrt = Rounded;
printf("Square root appears to be correctly rounded.\n");
}
else
{
k = 0;
add( MaxSqEr, U2, t );
sub( Half, U2, t2 );
if( cmp(t,t2) > 0 )
k = 1;
if( cmp( MinSqEr, Half ) > 0 )
k = 1;
add( MinSqEr, Radix, t );
if( cmp( t, Half ) < 0 )
k = 1;
if( k == 1 )
SqRWrng = True;
else
{
RSqrt = Chopped;
printf("Square root appears to be chopped.\n");
}
}
}
if( SqRWrng )
{
printf("Square root is neither chopped nor correctly rounded.\n");
printf("Observed errors run from " );
sub( Half, MinSqEr, t );
show( t );
printf("\tto " );
add( Half, MaxSqEr, t );
show( t );
printf( "ulps.\n" );
sub( MinSqEr, MaxSqEr, t );
mul( Radix, Radix, t2 );
if( cmp( t, t2 ) >= 0 )
{
ErrCnt[Serious] += 1;
printf( "sqrt gets too many last digits wrong\n");
}
}
}
Showsq( arg )
int arg;
{
k = 0;
if( arg <= 0 )
{
if( cmp(SqEr,MinSqEr) < 0 )
{
k = 1;
mov( SqEr, MinSqEr );
}
}
if( arg >= 0 )
{
if( cmp(SqEr,MaxSqEr) > 0 )
{
k = 2;
mov( SqEr, MaxSqEr );
}
}
#if DEBUG
if( k != 0 )
{
printf( "Square root of " );
show( arg );
printf( "\tis in error by " );
show( SqEr );
}
#endif
}
pow1test()
{
/*=============================================*/
Milestone = 90;
/*=============================================*/
Pause();
printf("Testing powers Z^i for small Integers Z and i.\n");
N = 0;
/* ... test powers of zero. */
I = 0;
mov( Zero, Z );
neg(Z);
M = 3;
Break = False;
do
{
mov( One, X );
SR3980();
if(I <= 10)
{
I = 1023;
SR3980();
}
if( cmp(Z,MinusOne) == 0 )
Break = True
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -