[R6RS] NaNs and infinities

William D Clinger will at ccs.neu.edu
Wed Mar 8 18:31:30 EST 2006


Warning: This message contains more tedious but possibly
controversial details.

>From today's conference call, it sounds as though we are
agreed to write the R6RS as though implementations have
IEEE-like infinities and NaNs, allowing implementations
to raise an &implementation-restriction exception when
can't represent an infinite or NaN that the R6RS specifies
as the result of some computation.

Applying that decision to my original message in this
thread got rid of all of the totally unspecified values!
Some examples still allow 0 or 0.0, or +inf.0 or an
exception.  Here is a revision of my original message.

Note that some systems may have multiple infinities that
all print as +inf.0 or -inf.0, and may have 2^52 or more
NaNs that all print as +nan.0.  In what follows, +inf.0
and -inf.0 stand for any positive or negative infinity,
respectively, and +nan.0 stands for any NaN, including
NaNs that might print as -nan.0.

                                * * *

Assuming Mike was asking about flsqrt:
> OK, but (nan? (flsqrt -1.0)) => #t, right?

Right.

Here is what the current (unpublished) working draft of
SRFI 77 actually requires, with my remarks as comments:

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

inf.0, +inf.0, -inf.0, nan.0, +nan.0, and -nan.0 are
external representations for flonums.

[Kent suggested we get rid of nan.0, and I think that
may be a good idea, but I'd like to ask Brad Lucier
about it.  In any case, we need to mention that systems
that can't represent infinities or NaNs must raise an
&implementation-restriction when they read these
external representations.]

(real? +nan.0)  ==>  #t
(rational? +nan.0)  ==>  #f
(number? +nan.0)  ==>  #t
(complex? +nan.0)  ==>  #t
(rational? +nan.0)  ==>  #f        ; this example appears twice
(real-valued? +nan.0)  ==>  #t     ; should be #f
(rational-valued? +nan.0)  ==>  #f
(string->number "+nan.0")  ==>  +nan.0
(fl= +nan.0 fl)  ==>  unspecified  ; should be #f
(fl= +nan.0 fl)  ==>  unspecified  ; this example appears twice
(fl< +nan.0 fl)  ==>  unspecified  ; should be #f
(fl/ 0.0 0.0)  ==>  +nan.0

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:  That is inconsistent with the examples in the
draft SRFI, and is also inconsistent with IEEE-754.
For consistency with IEEE-754 in the default mode that
dominates current practice (and maybe in any case; I'm
too lazy to check), these procedures should act as the
identity on infinities and NaNs.]

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

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.

[Note:  That is questionable.  Kent and I would prefer
they just return their argument when given an infinite or
NaN, for consistency with IEEE-754.  The argument for
consistency with IEEE-754 is not as strong here as it
is for flfloor, etc, but it still carries some weight.
Brad Lucier argued, however, that infinities and NaNs
should not be in the domain of floor, round, ceiling,
or truncate, and that "returning these values as results
implies, to me, that they are integers, and I believe
they aren't integers, since they aren't rational."  See
http://srfi.schemers.org/srfi-77/mail-archive/msg00404.html,
question 9.]

