[R6RS] NaNs and infinities

dyb at cs.indiana.edu dyb at cs.indiana.edu
Tue Mar 7 15:22:28 EST 2006


> Mike is revising the arithmetic SRFI, and some questions
> about infinities and NaNs have come up.  I'd like to
> bring these subtleties to the attention of the editors,
> and get these details into the R6RS archives.
>
> > OK, but (nan? (sqrt -1.0)) => #t, right?

I'm probably missing some context, but shouldn't (sqrt -1.0) be 0.0+1.0i?

> +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?

> inf.0, +inf.0, -inf.0, nan.0, +nan.0, and -nan.0 are
> external representations for flonums.
>
> (real-valued? +nan.0)  ==>  #t
> (rational-valued? +nan.0)  ==>  #f ; should be unspecified

I don't know what these are intended to do.

> (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.

> In safe mode, flfloor, flceiling, fltruncate, and flround
> signal an error when passed an infinity or NaN.  In unsafe
> mode, all bets are off.  In both safe and unsafe mode,
> these procedures signal an error if no integral flonum
> satisfying the above conditions exists.  [Note: this is
> not a good idea IMO, and is inconsistent with the examples
> in any case.]

I'd prefer that each behave as the identify when passed an infinity or
NaN, even in safe mode.  Those are the correct values in my understanding
of the IEEE arithmetic model.  I strongly dislike requiring them to
raise an exception

> (fllog -inf.0)  ==>  +nan.0

Fine.

> 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.

> (+ +nan.0 x)  ==>  +nan.0          ; should be unspecified

I wish we didn't have to leave this unspecified.  It takes all the fun out
of NaNs, which are supposed to be contageous.

Would it be better to allow implementations that don't support IEEE
arithmetic to leave NaNs and infinities out, and create a more precise
specification for those that do support IEEE arithmetic?

> (* +nan.0 x)  ==>  +nan.0          ; should be unspecified

I would like (* +nan.0 0) to be 0 and in other cases for this to be
+nan.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?

> (/ 0.0 0)  ==>  +nan.0

I'd prefer that (/ 0.0 0) raise an exception.  0 really is 0 and (/
<anything> 0) is undefined.  In my view, NaNs should be produced only when
we know there is a value but don't know what the value should be.

> (integer? -inf.0)  ==>  #f

If (integer? 0.0) => #t, I'd prefer that (integer? -inf.0) be #t.

> (real-valued? -inf.0)  ==>  #t
> (rational-valued? -inf.0)  ==>  #f ; should be unspecified

Again, I don't know what these predicates are intended to do.

> (fldenominator +inf.0)  ==>  1.0    ; should be unspecified
> (fldenominator -inf.0)  ==>  1.0    ; should be unspecified

I prefer 1.0 but don't really care.  Should we say at least that the
denominator in the first case is positive, not +nan.0, and not +inf.0
or simply that (/ (flnumerator +inf.0) (fldenominator +inf.0)) ==> +inf.0,
with something similar for the second case?

> (flfloor +inf.0)  ==>  +inf.0       ; should be unspecified or "is an error"

I prefer +inf.0.  I really dislike "is an error".

> (flceiling -inf.0)  ==>  -inf.0     ; should be unspecified or "is an error"

I prefer -inf.0.  I really dislike "is an error".

> (flexp +inf.0)  ==>  +inf.0
> (flexp -inf.0)  ==>  0.0
> (fllog +inf.0)  ==>  +inf.0         ; should be unspecified

I prefer +inf.0.  We should at least require (exp (fllog +inf.0)) ==> +inf.0.

I'd like to know the rationale for these unspecified items.  Some of them
are apparently to accommodate non-IEEE arithmetic.  Are there other
rationales at play?

> (flsqrt +inf.0)  ==>  +inf.0                ; should be unspecified

I prefer +inf.0.  We should at least require that
(let ([x (flsqrt +inf.0)]) (* x x)) ==> +inf.0. 

> (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.

> (+ +inf.0 -inf.0)  ==>  +nan.0      ; should be unspecified
> (- +inf.0 +inf.0)  ==>  +nan.0      ; should be unspecified

I prefer +nan.0.

> (/ 1.0 0)  ==>  +inf.0

I prefer this raise an exception as argued above for (/ 0.0 0).

> (/ +inf.0)  ==>  0.0                ; should be unspecified

I prefer 0.0.

> (abs -inf.0)  ==>  +inf.0           ; should be unspecified, I think

I prefer +inf.0;

> (floor +inf.0)  ==>  +inf.0         ; should be unspecified or "is an error"

I prefer +inf.0.  I really dislike "it is an error"

> (ceiling -inf.0)  ==>  -inf.0       ; should be unspecified or "is an error"

I prefer -inf.0.  I really dislike "it is an error"

> (rationalize +inf.0 3)  ==>  +inf.0 ; should be unspecified

I prefer +inf.0.

> (rationalize 3 +inf.0)  ==>  0      ; should be 0.0

Yes, should be 0.0.  (Actually, I prefer the original version of
rationalize that wasn't exactness preserving, so that one got an extact
rational out.  But if we aren't going to have that, then this should be
0.0.)

> (log +inf.0)  ==>  +inf.0           ; should be unspecified

I prefer +inf.0.

> (sqrt +inf.0)  ==>  +inf.0          ; should be unspecified

See comment about flsqrt above.

> The following behavior is strongly encouraged but not required:
>
> (fl= +nan.0 +nan.0)  ==>  #f

I wish it were required.

> Finally, requiring 0 = (* 0 x) = (* x 0) is a change from R5RS.
> Although many Scheme programmers have wanted this for years,
> there are many other Scheme programmers who don't want it.
> We should discuss this some more.

Many have had 0 = (* 0 x) = (* x 0) for years without complaint, too.

Kent



More information about the R6RS mailing list