[mercury-users] IEEE float (was: Newbie problem)

Richard A. O'Keefe ok at atlas.otago.ac.nz
Mon Jun 21 10:38:37 AEST 1999


	>From the Mercury library reference manual:
	
	    % Note that implementations which support IEEE floating point
	    % should ensure that in cases where the only valid answer is a "NaN"
	    % (the IEEE float representation for "not a number"), the det
	    % functions here will halt with a runtime error (or throw an exception)
	    % rather than returning a NaN.  Quiet (non-signalling) NaNs have a
	    % semantics which is not valid in Mercury, since they don't obey the
	    % axiom "all [X] X = X".
	
	So, even on machines which support IEEE floating point, the intent is that
	the Mercury `float' type will never have any NaN values.
	
This makes perfect sense, *BUT* it violates both the letter and the
spirit of the IEEE standards (754 and 854).  If you are happy to say
that Mercury does not conform to the IEEE standard and that simple
algorithms translated from Pascal, Fortran, or C (which *does* offer
IEEE compliance as an option in C9x) to Mercury will *not* have the
same behaviour, then that's fine.

	This design decision was arrived at after much thought.
	However, I'd be very interested to hear any user feedback on this issue.
	
However, while the IEEE standards (and LIA standards) require certain
operations, they do NOT require them to have the obvious names.  Mercury
could reclaim IEEE conformance by offering

    ieee_compare(O, X, Y) ==>
    O = (<) iff X < Y according to IEEE rules,
    O = (=) iff X = Y according to IEEE rules,
    O = (>) iff X > Y according to IEEE rules,
    failure otherwise.

That is, if NaNs were allowed as values.
Note in particular that this point means that the argument against
allowing NaNs in Mercury is bogus:  The fact that a QNaN Q does
not satisfy "ieee_numeric_equal(Q, Q)" does *NOT* require or in
any way imply that it does not satisfy "Q = Q".  I repeat, the
equality test that the IEEE and LIA standards talk about does NOT
have to be spelled '='.  Let's face it, there's a rather nasty
property that IEEE "equality" has even if you DO rule out NaNs
and infinities:

    X is 0.0,
    Y is -X,
    ieee_compare(=, X, Y),
    \+ (X == Y).

Because X and Y have different behaviour (e.g. 1.0/X is +infinity,
while 1.0/Y is -infinity, and of course there's copysign() as well),
they must *not* be regarded as identical (unifying) by Mercury.
But the IEEE standards say they *must* compare equal.  The only
way I can see to solve that requires splitting '=' and IEEE
comparison apart.  That having been done, to ensure correct
behaviour with +/- 0.0, there remains no equality-based argument
against QNaNs.

	Note that unfortunately the current implementation does not yet fully
	implement this intent -- the library reference manual goes on to explain
	this:
	
	    % XXX Unfortunately the current Mercury implementation does not
	    % do that on all platforms, since neither ANSI C nor POSIX provide
	    % any portable way of ensuring that floating point operations
	    % whose result is not representable will raise a signal rather
	    % than returning a NaN.  (Maybe C9X will help...?)
	    % The behaviour is correct on Linux and Digital Unix,
	    % but not on Solaris, for example.

Let's take it one step at a time.
(0) I've demolished the argument that you should *want* to do this.

(1) ANSI C and POSIX do not provide a portable way of requiring that
    certain valid operations with defined results must raise signals.
    Why should they?  More to the point, how _can_ they?  There are
    perfectly good implementations of IEEE 754 arithmetic where the
    thing cannot be done at all, including some of the best.  If
    Digital UNIX means OSF/1 on an Alpha, the documentation frankly
    admits that in its default mode of operation, DEC C is *NOT*
    IEEE compliant.
	
(2) That rather misses the point of how IEEE arithmetic is *supposed*
    to be used.  The idea is that you do your calculation, and then
    you check at the end whether the result is unusual.  That's easy
    enough to do:  just check if the top 12 bits of the result match
    x11111111111.  This would be a pain if you did it after every
    operation, but of course you *don't* do it that way, that's not
    what IEEE arithmetic is about.  You check at the *end* before
    making any decisions based on the result.  Cody has published
    portable C code for doing this (and some other IEEE-related things);
    a tiny assembly code function or a similarly tiny gcc inline
    pattern would do the job too.  Yes, not fully portable, but you
    only need SPARC, PPC, Alpha, Intel, and maybe HP and m68k versions
    to cover most systems, and on others you'd be no worse than before.

(3) Note that it is not sufficient to rely on requesting floating
    point exceptions.  You still have to check *every* floating
    point number returned by C code.  What if a Mercury program
    calls quiet_nan(1) on a Solaris system?  The documentation for
    that says it returns "a quiet ... NaN" (ignoring the argument)
    and that it is not "affected by IEEE rounding or trapping modes"
    and does not "generate... any IEEE exceptions".  If it weren't
    in the library, it would be easy to write.  So Mercury itself
    would have to be responsible for
    - resetting floating point modes after every foreign call
    - checking the floating point results from foreign calls
    For example, X is sqrt(Y) would have to involve a check under the
    present scheme, but not under either of the schemes I've suggested.
    
C9x *does* include a binding to various IEEE facilities, BUT there is
no obligation that a C compiler support them at all, so Mercury will
still be stuck.

--------------------------------------------------------------------------
mercury-users mailing list
post:  mercury-users at cs.mu.oz.au
administrative address: owner-mercury-users at cs.mu.oz.au
unsubscribe: Address: mercury-users-request at cs.mu.oz.au Message: unsubscribe
subscribe:   Address: mercury-users-request at cs.mu.oz.au Message: subscribe
--------------------------------------------------------------------------



More information about the users mailing list