(+ +inf.0 -inf.0)  ==>  +nan.0
(+ +nan.0 x)  ==>  +nan.0
(* +nan.0 x)  ==>  +nan.0
(- +inf.0 +inf.0)  ==>  +nan.0
(/ 0 0.0)  ==>  unspecified        ; should be 0 or +nan.0
(/ 0.0 0)  ==>  +nan.0             ; +nan.0 or may raise exception
(/ 0.0 0.0)  ==>  +nan.0
(rationalize +inf.0 +inf.0)  ==>  +nan.0
(real? -inf.0)  ==>  #t
(rational? -inf.0)  ==>  #f        ; Kent doesn't like this
(complex? +inf.0)  ==>  #t
(integer? -inf.0)  ==>  #f         ; Kent doesn't like this
(real-valued? -inf.0)  ==>  #t
(rational-valued? -inf.0)  ==>  #f ; Kent wouldn't like this
(inexact? +inf.0)  ==>  #t
(string->number "+inf.0")  ==>  +inf.0
(string->number "-inf.0")  ==>  -inf.0
(fl= +inf.0 +inf.0)  ==>  #t
(fl= -inf.0 +inf.0)  ==>  #f
(fl= -inf.0 -inf.0)  ==>  #t
(fl/ 1.0 0.0)  ==>  +inf.0
(fl/ -1.0 0.0)  ==>  -inf.0
(flnumerator +inf.0)  ==>  +inf.0
(flnumerator -inf.0)  ==>  -inf.0
(fldenominator +inf.0)  ==>  1.0
(fldenominator -inf.0)  ==>  1.0
(flfloor +inf.0)  ==>  +inf.0
(flceiling -inf.0)  ==>  -inf.0
(flexp +inf.0)  ==>  +inf.0
(flexp -inf.0)  ==>  0.0
(fllog +inf.0)  ==>  +inf.0
(fllog 0.0)  ==>  -inf.0
(fllog -inf.0)  ==>  +nan.0
(flatan -inf.0)  ==>  -1.5707963267948965   ; depends on precision etc
(flatan +inf.0)  ==>  1.5707963267948965    ; depends on precision etc
(flsqrt +inf.0)  ==>  +inf.0
(flonum->fixnum -inf.0)  ==>  -8388608      ; flush this procedure
(= +inf.0 +inf.0)  ==>  #t
(= -inf.0 +inf.0)  ==>  #f
(= -inf.0 -inf.0)  ==>  #t
(< -inf.0 x +inf.0)  ==>  #t        ; provided x is neither infinite nor NaN
(> +inf.0 x -inf.0)  ==>  #t        ; provided x is neither infinite nor NaN
(positive? +inf.0)  ==>  #t
(negative? -inf.0)  ==>  #t
(max +inf.0 x)  ==>  +inf.0
(min -inf.0 x)  ==>  -inf.0
(+ +inf.0 +inf.0)  ==>  +inf.0
(+ +inf.0 -inf.0)  ==>  +nan.0
(+ 5 +inf.0)  ==>  +inf.0
(* -5 +inf.0)  ==>  -inf.0
(* +inf.0 +inf.0)  ==>  +inf.0
(* +inf.0 -inf.0)  ==>  -inf.0
(+ +inf.0 x)  ==>  +inf.0           ; provided x neither infinite nor NaN
(+ -inf.0 x)  ==>  -inf.0           ; provided x neither infinite nor NaN
(- +inf.0 +inf.0)  ==>  +nan.0
(/ 0.0)  ==>  +inf.0
(/ 1.0 0)  ==>  +inf.0              ; +inf.0 or may raise exception
(/ -1 0.0)  ==>  -inf.0
(/ +inf.0)  ==>  0.0
(abs -inf.0)  ==>  +inf.0
(floor +inf.0)  ==>  +inf.0
(ceiling -inf.0)  ==>  -inf.0
(rationalize +inf.0 3)  ==>  +inf.0
(rationalize +inf.0 +inf.0)  ==>  +nan.0
(rationalize 3 +inf.0)  ==>  0      ; should be 0.0
(exp +inf.0)  ==>  +inf.0
(exp -inf.0)  ==>  0.0
(log +inf.0)  ==>  +inf.0
(log 0.0)  ==>  -inf.0
(log -inf.0)  ==>  +inf.0+pii
(atan -inf.0)  ==>  -1.5707963267948966  ; depends on precision etc
(atan +inf.0)  ==>  1.5707963267948966   ; depends on precision etc
(sqrt +inf.0)  ==>  +inf.0
(sqrt -inf.0)  ==>  +inf.0i
(magnitude (make-rectangular x1 x2))  ==>  +inf.0  ; if x1 or x2 infinity
(angle +inf.0)  ==>  0.0
(angle -inf.0)  ==>  pi

The following behavior is strongly encouraged but not required:

(fl= +nan.0 +nan.0)  ==>  #f             ; should be required

Will



More information about the R6RS mailing list