📄 eparanoi.c
字号:
mov( E0, Underflow );
if(N == 1)
mov( Y, Underflow );
I = 4;
if( cmp(E1,Zero) == 0 )
I = 3;
if( cmp( UfThold,Zero) == 0 )
I = I - 2;
UfNGrad = True;
switch(I)
{
case 1:
mov( Underflow, UfThold );
mul( CInvrse, Q, t );
mul( CInvrse, Y, t2 );
mul( t2, S, t2 );
if( cmp( t, t2 ) != 0 )
{
mov( Y, UfThold );
ErrCnt[Failure] += 1;
printf( "Either accuracy deteriorates as numbers\n");
printf("approach a threshold = " );
show( UfThold );
printf(" coming down from " );
show( C );
printf(" or else multiplication gets too many last digits wrong.\n");
}
break;
case 2:
ErrCnt[Failure] += 1;
printf( "Underflow confuses Comparison which alleges that\n");
printf("Q == Y while denying that |Q - Y| == 0; these values\n");
printf("print out as Q = " );
show( Q );
printf( ", Y = " );
show( Y );
sub( Y2, Q, t );
FABS(t);
printf ("|Q - Y| = " );
show( t );
mov( Q, UfThold );
break;
case 3:
mov( X, X );
break;
case 4:
div( E9, E1, t );
sub( t, UfThold, t );
FABS(t);
if( (cmp(Q,UfThold) == 0) && (cmp(E1,E0) == 0)
&& (cmp(t,E1) <= 0) )
{
UfNGrad = False;
printf("Underflow is gradual; it incurs Absolute Error =\n");
printf("(roundoff in UfThold) < E0.\n");
mul( E0, CInvrse, Y );
add( OneAndHalf, U2, t );
mul( Y, t, Y );
add( One, U2, X );
mul( CInvrse, X, X );
div( X, Y, t );
IEEE = (cmp(t,E0) == 0);
if( IEEE == 0 )
{
printf( "((CInvrse E0) (1.5+U2)) / (CInvrse (1+U2)) != E0\n" );
printf( "CInvrse = " );
show( CInvrse );
printf( "E0 = " );
show( E0 );
printf( "U2 = " );
show( U2 );
printf( "X = " );
show(X);
printf( "Y = " );
show(Y);
printf( "Y/X = " );
show(t);
}
}
}
if(UfNGrad)
{
printf("\n");
div( UfThold, Underflow, R );
SQRT( R, R );
if( cmp(R,H) <= 0)
{
mul( R, UfThold, Z );
/* X = Z * (One + R * H * (One + H));*/
add( One, H, X );
mul( H, X, X );
mul( R, X, X );
add( One, X, X );
mul( Z, X, X );
}
else
{
mov( UfThold, Z );
/*X = Z * (One + H * H * (One + H));*/
add( One, H, X );
mul( H, X, X );
mul( H, X, X );
add( One, X, X );
mul( Z, X, X );
}
sub( Z, X, t );
/* if(! ((cmp(X,Z) == 0) || (cmp(t,Zero) != 0)) )*/
if( (cmp(X,Z) != 0) && (cmp(t,Zero) == 0) )
{
/* ErrCnt[Flaw] += 1;*/
ErrCnt[Serious] += 1;
printf("X = " );
show( X );
printf( "\tis not equal to Z = " );
show( Z );
/* sub( Z, X, Z9 );*/
printf("yet X - Z yields " );
show( t );
printf("which compares equal to " );
show( Zero );
printf(" Should this NOT signal Underflow, ");
printf("this is a SERIOUS DEFECT\nthat causes ");
printf("confusion when innocent statements like\n");;
printf(" if (X == Z) ... else");
printf(" ... (f(X) - f(Z)) / (X - Z) ...\n");
printf("encounter Division by Zero although actually\n");
printf("X / Z = 1 + " );
div( Z, X, t );
sub( Half, t, t );
sub( Half, t, t );
show(t);
}
}
printf("The Underflow threshold is " );
show( UfThold );
printf( "below which calculation may suffer larger Relative error than" );
printf( " merely roundoff.\n");
mul( U1, U1, Y2 );
mul( Y2, Y2, Y );
mul( Y, U1, Y2 );
if( cmp( Y2,UfThold) <= 0 )
{
if( cmp(Y,E0) > 0 )
{
ErrCnt[Defect] += 1;
I = 5;
}
else
{
ErrCnt[Serious] += 1;
I = 4;
}
printf("Range is too narrow; U1^%d Underflows.\n", I);
}
Milestone = 130;
/*Y = - FLOOR(Half - TwoForty * LOG(UfThold) / LOG(HInvrse)) / TwoForty;*/
LOG( UfThold, Y );
LOG( HInvrse, t );
div( t, Y, Y );
mul( TwoForty, Y, Y );
sub( Y, Half, Y );
FLOOR( Y, Y );
div( TwoForty, Y, Y );
neg(Y);
sub( One, Y, Y2 ); /* ***** changed from Y2 = Y + Y */
printf("Since underflow occurs below the threshold\n");
printf("UfThold = " );
show( HInvrse );
printf( "\tto the power " );
show( Y );
printf( "only underflow should afflict the expression " );
show( HInvrse );
printf( "\tto the power " );
show( Y2 );
POW( HInvrse, Y2, V9 );
printf("Actually calculating yields: " );
show( V9 );
add( Radix, Radix, t );
add( t, E9, t );
mul( t, UfThold, t );
if( (cmp(V9,Zero) < 0) || (cmp(V9,t) > 0) )
{
ErrCnt[Serious] += 1;
printf( "this is not between 0 and underflow\n");
printf(" threshold = " );
show( UfThold );
}
else
{
add( One, E9, t );
mul( UfThold, t, t );
if( cmp(V9,t) <= 0 )
printf("This computed value is O.K.\n");
else
{
ErrCnt[Defect] += 1;
printf( "this is not between 0 and underflow\n");
printf(" threshold = " );
show( UfThold );
}
}
Milestone = 140;
pow2test();
/*=============================================*/
Milestone = 160;
/*=============================================*/
Pause();
printf("Searching for Overflow threshold:\n");
printf("This may generate an error.\n");
sigsave = sigfpe;
I = 0;
mov( CInvrse, Y ); /* a large power of 2 */
neg(Y);
mul( HInvrse, Y, V9 ); /* HInvrse = 2 */
if (setjmp(ovfl_buf))
goto overflow;
do
{
mov( Y, V );
mov( V9, Y );
mul( HInvrse, Y, V9 );
}
while( cmp(V9,Y) < 0 ); /* V9 = 2 * Y */
I = 1;
overflow:
show( HInvrse );
printf( "\ttimes " );
show( Y );
printf( "\tequals " );
show( V9 );
mov( V9, Z );
printf("Can `Z = -Y' overflow?\n");
printf("Trying it on Y = " );
show(Y);
mov( Y, V9 );
neg( V9 );
mov( V9, V0 );
sub( Y, V, t );
add( V, V0, t2 );
if( cmp(t,t2) == 0 )
printf("Seems O.K.\n");
else
{
printf("finds a Flaw, -(-Y) differs from Y.\n");
printf( "V-Y=t:" );
show(V);
show(Y);
show(t);
printf( "V+V0=t2:" );
show(V);
show(V0);
show(t2);
ErrCnt[Flaw] += 1;
}
if( (cmp(Z, Y) != 0) && (I != 0) )
{
ErrCnt[Serious] += 1;
printf("overflow past " );
show( Y );
printf( "\tshrinks to " );
show( Z );
printf( "= Y * " );
show( HInvrse );
}
/*Y = V * (HInvrse * U2 - HInvrse);*/
mul( HInvrse, U2, Y );
sub( HInvrse, Y, Y );
mul( V, Y, Y );
/*Z = Y + ((One - HInvrse) * U2) * V;*/
sub( HInvrse, One, Z );
mul( Z, U2, Z );
mul( Z, V, Z );
add( Y, Z, Z );
if( cmp(Z,V0) < 0 )
mov( Z, Y );
if( cmp(Y,V0) < 0)
mov( Y, V );
sub( V, V0, t );
if( cmp(t,V0) < 0 )
mov( V0, V );
printf("Overflow threshold is V = " );
show( V );
if(I)
{
printf("Overflow saturates at V0 = " );
show( V0 );
}
else
printf("There is no saturation value because the system traps on overflow.\n");
mul( V, One, V9 );
printf("No Overflow should be signaled for V * 1 = " );
show( V9 );
div( One, V, V9 );
printf(" nor for V / 1 = " );
show( V9 );
printf("Any overflow signal separating this * from the one\n");
printf("above is a DEFECT.\n");
/*=============================================*/
Milestone = 170;
/*=============================================*/
mov( V, t );
neg( t );
k = 0;
if( cmp(t,V) >= 0 )
k = 1;
mov( V0, t );
neg( t );
if( cmp(t,V0) >= 0 )
k = 1;
mov( UfThold, t );
neg(t);
if( cmp(t,V) >= 0 )
k = 1;
if( cmp(UfThold,V) >= 0 )
k = 1;
if( k != 0 )
{
ErrCnt[Failure] += 1;
printf( "Comparisons involving +-");
show( V );
show( V0 );
show( UfThold );
printf("are confused by Overflow." );
}
/*=============================================*/
Milestone = 175;
/*=============================================*/
printf("\n");
for(Indx = 1; Indx <= 3; ++Indx) {
switch(Indx)
{
case 1: mov(UfThold, Z); break;
case 2: mov( E0, Z); break;
case 3: mov(PseudoZero, Z); break;
}
if( cmp(Z, Zero) != 0 )
{
SQRT( Z, V9 );
mul( V9, V9, Y );
mul( Radix, E9, t );
sub( t, One, t );
div( t, Y, t );
add( One, Radix, t2 );
add( t2, E9, t2 );
mul( t2, Z, t2 );
if( (cmp(t,Z) < 0) || (cmp(Y,t2) > 0) )
{
if( cmp(V9,U1) > 0 )
ErrCnt[Serious] += 1;
else
ErrCnt[Defect] += 1;
printf("Comparison alleges that what prints as Z = " );
show( Z );
printf(" is too far from sqrt(Z) ^ 2 = " );
show( Y );
}
}
}
Milestone = 180;
for(Indx = 1; Indx <= 2; ++Indx)
{
if(Indx == 1)
mov( V, Z );
else
mov( V0, Z );
SQRT( Z, V9 );
mul( Radix, E9, X );
sub( X, One, X );
mul( X, V9, X );
mul( V9, X, V9 );
mul( Two, Radix, t );
mul( t, E9, t );
sub( t, One, t );
mul( t, Z, t );
if( (cmp(V9,t) < 0) || (cmp(V9,Z) > 0) )
{
mov( V9, Y );
if( cmp(X,W) < 0 )
ErrCnt[Serious] += 1;
else
ErrCnt[Defect] += 1;
printf("Comparison alleges that Z = " );
show( Z );
printf(" is too far from sqrt(Z) ^ 2 :" );
show( Y );
}
}
Milestone = 190;
Pause();
mul( UfThold, V, X );
mul( Radix, Radix, Y );
mul( X, Y, t );
if( (cmp(t,One) < 0) || (cmp(X,Y) > 0) )
{
mul( X, Y, t );
div( U1, Y, t2 );
if( (cmp(t,U1) < 0) || (cmp(X,t2) > 0) )
{
ErrCnt[Defect] += 1;
printf( "Badly " );
}
else
{
ErrCnt[Flaw] += 1;
}
printf(" unbalanced range; UfThold * V = " );
show( X );
printf( "\tis too far from 1.\n");
}
Milestone = 200;
for(Indx = 1; Indx <= 5; ++Indx)
{
mov( F9, X );
switch(Indx)
{
case 2: add( One, U2, X ); break;
case 3: mov( V, X ); break;
case 4: mov(UfThold,X); break;
case 5: mov(Radix,X);
}
mov( X, Y );
sigsave = sigfpe;
if (setjmp(ovfl_buf))
{
printf(" X / X traps when X = " );
show( X );
}
else
{
/*V9 = (Y / X - Half) - Half;*/
div( X, Y, t );
sub( Half, t, t );
sub( Half, t, V9 );
if( cmp(V9,Zero) == 0 )
continue;
mov( U1, t );
neg(t);
if( (cmp(V9,t) == 0) && (Indx < 5) )
{
ErrCnt[Flaw] += 1;
}
else
{
ErrCnt[Serious] += 1;
}
printf(" X / X differs from 1 when X = " );
show( X );
printf(" instead, X / X - 1/2 - 1/2 = " );
show( V9 );
}
}
Pause();
printf("\n");
{
static char *msg[] = {
"FAILUREs encountered =",
"SERIOUS DEFECTs discovered =",
"DEFECTs discovered =",
"FLAWs discovered =" };
int i;
for(i = 0; i < 4; i++) if (ErrCnt[i])
printf("The number of %-29s %d.\n",
msg[i], ErrCnt[i]);
}
printf("\n");
if ((ErrCnt[Failure] + ErrCnt[Serious] + ErrCnt[Defect]
+ ErrCnt[Flaw]) > 0) {
if ((ErrCnt[Failure] + ErrCnt[Serious] + ErrCnt[
Defect] == 0) && (ErrCnt[Flaw] > 0)) {
printf("The arithmetic diagnosed seems ");
printf("satisfactory though flawed.\n");
}
if ((ErrCnt[Failure] + ErrCnt[Serious] == 0)
&& ( ErrCnt[Defect] > 0)) {
printf("The arithmetic diagnosed may be acceptable\n");
printf("despite inconvenient Defects.\n");
}
if ((ErrCnt[Failure] + ErrCnt[Serious]) > 0) {
printf("The arithmetic diagnosed has ");
printf("unacceptable serious defects.\n");
}
if (ErrCnt[Failure] > 0) {
printf("Fatal FAILURE may have spoiled this");
printf(" program's subsequent diagnoses.\n");
}
}
else {
printf("No failures, defects nor flaws have been discovered.\n");
if (! ((RMult == Rounded) && (RDiv == Rounded)
&& (RAddSub == Rounded) && (RSqrt == Rounded)))
printf("The arithmetic diagnosed seems satisfactory.\n");
else {
k = 0;
if( cmp( Radix, Two ) == 0 )
k = 1;
if( cmp( Radix, Ten ) == 0 )
k = 1;
if( (cmp(StickyBit,One) >= 0) && (k == 1) )
{
printf("Rounding appears to conform to ");
printf("the proposed IEEE standard P");
k = 0;
k |= cmp( Radix, Two );
mul( Four, Three, t );
mul( t, Two, t );
sub( t, Precision, t );
sub( TwentySeven, Precision, t2 );
sub( TwentySeven, t2, t2 );
add( t2, One, t2 );
mul( t2, t, t );
if( (cmp(Radix,Two) == 0)
&& (cmp(t,Zero) == 0) )
printf("754");
else
printf("854");
if(IEEE)
printf(".\n");
else
{
printf(",\nexcept for possibly Double Rounding");
printf(" during Gradual Underflow.\n");
}
}
printf("The arithmetic diagnosed appears to be excellent!\n");
}
}
if (fpecount)
printf("\nA total of %d floating point exceptions were registered.\n",
fpecount);
printf("END OF TEST.\n");
}
/* Random */
/* Random computes
X = (Random1 + Random9)^5
Random1 = X - FLOOR(X) + 0.000005 * X;
and returns the new value of Random1
*/
static int randflg = 0;
FLOAT(C5em6);
Random()
{
if( randflg == 0 )
{
mov( Six, t );
neg(t);
POW( Ten, t, t );
mul( Five, t, C5em6 );
randflg = 1;
}
add( Random1, Random9, t );
mul( t, t, t2 );
mul( t2, t2, t2 );
mul( t, t2, t );
FLOOR(t, t2 );
sub( t2, t, t2 );
mul( t, C5em6, t );
add( t, t2, Random1 );
/*return(Random1);*/
}
/* SqXMinX */
SqXMinX( ErrKind )
int ErrKind;
{
mul( X, BInvrse, t2 );
sub( t2, X, t );
/*SqEr = ((SQRT(X * X) - XB) - XA) / OneUlp;*/
mul( X, X, Sqarg );
SQRT( Sqarg, SqEr );
sub( t2, SqEr, SqEr );
sub( t, SqEr, SqEr );
div( OneUlp, SqEr, SqEr );
if( cmp(SqEr,Zero) != 0)
{
Showsq( 0 );
add( J, One, J );
ErrCnt[ErrKind] += 1;
printf("sqrt of " );
mul( X, X, t );
show( t );
printf( "minus " );
show( X );
printf( "equals " );
mul( OneUlp, SqEr, t );
show( t );
printf("\tinstead of correct value 0 .\n");
}
}
/* NewD */
NewD()
{
mul( Z1, Q, X );
/*X = FLOOR(Half - X / Radix) * Radix + X;*/
div( Radix, X, t );
sub( t, Half, t );
FLOOR( t, t );
mul( t, Radix, t );
add( t, X, X );
/*Q = (Q - X * Z) / Radix + X * X * (D / Radix);*/
mul( X, Z, t );
sub( t, Q, t );
div( Radix, t, t );
div( Radix, D, t2 );
mul( X, t2, t2 );
mul( X, t2, t2 );
add( t, t2, Q );
/*Z = Z - Two * X * D;*/
mul( Two, X, t );
mul( t, D, t );
sub( t, Z, Z );
if( cmp(Z,Zero) <= 0)
{
neg(Z);
neg(Z1);
}
mul( Radix, D, D );
}
/* SR3750 */
SR3750()
{
sub( Radix, X, t );
sub( Radix, Z2, t2 );
k = 0;
if( cmp(t,t2) < 0 )
k = 1;
sub( Z2, X, t );
sub( Z2, W, t2 );
if( cmp(t,t2) > 0 )
k = 1;
/*if (! ((X - Radix < Z2 - Radix) || (X - Z2 > W - Z2))) {*/
if( k == 0 )
{
I = I + 1;
mul( X, D, X2 );
mov( X2, Sqarg );
SQRT( X2, X2 );
/*Y2 = (X2 - Z2) - (Y - Z2);*/
sub( Z2, X2, Y2 );
sub( Z2, Y, t );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -