guile-devel
[Top][All Lists]
Advanced

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



reply via email to

[Prev in Thread] Current Thread [Next in Thread]