# [R6RS] NaNs and infinities

dyb at cs.indiana.edu dyb at cs.indiana.edu
Wed Mar 8 09:53:30 EST 2006

> > > +inf.0 represents the result of (/ 1.0 0.0).
> > > -inf.0 represents the result of (/ -1.0 0.0).
> > > +nan.0 represents the result of (/ 0.0 0.0).
> >
> > Are we going to require implementions to return values in these cases,
> > or can they raise exceptions?
>
> Good question.  If we were to allow implementations to
> raise an exception in all circumstances that would result
> in an infinity or NaN with IEEE-754 arithmetic, and allow
> them to raise an exception when they see any of the external
> representations +inf.0, -inf.0, +nan.0, -nan.0, nan.0,
> then we could write a much tighter spec that requires IEEE
> behavior for infinities and NaNs.  I like that.

Me too, in case I didn't already make that clear.

> > > (fl= +nan.0 fl)  ==>  unspecified
> > > (fl= +nan.0 fl)  ==>  unspecified  ; this example appears twice
> > > (fl< +nan.0 fl)  ==>  unspecified
> >
> > I'd prefer these all return #f.
>
> With our (admittedly broken) definition of +nan.0, that means
> non-IEEE systems would probably *have* to raise an exception
> when dividing by an inexact zero.

That's okay with me.

> > > The inexact-floor, inexact-ceiling, inexact-truncate, and
> > > inexact-round procedures signal an error when passed an
> > > infinity or NaN, or when no integral number satisfying
> > > the above conditions exists.
> >
> > See comment for fl versions above.
>
> Which comment for which fl versions?

The comment for flfloor, flceiling, etc., where I said they should act as
identities on NaNs and infinities.

> > > (integer? -inf.0)  ==>  #f
> >
> > If (integer? 0.0) => #t, I'd prefer that (integer? -inf.0) be #t.
>
> If (integer? -inf.0) is #t, then -inf.0 would be an integer
> that isn't rational, which seems strange.  We just went to
> some trouble to eliminate a similar strangeness in SRFI 77,
> and I'm not eager to create that problem again.

I would have (rational? -inf.0) be #t as well.

Beyond a certain number of digits, all IEEE floats are integers.  +inf.0
and -inf.0, which represent the limits that the sequence of representable
floats apprach in either direction, should also be integers.

I'm not even sure why you treat +nan.0 as irrational.  This is definitely
a departure from R5RS, which not only allows rational? to be the same as
real? but states that this is how it will be in most implementations.
I don't understand why you have departed from that.

> In particular, the external representation
> nan.0 might just be a name for 17.0, +nan.0 might be a
> name for -46.3, and -nan.0 might be a name for 3.14159.

> Similarly, +inf.0 and -inf.0 might be names for the
> largest and smallest representable inexact reals.

With these values, integer? returns true for nan.0, +inf.0, and -inf.0,
and rational? returns true for all of these values.

> I like both ideas, especially the second.
>
> > > (flfloor +inf.0)  ==>  +inf.0      ; should be unspecified or "is an error"
> >
> > I prefer +inf.0.  I really dislike "is an error".
>
> Me too.  I wouldn't object to "may raise a &domain exception",
> but I would object to "should raise".

I prefer requiring +inf.0.

> > > (/ 0 0.0)  ==>  unspecified
> >
> > I would prefer (/ 0 0.0) return 0.  In my understanding of the IEEE world,
> > 0.0 is something that is just slightly on the positive side of 0, so
> > (/ 0 0.0) is 0.  Is the intent is to accommodate non-IEEE-arithmetic,
> > or is there some differing opinion on what this should return in a system
> > that supports IEEE arithmetic?
>
> If 0.0 represents an ever-so-slightly positive real,
> then why does IEEE-754 require (/ 0.0 0.0) to evaluate
> to a NaN instead of 1.0?

+inf.0 represents a whole range of numbers.  0.0=1/+inf.0, so 0.0 also
represents a whole range of numbers---all infinitesimally close to but not
quite zero.  0.0/0.0 is +nan.0 for the same reason that +inf.0/+inf.0 is
+nan.0, because we really have no idea what the value is.  Indeed, since
0.0=1/+inf.0, we can reduce 0.0/0.0 to +inf.0/+inf.0 = +nan.0.
Of course, this implies that (= +inf.0 +inf.0) and (= 0.0 0.0) should
be #f, so I agree that the system is somewhat ad-hoc.

> The behaviors exhibited by Larceny, Gambit, Bigloo, Java,
> and Common Lisp preserve the closure properties that were
> part of the rationale for SRFI 77.  The behaviors exhibited
> by MzScheme, Chez Scheme, and MIT Scheme do not have those
> closure properties, but they are very much in tune with the
> model for arithmetic that was adopted in the RRRS that came
> out of the Brandeis meeting.

Can you elaborate?  I don't see in your table any case where MzScheme,
Chez Scheme, or MIT Scheme violate the closure properties laid out by SRFI
77.  SRFI 77 claims separate closure properties for exact integers and
exact rationals, which don't apply in any of the cases in your table.
For reals and complex numbers it says:

The reals (and inexact reals) are closed under some (often inexact)
interpretation of rational and irrational operations such as exp and sin,
but are not closed under operations such as log, sqrt, and expt.  The
complex (and inexact complex) numbers are closed under the largest set of
operations.

In other words, it says they aren't closed, but I'll try to read between
the lines and make some reasonable assumptions.  So where can the problem
be?  The cases where MzScheme, Chez Scheme, and MIT Scheme return exact 0
don't involve closure of inexact numbers and obviously don't violate
closure of real numbers.  You can't be talking about the (sqrt 3) case,
since the systems agree on that.  So you must be talking about the two
cases where MzScheme and Chez Scheme signal an error.  But no, MIT Scheme
agrees with Larceny, Bigloo, and Java in that case.  If you are talking
about that case, then why not make the same exception for reals that you
make for exact rationals, i.e., for division by (exact) 0?

> Some of the participants in the SRFI 77 discussion would
> argue as I would.  IIRC, the participants who argued for
> allowing (* 0 3.5) to evaluate to an exact 0 were mainly
> concerned that this behavior be allowed; I don't remember
> anyone arguing that it should be required (although there
> were some pretty strange things said in that discussion).

I would prefer that it be required, but I'll settle for allowed.
Similarly, I prefer that (/ x 0) be an error, but I'll settle for allowed.

I'm interested in your response to this comment in my earlier note:

> > (flonum->fixnum -inf.0)  ==>  -8388608      ; correct under supposition

> Even under the supposition that the fixnum range is [-8388608,8388607], I
> really dislike this.  I think this should raise an exception (in safe
> mode, of course), as should any input outside of the fixnum range.

One more thing:  I'd prefer that we not allow nan.0 and inf.0, partly
because these were previously valid R5RS symbols, and partly to avoid the
extra overhead in the reader.  I think +nan.0, -nan.0, +inf.0, and -inf.0
are sufficient.

Kent