summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark H Weaver <mhw@netris.org>2011-01-28 23:32:20 -0500
committerAndy Wingo <wingo@pobox.com>2011-01-30 13:08:53 +0100
commitc960e55600962c45be7e623859eddca3fad87783 (patch)
treec2b39d47d31923d52eb01774b4611ca58038b31e
parent2e6e1933b4ca26793741cc0ec0832978f10c0c99 (diff)
downloadguile-c960e55600962c45be7e623859eddca3fad87783.tar.gz
Infinities and NaNs are no longer rational
* libguile/numbers.c (scm_rational_p): Return #f for infinities and NaNs, per R6RS. Previously it returned #t for real infinities and NaNs. They are still considered real by scm_real `real?' however, per R6RS. Also simplify the code. (scm_real_p): New implementation to reflect the fact that the rationals and reals are no longer the same set. Previously it just called scm_rational_p. (scm_integer_p): Simplify the code. * test-suite/tests/numbers.test: Add test cases for `rational?' and `real?' applied to infinities and NaNs. * doc/ref/api-data.texi (Real and Rational Numbers): Update docs to reflect the fact that infinities and NaNs are no longer rational, and that `real?' no longer implies `rational?'. Improve discussion of infinities and NaNs. * NEWS: Add NEWS entries, and combine with an earlier entry about infinities no longer being integers.
-rw-r--r--NEWS18
-rwxr-xr-xdoc/ref/api-data.texi73
-rw-r--r--libguile/numbers.c40
-rw-r--r--test-suite/tests/numbers.test12
4 files changed, 76 insertions, 67 deletions
diff --git a/NEWS b/NEWS
index 29798499c..5651b17ed 100644
--- a/NEWS
+++ b/NEWS
@@ -27,11 +27,6 @@ Previously, `(equal? +nan.0 +nan.0)' returned #f, although
both returned #t. R5RS requires that `equal?' behave like
`eqv?' when comparing numbers.
-*** Infinities are no longer integers.
-
-Following the R6RS, infinities (+inf.0 and -inf.0) are no longer
-considered to be integers.
-
*** `expt' and `integer-expt' changes when the base is 0
While `(expt 0 0)' is still 1, and `(expt 0 N)' for N > 0 is still
@@ -40,6 +35,19 @@ integer-expt. This is more correct, and conforming to R6RS, but seems
to be incompatible with R5RS, which would return 0 for all non-zero
values of N.
+*** Infinities are no longer integers, nor rationals
+
+scm_integer_p `integer?' and scm_rational_p `rational?' now return #f
+for infinities, per R6RS. Previously they returned #t for real
+infinities. The real infinities and NaNs are still considered real by
+scm_real `real?' however, per R6RS.
+
+*** NaNs are no longer rationals
+
+scm_rational_p `rational?' now returns #f for NaN values, per R6RS.
+Previously it returned #t for real NaN values. They are still
+considered real by scm_real `real?' however, per R6RS.
+
*** `inf?' and `nan?' now throw exceptions for non-reals
The domain of `inf?' and `nan?' is the real numbers. Guile now signals
diff --git a/doc/ref/api-data.texi b/doc/ref/api-data.texi
index a0ab2585f..4256e1833 100755
--- a/doc/ref/api-data.texi
+++ b/doc/ref/api-data.texi
@@ -492,10 +492,10 @@ are not rational, for example @m{\sqrt2, the square root of 2}, and
@m{\pi,pi}.
Guile can represent both exact and inexact rational numbers, but it
-can not represent irrational numbers. Exact rationals are represented
-by storing the numerator and denominator as two exact integers.
-Inexact rationals are stored as floating point numbers using the C
-type @code{double}.
+cannot represent precise finite irrational numbers. Exact rationals are
+represented by storing the numerator and denominator as two exact
+integers. Inexact rationals are stored as floating point numbers using
+the C type @code{double}.
Exact rationals are written as a fraction of integers. There must be
no whitespace around the slash:
@@ -518,26 +518,41 @@ example:
4.0
@end lisp
-The limited precision of Guile's encoding means that any ``real'' number
-in Guile can be written in a rational form, by multiplying and then dividing
-by sufficient powers of 10 (or in fact, 2). For example,
-@samp{-0.00000142857931198} is the same as @minus{}142857931198 divided by
-100000000000000000. In Guile's current incarnation, therefore, the
-@code{rational?} and @code{real?} predicates are equivalent.
-
-
-Dividing by an exact zero leads to a error message, as one might
-expect. However, dividing by an inexact zero does not produce an
-error. Instead, the result of the division is either plus or minus
-infinity, depending on the sign of the divided number.
+The limited precision of Guile's encoding means that any finite ``real''
+number in Guile can be written in a rational form, by multiplying and
+then dividing by sufficient powers of 10 (or in fact, 2). For example,
+@samp{-0.00000142857931198} is the same as @minus{}142857931198 divided
+by 100000000000000000. In Guile's current incarnation, therefore, the
+@code{rational?} and @code{real?} predicates are equivalent for finite
+numbers.
-The infinities are written @samp{+inf.0} and @samp{-inf.0},
-respectively. This syntax is also recognized by @code{read} as an
-extension to the usual Scheme syntax. The infinities are considered to
-be inexact, non-integer values.
-Dividing zero by zero yields something that is not a number at all:
-@samp{+nan.0}. This is the special `not a number' value.
+Dividing by an exact zero leads to a error message, as one might expect.
+However, dividing by an inexact zero does not produce an error.
+Instead, the result of the division is either plus or minus infinity,
+depending on the sign of the divided number and the sign of the zero
+divisor (some platforms support signed zeroes @samp{-0.0} and
+@samp{+0.0}; @samp{0.0} is the same as @samp{+0.0}).
+
+Dividing zero by an inexact zero yields a @acronym{NaN} (`not a number')
+value, although they are actually considered numbers by Scheme.
+Attempts to compare a @acronym{NaN} value with any number (including
+itself) using @code{=}, @code{<}, @code{>}, @code{<=} or @code{>=}
+always returns @code{#f}. Although a @acronym{NaN} value is not
+@code{=} to itself, it is both @code{eqv?} and @code{equal?} to itself
+and other @acronym{NaN} values. However, the preferred way to test for
+them is by using @code{nan?}.
+
+The real @acronym{NaN} values and infinities are written @samp{+nan.0},
+@samp{+inf.0} and @samp{-inf.0}. This syntax is also recognized by
+@code{read} as an extension to the usual Scheme syntax. These special
+values are considered by Scheme to be inexact real numbers but not
+rational. Note that non-real complex numbers may also contain
+infinities or @acronym{NaN} values in their real or imaginary parts. To
+test a real number to see if it is infinite, a @acronym{NaN} value, or
+neither, use @code{inf?}, @code{nan?}, or @code{finite?}, respectively.
+Every real number in Scheme belongs to precisely one of those three
+classes.
On platforms that follow @acronym{IEEE} 754 for their floating point
arithmetic, the @samp{+inf.0}, @samp{-inf.0}, and @samp{+nan.0} values
@@ -545,13 +560,6 @@ are implemented using the corresponding @acronym{IEEE} 754 values.
They behave in arithmetic operations like @acronym{IEEE} 754 describes
it, i.e., @code{(= +nan.0 +nan.0)} @result{} @code{#f}.
-While @samp{+nan.0} is not @code{=} to itself, it is @code{eqv?} to
-itself.
-
-To test for the special values, use the functions @code{inf?} and
-@code{nan?}. To test for numbers than are neither infinite nor a NaN,
-use @code{finite?}.
-
@deffn {Scheme Procedure} real? obj
@deffnx {C Function} scm_real_p (obj)
Return @code{#t} if @var{obj} is a real number, else @code{#f}. Note
@@ -566,9 +574,6 @@ Return @code{#t} if @var{x} is a rational number, @code{#f} otherwise.
Note that the set of integer values forms a subset of the set of
rational numbers, i. e. the predicate will also be fulfilled if
@var{x} is an integer number.
-
-Since Guile can not represent irrational numbers, every number
-satisfying @code{real?} also satisfies @code{rational?} in Guile.
@end deffn
@deffn {Scheme Procedure} rationalize x eps
@@ -607,12 +612,12 @@ NaN, @code{#f} otherwise.
@deffn {Scheme Procedure} nan
@deffnx {C Function} scm_nan ()
-Return NaN.
+Return @samp{+nan.0}, a @acronym{NaN} value.
@end deffn
@deffn {Scheme Procedure} inf
@deffnx {C Function} scm_inf ()
-Return Inf.
+Return @samp{+inf.0}, positive infinity.
@end deffn
@deffn {Scheme Procedure} numerator x
diff --git a/libguile/numbers.c b/libguile/numbers.c
index 8513fea82..608cf7a71 100644
--- a/libguile/numbers.c
+++ b/libguile/numbers.c
@@ -3281,8 +3281,8 @@ SCM_DEFINE (scm_real_p, "real?", 1, 0, 0,
"fulfilled if @var{x} is an integer number.")
#define FUNC_NAME s_scm_real_p
{
- /* we can't represent irrational numbers. */
- return scm_rational_p (x);
+ return scm_from_bool
+ (SCM_I_INUMP (x) || SCM_REALP (x) || SCM_BIGP (x) || SCM_FRACTIONP (x));
}
#undef FUNC_NAME
@@ -3294,18 +3294,12 @@ SCM_DEFINE (scm_rational_p, "rational?", 1, 0, 0,
"fulfilled if @var{x} is an integer number.")
#define FUNC_NAME s_scm_rational_p
{
- if (SCM_I_INUMP (x))
- return SCM_BOOL_T;
- else if (SCM_IMP (x))
- return SCM_BOOL_F;
- else if (SCM_BIGP (x))
- return SCM_BOOL_T;
- else if (SCM_FRACTIONP (x))
+ if (SCM_I_INUMP (x) || SCM_BIGP (x) || SCM_FRACTIONP (x))
return SCM_BOOL_T;
else if (SCM_REALP (x))
- /* due to their limited precision, all floating point numbers are
- rational as well. */
- return SCM_BOOL_T;
+ /* due to their limited precision, finite floating point numbers are
+ rational as well. (finite means neither infinity nor a NaN) */
+ return scm_from_bool (DOUBLE_IS_FINITE (SCM_REAL_VALUE (x)));
else
return SCM_BOOL_F;
}
@@ -3317,23 +3311,15 @@ SCM_DEFINE (scm_integer_p, "integer?", 1, 0, 0,
"else.")
#define FUNC_NAME s_scm_integer_p
{
- double r;
- if (SCM_I_INUMP (x))
- return SCM_BOOL_T;
- if (SCM_IMP (x))
- return SCM_BOOL_F;
- if (SCM_BIGP (x))
+ if (SCM_I_INUMP (x) || SCM_BIGP (x))
return SCM_BOOL_T;
- if (!SCM_INEXACTP (x))
- return SCM_BOOL_F;
- if (SCM_COMPLEXP (x))
- return SCM_BOOL_F;
- r = SCM_REAL_VALUE (x);
- if (isinf (r))
+ else if (SCM_REALP (x))
+ {
+ double val = SCM_REAL_VALUE (x);
+ return scm_from_bool (!isinf (val) && (val == floor (val)));
+ }
+ else
return SCM_BOOL_F;
- if (r == floor (r))
- return SCM_BOOL_T;
- return SCM_BOOL_F;
}
#undef FUNC_NAME
diff --git a/test-suite/tests/numbers.test b/test-suite/tests/numbers.test
index d116b6f63..36e31281b 100644
--- a/test-suite/tests/numbers.test
+++ b/test-suite/tests/numbers.test
@@ -1505,6 +1505,11 @@
(pass-if (real? (+ 1 fixnum-max)))
(pass-if (real? (- 1 fixnum-min)))
(pass-if (real? 1.3))
+ (pass-if (real? +inf.0))
+ (pass-if (real? -inf.0))
+ (pass-if (real? +nan.0))
+ (pass-if (not (real? +inf.0-inf.0i)))
+ (pass-if (not (real? +nan.0+nan.0i)))
(pass-if (not (real? 3+4i)))
(pass-if (not (real? #\a)))
(pass-if (not (real? "a")))
@@ -1515,7 +1520,7 @@
(pass-if (not (real? (current-input-port)))))
;;;
-;;; rational? (same as real? right now)
+;;; rational?
;;;
(with-test-prefix "rational?"
@@ -1526,6 +1531,11 @@
(pass-if (rational? (+ 1 fixnum-max)))
(pass-if (rational? (- 1 fixnum-min)))
(pass-if (rational? 1.3))
+ (pass-if (not (rational? +inf.0)))
+ (pass-if (not (rational? -inf.0)))
+ (pass-if (not (rational? +nan.0)))
+ (pass-if (not (rational? +inf.0-inf.0i)))
+ (pass-if (not (rational? +nan.0+nan.0i)))
(pass-if (not (rational? 3+4i)))
(pass-if (not (rational? #\a)))
(pass-if (not (rational? "a")))