/* Note all arguments of operation subroutines are pointers. */ /* c = b + a */ #define add(a,b,c) qadd(a,b,c) /* c = b - a */ #define sub(a,b,c) qsub(a,b,c) /* c = b * a */ #define mul(a,b,c) qmul(a,b,c) /* c = b / a */ #define div(a,b,c) qdiv(a,b,c) /* 1 if a>b, 0 if a==b, -1 if a<b */ #define cmp(a,b) qcmp(a,b) /* b = a */ #define mov(a,b) qmov(a,b) /* a = -a */ #define neg(a) qneg(a) /* a = 0 */ #define clear(a) qclear(a)
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, Y1 );
sub( U2, OneAndHalf, X );
add( OneAndHalf, U2, Y );
sub( U2, X, Z );
mul( Z, Y2, Z );
mul( Y, Y1, T );
sub( X, Z, Z );
sub( X, T, T );
mul( X, Y2, X );
add( Y, U2, Y );
mul( Y, Y1, 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, Y1, T );
add( Z, U2, t );
sub( t, X, X );
mul( Y, Y1, 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, Y1, StickyBit );
mul( Y2, Y1, Y1 );
sub( Y2, StickyBit, StickyBit );
sub( Half, Y1, Y1 );
k = cmp( X, Zero );
k |= cmp( Y, Zero );
k |= cmp( Z, Zero );
k |= cmp( T, Zero );
k |= cmp( StickyBit, Zero );
k |= cmp( Y1, 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(Y1, 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, Y1 );
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( Y1, Y, Y );
add( Z, U2, Z );
div( Y2, Z, Z );
sub( OneAndHalf, X, X );
sub( T, Y, Y );
div( Y1, 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( Y1, OneAndHalf, T );
div( Y1, Y, Y );
add( Z, U2, t );
sub( t, T, T );
sub( Z, Y, Y );
div( Y2, Z, Z );
add( Y2, U2, Y1 );
div( Y2, Y1, Y1 );
sub( OneAndHalf, Z, Z );
sub( Y2, Y1, Y2 );
sub( U1, F9, Y1 );
div( F9, Y1, Y1 );
k = cmp( X, Zero );
k |= cmp( Y, Zero );
k |= cmp( Z, Zero );
k |= cmp( T, Zero );
k |= cmp( Y2, Zero );
sub( Half, Y1, 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, Y1, 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) );
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, Y1 );
mov( Z, PseudoZero );
}
} else
{
mov( D, Underflow );
mul( Underflow, H, PseudoZero );
mov( Zero, UfThold ); do
{
mov( Underflow, Y1 );
mov( PseudoZero, Underflow );
add( E1, E1, t ); if( cmp(t, E1) <= 0)
{
mul( Underflow, HInvrse, Y2 );
sub( Y2, Y1, E1 );
FABS( E1 );
mov( Y1, Q ); if( (cmp( UfThold, Zero ) == 0)
&& (cmp(Y1, Y2) != 0) )
mov( Y1, 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, Y1, 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();
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)
{ case1:
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;
case2:
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;
case3:
mov( X, X ); break;
case4:
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, Y );
IEEE = (cmp(Y,E0) == 0);
}
} 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)) )
{
ErrCnt[Flaw] += 1;
printf("X = " );
show( X );
printf( "\tis not equal to Z = " );
show( Z );
sub( Z, X, Z9 );
printf("yet X - Z yields " );
show( Z9 );
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 );
neg(Y);
mul( HInvrse, Y, V9 ); if (setjmp(ovfl_buf)) goto overflow; do
{
mov( Y, V );
mov( V9, Y );
mul( HInvrse, Y, V9 );
} while( cmp(V9,Y) < 0 );
I = 1;
overflow:
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");
ErrCnt[Flaw] += 1;
} if( cmp(Z, Y) != 0 )
{
ErrCnt[Serious] += 1;
printf("overflow past " );
show( Y );
printf( "\tshrinks to " );
show( Z );
} /*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)
{ case1: mov(UfThold, Z); break; case2: mov( E0, Z); break; case3: 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)
{ case2: add( One, U2, X ); break; case3: mov( V, X ); break; case4: mov(UfThold,X); break; case5: 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");
{ staticchar *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; andreturnsthenewvalueofRandom1
*/
mul( Two, Three, Y );
mov( Zero, Q );
N = 0; do
{
mov( X, Z );
add( t2, One, t2 ); /*I = I + 1;*/
add( t2, t2, t );
div( t, Y, Y ); /*Y = Y / (I + I);*/
add( Y, Q, R );
add( Z, R, X );
sub( X, Z, Q );
add( Q, R, Q );
} while( cmp(X,Z) > 0 );
/*Z = (OneAndHalf + One / Eight) + X / (OneAndHalf * ThirtyTwo);*/
div( Eight, One, t );
add( OneAndHalf, t, Z );
mul( OneAndHalf, ThirtyTwo, t );
div( t, X, t );
add( Z, t, Z );
mul( Z, Z, X );
mul( X, X, Exp2 );
mov( F9, X );
sub( U1, X, Y );
printf("Testing X^((X + 1) / (X - 1)) vs. exp(2) = " );
show( Exp2 );
printf( "\tas X -> 1.\n" ); for(I = 1;;)
{
sub( BInvrse, X, Z ); /*Z = (X + One) / (Z - (One - BInvrse));*/
add( X, One, t2 );
sub( BInvrse, One, t );
sub( t, Z, t );
div( t, t2, Z );
POW( X, Z, Sqarg );
sub( Exp2, Sqarg, Q );
mov( Q, t );
FABS( t );
mul( TwoForty, U2, t2 ); if( cmp( t, t2 ) > 0 )
{
N = 1;
sub( BInvrse, X, V9 );
sub( BInvrse, One, t );
sub( t, V9, V9 );
ErrCnt[Defect] += 1;
printf( "Calculated " );
show( Sqarg );
printf(" for \t(1 + " );
show( V9 );
printf( "\tto the power " );
show( Z );
printf("\tdiffers from correct value by " );
show( Q );
printf("\tThis much error may spoil financial\n");
printf("\tcalculations involving tiny interest rates.\n"); break;
} else
{
sub( X, Y, Z );
mul( Z, Two, Z );
add( Z, Y, Z );
mov( Y, X );
mov( Z, Y );
sub( F9, X, Z );
mul( Z, Z, Z );
add( Z, One, Z ); if( (cmp(Z,One) > 0) && (I < NoTrials) )
I++; else
{ if( cmp(X,One) > 0 )
{ if(N == 0)
printf("Accuracy seems adequate.\n"); break;
} else
{
add( One, U2, X );
add( U2, U2, Y );
add( X, Y, Y );
I = 1;
}
}
}
} /*=============================================*/
Milestone = 150; /*=============================================*/
printf("Testing powers Z^Q at four nearly extreme values.\n");
N = 0;
mov( A1, Z ); /*Q = FLOOR(Half - LOG(C) / LOG(A1));*/
LOG( C, t );
LOG( A1, t2 );
div( t2, t, t );
sub( t, Half, t );
FLOOR( t, Q ); Break = False; do
{
mov( CInvrse, X );
POW( Z, Q, Y );
IsYeqX();
neg(Q);
mov( C, X );
POW( Z, Q, Y );
IsYeqX(); if( cmp(Z,One) < 0 ) Break = True; else
mov( AInvrse, Z );
} while( ! (Break));
PrintIfNPositive(); if(N == 0)
printf(" ... no discrepancies found.\n");
printf("\n");
}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.32 Sekunden
(vorverarbeitet am 2026-06-14)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.