📄 eparanoi.c
字号:
}
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");
/*=============================================*/
Milestone = 45;
/*=============================================*/
add( One, U2, Y2 );
sub( U2, One, YY1 );
add( OneAndHalf, U2, Z );
add( Z, U2, Z );
div( Y2, Z, X );
sub( U2, OneAndHalf, T );
sub( U2, T, T );
sub( U2, T, Y );
div( YY1, Y, Y );
add( Z, U2, Z );
div( Y2, Z, Z );
sub( OneAndHalf, X, X );
sub( T, Y, Y );
div( YY1, T, T );
add( OneAndHalf, U2, t );
sub( t, Z, Z );
sub( OneAndHalf, U2, t );
add( t, T, T );
k = 0;
if( cmp( X, Zero ) > 0 )
k = 1;
if( cmp( Y, Zero ) > 0 )
k = 1;
if( cmp( Z, Zero ) > 0 )
k = 1;
if( cmp( T, Zero ) > 0 )
k = 1;
if( k == 0 )
{
div( Y2, OneAndHalf, X );
sub( U2, OneAndHalf, Y );
add( U2, OneAndHalf, Z );
sub( Y, X, X );
div( YY1, OneAndHalf, T );
div( YY1, Y, Y );
add( Z, U2, t );
sub( t, T, T );
sub( Z, Y, Y );
div( Y2, Z, Z );
add( Y2, U2, YY1 );
div( Y2, YY1, YY1 );
sub( OneAndHalf, Z, Z );
sub( Y2, YY1, Y2 );
sub( U1, F9, YY1 );
div( F9, YY1, YY1 );
k = cmp( X, Zero );
k |= cmp( Y, Zero );
k |= cmp( Z, Zero );
k |= cmp( T, Zero );
k |= cmp( Y2, Zero );
sub( Half, YY1, t );
sub( Half, F9, t2 );
k |= cmp( t, t2 );
if( k == 0 )
{
RDiv = Rounded;
printf("Division appears to round correctly.\n");
if(GDiv == No)
printf("Division test inconsistent\n");
}
else
{
k = 0;
if( cmp( X, Zero ) >= 0 )
k = 1;
if( cmp( Y, Zero ) >= 0 )
k = 1;
if( cmp( Z, Zero ) >= 0 )
k = 1;
if( cmp( T, Zero ) >= 0 )
k = 1;
if( cmp( Y, Zero ) >= 0 )
k = 1;
sub( Half, YY1, t );
sub( Half, F9, t2 );
if( cmp( t, t2 ) >= 0 )
k = 1;
if( k == 0 )
{
RDiv = Chopped;
printf("Division appears to chop.\n");
}
}
}
if(RDiv == Other)
printf("/ is neither chopped nor correctly rounded.\n");
div( Radix, One, BInvrse );
mul( BInvrse, Radix, t );
sub( Half, t, t );
if( cmp( t, Half ) != 0 )
{
ErrCnt[Failure] += 1;
printf( "Radix * ( 1 / Radix ) differs from 1\n" );
}
Milestone = 50;
/*=============================================*/
add( F9, U1, t );
sub( Half, t, t );
k = cmp( t, Half );
add( BMinusU2, U2, t );
sub( One, t, t );
sub( One, Radix, t2 );
k |= cmp( t, t2 );
if( k != 0 )
{
ErrCnt[Failure] += 1;
printf( "Incomplete carry-propagation in Addition\n" );
}
mul( U1, U1, X );
sub( X, One, X );
sub( U2, One, Y );
mul( U2, Y, Y );
add( One, Y, Y );
sub( Half, F9, Z );
sub( Half, X, X );
sub( Z, X, X );
sub( One, Y, Y );
if( (cmp(X,Zero) == 0) && (cmp(Y,Zero) == 0) )
{
RAddSub = Chopped;
printf("Add/Subtract appears to be chopped.\n");
}
if(GAddSub == Yes)
{
add( Half, U2, X );
mul( X, U2, X );
sub( U2, Half, Y );
mul( Y, U2, Y );
add( One, X, X );
add( One, Y, Y );
add( One, U2, t );
sub( X, t, X );
sub( Y, One, Y );
k = cmp(X,Zero);
if( k )
printf( "1+U2-[u2(1/2+U2)+1] != 0\n" );
k2 = cmp(Y,Zero);
if( k2 )
printf( "1-[U2(1/2-U2)+1] != 0\n" );
k |= k2;
if( k == 0 )
{
add( Half, U2, X );
mul( X, U1, X );
sub( U2, Half, Y );
mul( Y, U1, Y );
sub( X, One, X );
sub( Y, One, Y );
sub( X, F9, X );
sub( Y, One, Y );
k = cmp(X,Zero);
if( k )
printf( "F9-[1-U1(1/2+U2)] != 0\n" );
k2 = cmp(Y,Zero);
if( k2 )
printf( "1-[1-U1(1/2-U2)] != 0\n" );
k |= k2;
if( k == 0 )
{
RAddSub = Rounded;
printf("Addition/Subtraction appears to round correctly.\n");
if(GAddSub == No)
printf( "Add/Subtract test inconsistent\n");
}
else
{
printf("Addition/Subtraction neither rounds nor chops.\n");
}
}
else
printf("Addition/Subtraction neither rounds nor chops.\n");
}
else
printf("Addition/Subtraction neither rounds nor chops.\n");
mov( One, S );
add( One, Half, X );
mul( Half, X, X );
add( One, X, X );
add( One, U2, Y );
mul( Y, Half, Y );
sub( Y, X, Z );
sub( X, Y, T );
add( Z, T, StickyBit );
if( cmp(StickyBit, Zero) != 0 )
{
mov( Zero, S );
ErrCnt[Flaw] += 1;
printf( "(X - Y) + (Y - X) is non zero!\n" );
}
mov( Zero, StickyBit );
FLOOR( RadixD2, t );
k2 = cmp( t, RadixD2 );
k = 1;
if( (GMult == Yes) && (GDiv == Yes) && (GAddSub == Yes)
&& (RMult == Rounded) && (RDiv == Rounded)
&& (RAddSub == Rounded) && (k2 == 0) )
{
printf("Checking for sticky bit.\n");
k = 0;
add( Half, U1, X );
mul( X, U2, X );
mul( Half, U2, Y );
add( One, Y, Z );
add( One, X, T );
sub( One, Z, t );
sub( One, T, t2 );
if( cmp(t,Zero) > 0 )
{
k = 1;
printf( "[1+(1/2)U2]-1 > 0\n" );
}
if( cmp(t2,U2) < 0 )
{
k = 1;
printf( "[1+U2(1/2+U1)]-1 < U2\n" );
}
add( T, Y, Z );
sub( X, Z, Y );
sub( T, Z, t );
sub( T, Y, t2 );
if( cmp(t,U2) < 0 )
{
k = 1;
printf( "[[1+U2(1/2+U1)]+(1/2)U2]-[1+U2(1/2+U1)] < U2\n" );
}
if( cmp(t2,Zero) != 0 )
{
k = 1;
printf( "(1/2)U2-[1+U2(1/2+U1)] != 0\n" );
}
add( Half, U1, X );
mul( X, U1, X );
mul( Half, U1, Y );
sub( Y, One, Z );
sub( X, One, T );
sub( One, Z, t );
sub( F9, T, t2 );
if( cmp(t,Zero) != 0 )
{
k = 1;
printf( "(1-(1/2)U1)-1 != 0\n" );
}
if( cmp(t2,Zero) != 0 )
{
k = 1;
printf( "[1-U1(1/2+U1)]-F9 != 0\n" );
}
sub( U1, Half, Z );
mul( Z, U1, Z );
sub( Z, F9, T );
sub( Y, F9, Q );
sub( F9, T, t );
if( cmp( t, Zero ) != 0 )
{
k = 1;
printf( "[F9-U1(1/2-U1)]-F9 != 0\n" );
}
sub( U1, F9, t );
sub( Q, t, t );
if( cmp( t, Zero ) != 0 )
{
k = 1;
printf( "(F9-U1)-(F9-(1/2)U1) != 0\n" );
}
add( One, U2, Z );
mul( Z, OneAndHalf, Z );
add( OneAndHalf, U2, T );
sub( Z, T, T );
add( U2, T, T );
div( Radix, Half, X );
add( One, X, X );
mul( Radix, U2, Y );
add( One, Y, Y );
mul( X, Y, Z );
if( cmp( T, Zero ) != 0 )
{
k = 1;
printf( "(3/2+U2)-3/2(1+U2)+U2 != 0\n" );
}
mul( Radix, U2, t );
add( X, t, t );
sub( Z, t, t );
if( cmp( t, Zero ) != 0 )
{
k = 1;
printf( "(1+1/2Radix)+Radix*U2-[1+1/(2Radix)][1+Radix*U2] != 0\n" );
}
if( cmp(Radix, Two) != 0 )
{
add( Two, U2, X );
div( Two, X, Y );
sub( One, Y, t );
if( cmp( t, Zero) != 0 )
k = 1;
}
}
if( k == 0 )
{
printf("Sticky bit apparently used correctly.\n");
mov( One, StickyBit );
}
else
{
printf("Sticky bit used incorrectly or not at all.\n");
}
if( GMult == No || GDiv == No || GAddSub == No ||
RMult == Other || RDiv == Other || RAddSub == Other)
{
ErrCnt[Flaw] += 1;
printf("lack(s) of guard digits or failure(s) to correctly round or chop\n");
printf( "(noted above) count as one flaw in the final tally below\n" );
}
/*=============================================*/
Milestone = 60;
/*=============================================*/
printf("\n");
printf("Does Multiplication commute? ");
printf("Testing on %d random pairs.\n", NoTrials);
SQRT( Three, Random9 );
mov( Third, Random1 );
I = 1;
do
{
Random();
mov( Random1, X );
Random();
mov( Random1, Y );
mul( Y, X, Z9 );
mul( X, Y, Z );
sub( Z9, Z, Z9 );
I = I + 1;
}
while ( ! ((I > NoTrials) || (cmp(Z9,Zero) != 0)));
if(I == NoTrials)
{
div( Three, Half, t );
add( One, t, Random1 );
add( U2, U1, t );
add( t, One, Random2 );
mul( Random1, Random2, Z );
mul( Random2, Random1, Y );
/* Z9 = (One + Half / Three) * ((U2 + U1) + One) - (One + Half /
* Three) * ((U2 + U1) + One);
*/
div( Three, Half, t2 );
add( One, t2, t2 );
add( U2, U1, t );
add( t, One, t );
mul( t2, t, Z9 );
mul( t2, t, t );
sub( t, Z9, Z9 );
}
if(! ((I == NoTrials) || (cmp(Z9,Zero) == 0)))
{
ErrCnt[Defect] += 1;
printf( "X * Y == Y * X trial fails.\n");
}
else
{
printf(" No failures found in %d integer pairs.\n", NoTrials);
}
/*=============================================*/
Milestone = 70;
/*=============================================*/
sqtest();
Milestone = 90;
pow1test();
Milestone = 110;
printf("Seeking Underflow thresholds UfThold and E0.\n");
mov( U1, D );
FLOOR( Precision, t );
if( cmp(Precision, t) != 0 )
{
mov( BInvrse, D );
mov( Precision, X );
do
{
mul( D, BInvrse, D );
sub( One, X, X );
}
while( cmp(X, Zero) > 0 );
}
mov( One, Y );
mov( D, Z );
/* ... D is power of 1/Radix < 1. */
sigsave = sigfpe;
if( setjmp(ovfl_buf) )
goto under0;
do
{
mov( Y, C );
mov( Z, Y );
mul( Y, Y, Z );
add( Z, Z, t );
}
while( (cmp(Y,Z) > 0) && (cmp(t,Z) > 0) );
under0:
sigsave = 0;
mov( C, Y );
mul( Y, D, Z );
sigsave = sigfpe;
if( setjmp(ovfl_buf) )
goto under1;
do
{
mov( Y, C );
mov( Z, Y );
mul( Y, D, Z );
add( Z, Z, t );
}
while( (cmp(Y,Z) > 0) && (cmp(t,Z) > 0) );
under1:
sigsave = 0;
if( cmp(Radix,Two) < 0 )
mov( Two, HInvrse );
else
mov( Radix, HInvrse );
div( HInvrse, One, H );
/* ... 1/HInvrse == H == Min(1/Radix, 1/2) */
div( C, One, CInvrse );
mov( C, E0 );
mul( E0, H, Z );
/* ...1/Radix^(BIG Integer) << 1 << CInvrse == 1/C */
sigsave = sigfpe;
if( setjmp(ovfl_buf) )
goto under2;
do
{
mov( E0, Y );
mov( Z, E0 );
mul( E0, H, Z );
add( Z, Z, t );
}
while( (cmp(E0,Z) > 0) && (cmp(t,Z) > 0) );
under2:
sigsave = 0;
mov( E0, UfThold );
mov( Zero, E1 );
mov( Zero, Q );
mov( U2, E9 );
add( One, E9, S );
mul( C, S, D );
if( cmp(D,C) <= 0 )
{
mul( Radix, U2, E9 );
add( One, E9, S );
mul( C, S, D );
if( cmp(D, C) <= 0 )
{
ErrCnt[Failure] += 1;
printf( "multiplication gets too many last digits wrong.\n" );
mov( E0, Underflow );
mov( Zero, YY1 );
mov( Z, PseudoZero );
}
}
else
{
mov( D, Underflow );
mul( Underflow, H, PseudoZero );
mov( Zero, UfThold );
do
{
mov( Underflow, YY1 );
mov( PseudoZero, Underflow );
add( E1, E1, t );
if( cmp(t, E1) <= 0)
{
mul( Underflow, HInvrse, Y2 );
sub( Y2, YY1, E1 );
FABS( E1 );
mov( YY1, Q );
if( (cmp( UfThold, Zero ) == 0)
&& (cmp(YY1, Y2) != 0) )
mov( YY1, UfThold );
}
mul( PseudoZero, H, PseudoZero );
add( PseudoZero, PseudoZero, t );
}
while( (cmp(Underflow, PseudoZero) > 0)
&& (cmp(t, PseudoZero) > 0) );
}
/* Comment line 4530 .. 4560 */
if( cmp(PseudoZero, Zero) != 0 )
{
printf("\n");
mov(PseudoZero, Z );
/* ... Test PseudoZero for "phoney- zero" violates */
/* ... PseudoZero < Underflow or PseudoZero < PseudoZero + PseudoZero
... */
if( cmp(PseudoZero, Zero) <= 0 )
{
ErrCnt[Failure] += 1;
printf("Positive expressions can underflow to an\n");
printf("allegedly negative value\n");
printf("PseudoZero that prints out as: " );
show( PseudoZero );
mov( PseudoZero, X );
neg( X );
if( cmp(X, Zero) <= 0 )
{
printf("But -PseudoZero, which should be\n");
printf("positive, isn't; it prints out as " );
show( X );
}
}
else
{
ErrCnt[Flaw] += 1;
printf( "Underflow can stick at an allegedly positive\n");
printf("value PseudoZero that prints out as " );
show( PseudoZero );
}
/* TstPtUf();*/
}
/*=============================================*/
Milestone = 120;
/*=============================================*/
mul( CInvrse, Y, t );
mul( CInvrse, YY1, t2 );
if( cmp(t,t2) > 0 )
{
mul( H, S, S );
mov( Underflow, E0 );
}
if(! ((cmp(E1,Zero) == 0) || (cmp(E1,E0) == 0)) )
{
ErrCnt[Defect] += 1;
if( cmp(E1,E0) < 0 )
{
printf("Products underflow at a higher");
printf(" threshold than differences.\n");
if( cmp(PseudoZero,Zero) == 0 )
mov( E1, E0 );
}
else
{
printf("Difference underflows at a higher");
printf(" threshold than products.\n");
}
}
printf("Smallest strictly positive number found is E0 = " );
show( E0 );
mov( E0, Z );
TstPtUf();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -