Path: utzoo!utgpu!watmath!clyde!att!osu-cis!tut.cis.ohio-state.edu!mailrus!cornell!uw-beaver!teknowledge-vaxc!sri-unix!quintus!ok
From: ok@quintus.uucp (Richard A. O'Keefe)
Newsgroups: comp.lang.fortran
Subject: Re: .GT. is not transitive
Keywords: interest amusement floating-point
Message-ID: <809@quintus.UUCP>
Date: 5 Dec 88 06:06:54 GMT
References: <791@quintus.UUCP> <3069@ttrdc.UUCP>
Sender: news@quintus.UUCP
Reply-To: ok@quintus.UUCP (Richard A. O'Keefe)
Organization: Quintus Computer Systems, Inc.
Lines: 46

In article <3069@ttrdc.UUCP> levy@ttrdc.UUCP (Daniel R. Levy) writes:
>In article <791@quintus.UUCP>, ok@quintus writes:
>> I offer the following F77 program for your interest and amusement.
>> On VAXen it prints "BROKEN".  On Sun3s it prints "BROKEN".  On a
>> Sequent (BSD UNIX, 386/387 processor, own Fortran) it prints "OK".
>
>Is the bug machine-specific?  It also prints "BROKEN" on VMS FORTRAN 4.2-102,
>which surprised me since DEC's VMS FORTRAN is generally an excellent compiler.

Although I had the program print "BROKEN" under certain circumstances,
I meant by that only that the behaviour violated ordinary mathematical
intuition.  I don't know what the Fortran standard says about this, but
I suspect that technically it is *not* a bug.  Here it is again:

	X = 1000000002
	Y = 1000000001.0D0
	Z = 1000000000.0E0

	IF (X.GT.Y .AND. Y.GT.Z .AND..NOT. X.GT.Z) STOP 'BROKEN'

where X: integer, Y: double precision, Z: real.
What's going on here?  Well, the comparison of X with Y is likely to be
done by converting X to the same kind of float as Y, namely double
precision.  Similarly, the comparison of Y with Z is likely to be done
by converting Z to the same kind of float as Y, namely double precision.
In neither case was any information lost from either operand.  But the
comparison of X with Z is done by converting X to the same kind of float
as Z, namely SINGLE precision, and in this case enough of X's precision
is lost for FLOAT(X) to compare equal to Z.  The key is that
    precision(DOUBLE PRECISION) >= precision(INTEGER) > precision(REAL).

Now on a 68881 or 83087, the floating-point co-processor is carrying around
80 bits per FP register anyway, so the chances are that the comparison is
being done in double or better precision.

The point is that if you don't want to be surprised by non-transitivity
of comparison, when two operands of different types are met, they should
both be converted to something which has sufficient range and sufficient
precision to represent both operands without loss of information.  With
the usual Fortran (and Common Lisp!) rules, it is very easy to make up
examples like
	IF (I.EQ.Y .AND. Y.EQ.K .AND. I.GT.K) STOP 'BROKEN'

I did say that this was offered for interest and amusement, and if
anyone took it as a claim that Sun's or anyone else's compilers violate
anything but the Law of Least Surprise, I apologise.