floating point comparisons illegitimate?

Tim Peters uunet!ksr.com!tim
Sun Mar 24 12:28:49 PST 1991


>  [PLS]
>  ...
>  If a compiler sees
>    if (1.0 + EPS .EQ. 1.0)
>  is it justified in optimizing it to
>    if (EPS .EQ. 0.0)
>  If not, why not.

Since that's a Fortran fragment, you need a Fortran lawyer, and you get
three answers:

1) Technical answer #1:  If EPS is any type but REAL, no it can't.  When
   X and Y have different types, F77 defines the meaning of
	X .relational. Y
   to be the meaning of
	((X) - (Y)) .relational. 0
   So if, e.g., EPS is DOUBLE PRECISION, then the type of 1.0+EPS is
   also DOUBLE, while the type of 1.0 is REAL, so this clause applies
   and the meaning of
	(1.0+EPS .EQ. 1.)
   is the meaning of
	((1.0+EPS) -  1.)) .EQ. 0
   F77 explicitly prohibits optimizations across parentheses, so a
   compiler must not change this to
	(EPS) .EQ. 0

1a) Gloss to #1:  By most accounts, the answer to #1 was not X3J3's
    *intent* -- they were really just trying to hint at how type
    conversion gets done in comparisons without actually bothering to
    spell it out.  Nevertheless, it's what F77 says.

2) Technical answer #2:  If EPS is REAL, all the std says is that the
   compiler is free to evaluate any expression "relationally equivalent"
   to "1.+EPS.EQ.1", where "relationally equivalent" is undefined, but
   where I believe most reasonable people would take it as allowing
   evaluating "EPS.EQ.0" instead.

3) Practical answer:  Of course not -- no Fortran compiler jockey worth
   their salt would impose a marginal optimization they know will break
   countless programs.  That's a "quality of implementation" kind of
   issue that has to be decided on the basis of the Fortran culture, and
   the std is no help in such matters.  The C culture may well come to
   different answers (indeed, if that was a C fragment I believe X3J11's
   "as if" rule would explicitly prohibit the optimization -- but the
   Fortran world doesn't have-- and wouldn't abide! --an optimization- 
   inhibiting rule that severe).

>  The C standard chose to make information about precision and exponent
>  range available through the environment.  In part because tricks like
>  the above don't work on a lot of machines.

F90 too -- and I think all languages are moving in this direction.  Good
thing, since most people who think they need this info don't know how to
write code to compute it correctly anyway <grin/sigh>.

>  ...
>  A couple of the previous messages have said, in effect, that the IEEE
>  standard requires a minimum precision implementation.  Does it?

I'd say yes & no.

Yes, because 754/854 define every bit of the results required for every
combination of operation, operands, and various options for rounding
mode & "precision control", and these definitions generally require that
if X and Y are the same type, X op Y is of that type too & is fully
defined by knowing X, Y, op, and the values of the options (i.e., the
result is fully defined without reference to the context (if any) in
which "X op Y" appears).

No, because 754/854 say nothing about how language constructions map to
IEEE features.  So, e.g., if your compiler does the entire RHS of

        sometype t, x, y, z
	t = x + y + z

in an extended (wrt sometype) precision, it's not a violation of the
754/854 stds unless your compiler docs *claim* that its "+" operator
maps directly into the sometype flavor of IEEE's addition operation.
In other words, 754/854 just define an arithmetic, not a way to get at
it.

As the traffic on this list demonstrates, there's no consensus on "how
to get at it" yet; defining a language binding may be harder than
defining a good arithmetic ...

except-in-assembler<grin>-ly y'rs  - tim


Tim Peters   Kendall Square Research Corp
timaksr.com,  ksr!timaharvard.harvard.edu



More information about the Numeric-interest mailing list