[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Large changes to numerics coming
From: |
Mark H Weaver |
Subject: |
Large changes to numerics coming |
Date: |
Tue, 25 Jan 2011 23:22:02 -0500 |
User-agent: |
Gnus/5.13 (Gnus v5.13) Emacs/23.1 (gnu/linux) |
Hello all,
I have a very large set of changes to guile numerics for better
compliance to R6RS, including a massive increase in the number of test
cases in numbers.test. All that remains is to split it up into smaller
commits.
If others could hold off on changes to numbers.c for now, I would be
grateful.
Below is a summary of what I've done so far.
Mark
* Fix NEWS item relating to earlier change of (expt 0 N) for N < 0.
* Add SCM_INUM1, a name for SCM_I_MAKINUM(1), to numbers.h.
This is analogous to SCM_INUM0, which already existed.
* Add flo1, a static global of type SCM containing 1.0, to numbers.c.
This is analogous to flo0, which already existed.
* Replace many occurrences of SCM_I_MAKINUM (0) to SCM_INUM0,
SCM_I_MAKINUM (1) to SCM_INUM1, scm_from_double (0.0) to flo0,
and scm_from_double (1.0) to flo1.
* Add scm_finite_p `finite?' from R6RS to guile core, which returns #t
if and only if its argument is neither infinite nor a NaN. Note
that this is not the same as (not (inf? x)) or (not (infinite? x)),
since NaNs are neither finite nor infinite.
* Add new internal predicates to numbers.test:
* `real-nan?' checks that its argument is real and a NaN.
* `complex-nan?' checks that both the real and imaginary
parts of its argument are NaNs.
* `imaginary-nan?' checks that its argument's real part
is zero and the imaginary part is a NaN.
* `complex-zero?' checks that its argument is a non-real
complex zero, i.e. that both the real
and imaginary parts are inexact zeroes.
* Convert many test cases in numbers.test from `nan?' to `real-nan?'.
* Add many new test cases to numbers.test and r6rs-base.test, and
change many existing tests from `=' to `eqv?' which is more
discriminating. In particular, `eqv?' tests the exactness of the
result, and can also distinguish 0.0 from -0.0.
* Reindent some function calls to make their arguments line up.
* Move a comment about the trigonometric functions next to those
functions. At some point they became separated, when scm_expt was
placed between them.
* Add SCM_LIKELY and SCM_UNLIKELY to various places for optimization.
* scm_product `*' now handles exact 0 differently. A product
containing an exact 0 now returns an exact 0 if and only if the
other arguments are all finite, otherwise a NaN is returned.
* Fix bugs in scm_difference `-' and scm_product `*' when negating
SCM_MOST_POSITIVE_FIXNUM+1. Previously, these cases failed
to normalize the result back to a fixnum, so eqv? failed:
(eqv? most-negative-fixnum (- 0 (- most-negative-fixnum)))
(eqv? most-negative-fixnum (* -1 (- most-negative-fixnum)))
(eqv? most-negative-fixnum (* (- most-negative-fixnum) -1))
* scm_eqv_p `eqv?' and scm_equal_p `equal?' now return #f if either
argument is a NaN, per R6RS. Previously, they returned #t if both
were real NaNs, or both were non-real complex NaNs.
* scm_equal_p `equal?' now behaves identically to scm_eqv_p `eqv?' for
numeric values, per R5RS. Previously, equal? worked differently,
e.g. (equal? 0.0 -0.0) returned #t but (eqv? 0.0 -0.0) returned #f.
* scm_real_equalp, scm_bigequal, and scm_complex_equalp have been
moved from numbers.c to eq.c, and changed to use the same code that
scm_eqv_p does.
* Remove from the list of `General assumptions' in numbers.c
that objects satisfying SCM_COMPLEXP() has a non-zero complex
component. This is no longer true.
* Complex numbers whose imaginary part is 0.0 or -0.0 are no longer
considered real, e.g. (real? 0.0+0.0i) is now #f, per R6RS, although
(zero? 0.0+0.0i) still returns #t, per R6RS. (= 0 0.0+0.0i) and
(= 0.0 0.0+0.0i) are #t, but the same comparisons using `eqv?' or
`equal?' are #f. Like other non-real numbers, these complex numbers
with inexact zero imaginary part will raise exceptions for
operations requiring reals, such as `<', `>', `<=', `>=', `min'
and `max'.
* scm_inexact_to_exact `inexact->exact' now treats a complex number
with inexact zero imaginary part as if it was a real. Previously,
such numbers did not exist.
* scm_make_rectangular `make-rectangular' now returns a real number
only if the imaginary part is an _exact_ 0. Previously, it would
return a real number if the imaginary part was an inexact zero.
* scm_c_make_rectangular now always returns a non-real complex number,
even if the imaginary part is 0.0. Previously, it would return a
real number if the imaginary part was 0.0.
* scm_make_polar `make-polar' now returns a real number only if the
angle or magnitude is an _exact_ 0. If the magnitude is an exact 0,
it now returns an exact 0. Previously, it would return a real
number if the imaginary part was an inexact zero.
* scm_c_make_polar now always returns a non-real complex number, even
if the imaginary part is 0.0. Previously, it would return a real
number if the imaginary part was 0.0.
* scm_imag_part `imag-part' now returns an exact 0 when its argument
is an inexact real flonum. This is now justified because we are
careful elsewhere to return real numbers only when their imaginary
part is an exact 0.
* Complex numbers with -0.0 imaginary part (which previously were
automatically converted to reals, so were never printed) are now
printed as "<REALPART>-0.0i" instead of "<REALPART>+-0.0i".
* Add a special case for fractions with differing SCM_CELL_TYPE, which
might nonetheless be considered equal (due to the use of 0x10000 as
a flag), to scm_equal_p. This code was already present in
scm_eqv_p.
* 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.
* scm_integer_p `integer?' now returns #f for flonums too large to be
distinguished from their increments. Previously it returned #t.
* scm_even_p `even?' and scm_odd_p `odd?' now return #f for infinities
and flonums too large to be distinguished from their increments.
Previously, the infinities were both even and odd, and such large
flonums were even.
* scm_even_p `even?' and scm_odd_p `odd?' now throw exceptions only if
passed non-number objects, per R5RS. Previously, they threw
exceptions for non-integers. (Note that NaNs _are_ considered
numbers by scheme, despite their name).
* Improve documentation string for scm_inf_p `inf?' to mention that
complex numbers with infinite real or imaginary part are also
considered infinite.
* scm_inf_p `inf?' and scm_nan_p `nan?' now throw exceptions if passed
non-number objects. Previously they returned #f. (Note that NaNs
_are_ considered numbers by scheme, despite their name).
* Fix format so that it will never call `inf?' or `nan?' on strings,
since those functions now throw exceptions in that case.
* scm_expt `expt' and scm_integer_expt `integer-expt', when raising
zero to the zero power, now sometimes throw an exception (if taking
the reciprocal of the base would do so, currently true if the base
is an exact 0), and intelligently return either a real or a non-real
complex NaN, depending on the types of zeroes in the arguments.
* scm_positive_p `positive?' and scm_negative_p `negative?' now return
#f for non-real numbers (including complex numbers with inexact zero
imaginary part). Previously they threw an exception for non-reals.
* scm_max `max?' and scm_min `min?' now properly order the real
infinities and NaNs, per R6RS. Note that this ordering is different
than that of `<', `>', `<=', and `>=', which return #f if any
argument is a real NaN. The relevant real infinity (-inf.0 for min,
+inf.0 for max) beats everything, including NaNs, and NaNs beat
everything else. Previously these were handled improperly in many
cases.
* Fix bug in scm_abs `abs' relating to signed zeros: (abs -0.0) now
returns 0.0. Previously it returned -0.0.
* Fix bug in scm_difference `-' relating to signed zeros: (- 0 0.0)
now returns -0.0. Previously it returned 0.0. Also (- 0 0.0+0.0i),
which previously never occurred, returns -0.0-0.0i.
* scm_expt `expt' now makes sure that the result is a non-real complex
(perhaps with an inexact 0.0 imaginary part) if it cannot be
determined that the imaginary part is an exact 0. For example,
(expt -1.0 2) returns 1.0, but (expt -1 2.0) returns 1.0+0.0i.
* scm_expt `expt' now tries to be more mathematically correct in the
case where both the base and exponent are zeroes. If the base is
-0.0 (or a non-real complex zero), or the exponent is a non-real
complex zero, the result now contains an inexact zero imaginary part
of the correct sign.
* scm_expt `expt' now returns an exact 1 if the base is an exact 1 or
the exponent is an exact 0, regardless of the other argument.
Previously it returned an inexact 1.0 in some of these cases,
e.g. (expt 1 0.5) and (expt 1.0 0)
* scm_expt `expt' and scm_integer_expt `integer-expt' are now more
careful in the case of zero^p (for re(p)>0) to return either an
exact 0, an inexact real zero, or an inexact non-real complex zero,
depending on the arguments.
* Fix bugs in scm_rationalize `rationalize'. Previously, it returned
exact integers unmodified, although that was incorrect if the
epsilon was at least 1 or inexact, e.g. (rationalize 4 1) should
return 3 per R5RS and R6RS, but previously it returned 4. Also
handle cases involving infinities and NaNs properly, per R6RS.
* R6RS base.scm now imports `inf?' as `infinite?' instead of
reimplementing it. Previously, the reimplementation of `infinite?'
did not detect non-real complex infinities, nor did it throw
exceptions for non-numbers. (Note that NaNs _are_ considered
numbers by scheme, despite their name).
* R6RS base.scm now imports `finite?' instead of reimplementing it.
Previously, the reimplementation of `finite?' returned #t for both
NaNs and non-real complex infinities, in violation of R6RS.
* R6RS base.scm now implements `real-valued?', `rational-valued?',
and `integer-valued?' properly, per R6RS.
* R6RS base.scm now implements `div', `mod', and `div-and-mod'
properly (though admittedly inefficiently). Previously, `div' and
`mod' were aliases of R5RS `quotient' and `modulo', although they
have different semantics. R6RS `mod' is supposed to return a
non-negative number less than the absolute value of the divisor, but
R5RS `modulo' returns a number of the same sign as the divisor (or
zero). R6RS `div' is supposed to return (floor (/ x y)), but R5RS
`quotient' returns (truncate (/ x y)). For example, R6RS states
that (div-and-mod 123 -10) should return -12 and 3, but previously
it returned -12 and -7.
* R6RS base.scm now implements `div0', `mod0', and `div0-and-mod0'
properly (though admittedly inefficiently). R6RS states that
(div0-and-mod0 123 -10) should return -12 and 3, but previously
it returned -12 and -7.
* Fix test cases in r6rs-arithmetic-fixnums.test regarding
`fxdiv0-and-mod0' and `fxdiv0'.
* scm_sin `sin', scm_cos `cos', scm_tan `tan', scm_sinh `sinh',
scm_cosh `cosh', scm_tanh `tanh', scm_asin `asin', scm_acos `acos',
scm_sys_asinh `asinh', scm_sys_acosh `acosh', scm_sys_acosh `acosh',
scm_sys_atanh `atanh' and the one-argument case of scm_atan `atan'
now return an exact result in some cases.
* Removed a case from do_divide that never occurs: a zero bignum.
* Optimized scm_exact_p `exact?' by making use of the SCM_INEXACTP
macro.
- Large changes to numerics coming,
Mark H Weaver <=