[comp.sys.mac.programmer] Severe Bug in SANE Package ?

roh@gmdzi.UUCP (Peter Rohleder ) (02/28/89)

It seems that we have found a severe bug in the Apples SANE-Package.

We found it when we tried to figure out whether an EXTENDED has
digits unequal zero behind a predefined position after the decimalpoint.

The only(?) way to figure this out seems to shift this significant position
before the decimalpoint by multiplication, then to truncate the
value(we used Rint cause trunc also didn't work) and then making the
opposite operation and comparing the value against the original value.

If it is not equal you can say that obviously the value has digits nonzero
after the fourth position behind the decimalpoint. Otherwise you can
say that there are no digits unequal zero behind a predefined position.

We wrote following short test program including some features to make
the bug obvious.

It should be easy to execute it in the MPW-Pascal or LightSpeedPascal
Environment.

The program reads out of a testfile. Try to use values like 0.004 or 0.09
or 0.01 or 0.3. The Relation-operation in this cases should always return with
EqualTo but it doesn't.

Is this really a severe bug in the SANE-Package or is there anything wrong
in our understanding of the precision of the different operations in SANE.

Also any other ideas to figure out whether a value has significat digits
after a predefined position behind the decimalpoint are helpful and welcome!

PROGRAM Teststr;

	USES
 	{$LOAD MacIntf.LOAD}
{Memtypes, QuickDraw, OSIntf, ToolIntf, PackIntf, FixMath,}
		SANE;

	CONST
		z = 10000;
		kDelta = 1E-18;

	VAR
		s : DecStr;
		f : DecForm;
		i : INTEGER;
		va : Extended;
		re : RelOp;
		t : Text;
		a, b, c : Extended;

FUNCTION CompExtended(a,b:	EXTENDED): RelOp;
	VAR d:	Extended;
BEGIN
	IF (a=0.0) OR (b=0.0) THEN
		CompExtended := Relation(a,b)
	ELSE
		BEGIN
		d := ABS(a - b);
		IF Relation(d,kDelta)= LessThan THEN 
			CompExtended := EqualTo 
		ELSE
			CompExtended := Relation(a,b);
		END;
END;
	
	

	PROCEDURE PrintBitstring (a : Extended);
		VAR
			t : RECORD
					CASE INTEGER OF
						1 : (
								x : Extended
						);
						2 : (
								b : PACKED ARRAY[0..79] OF BOOLEAN
						);
						3 : (
								f : ARRAY[0..4] OF INTEGER
						);
				END;
			i : INTEGER;

	BEGIN

		t.x := a;
		Write(a : 50 : 30,' / ',a, ': ');
		FOR i := 0 TO 79 DO
			BEGIN
				IF t.b[i] = TRUE THEN
					Write('1')
				ELSE
					Write('0');
				IF i = 16 THEN
					Write('  ');
			END;

		FOR i := 0 TO 4 DO
			BEGIN
				Write(t.f[i])
			END;

		Write('  Numclass:', ORD(ClassExtended(a)));
		WriteLn;
	END;

BEGIN

	Reset(t, 'TestFile');
	WHILE NOT EOF(t) DO
		BEGIN
			ReadLn(t, va);
			PrintBitString(va);
			a := va * z;
			b := Rint(a);
			c := a - b;
			WriteLn(a);
			WriteLn(b);
			WriteLn(c);
			Re := CompExtended(a, b);
			CASE Re OF
				GreaterThan : 
					WriteLn('Greaterthan');
				LessThan : 
					WriteLN('LessThan');
				EqualTo : 
					WritelN('EqualTo');
				Unordered : 
					WriteLn('uordered');
			END;
		END;
	Close(t);

END.

Thanks in advance!

Peter Rohleder
e-mail address:    roh@gmdzi.uucp

lippin@wheatena.berkeley.edu (The Apathist) (03/02/89)

Recently roh@gmdzi.UUCP (Peter Rohleder ) wrote:
>
>It seems that we have found a severe bug in the Apples SANE-Package.
>
>We found it when we tried to figure out whether an EXTENDED has
>digits unequal zero behind a predefined position after the decimalpoint.
[...]
>Is this really a severe bug in the SANE-Package or is there anything wrong
>in our understanding of the precision of the different operations in SANE.

I don't think this is really a bug; the problem lies in the necessary
inaccuracy of applying the decimal concept of digits to the binary
representations of SANE.

In your relation test, you are (correctly) using a fudge factor in the
check for equality, to avoid errors in the last few bits.  However,
you neglect to scale the fudge factor along with the numbers you are
comparing, and so when you multiply by 10000, the errors in
representation become greater than your saftey margin.  I suspect,
though I haven't tried it, that if you raise kDelta to 1E-14 your
example program will work.

					--Tom Lippincott
					  lippin@math.berkeley.edu

	"Thank you for observing all saftey precautions."
					--Dark Star