guile-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Guile-commits] GNU Guile branch, master, updated. release_1-9-15-65-g4a


From: Andy Wingo
Subject: [Guile-commits] GNU Guile branch, master, updated. release_1-9-15-65-g4a46bc2
Date: Sat, 12 Feb 2011 11:56:25 +0000

This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU Guile".

http://git.savannah.gnu.org/cgit/guile.git/commit/?id=4a46bc2a5f9a0d992c67e0be3eab64077b8421a6

The branch, master has been updated
       via  4a46bc2a5f9a0d992c67e0be3eab64077b8421a6 (commit)
       via  bc3d34f58785f843f588d3ed5dc76adf45e9811e (commit)
       via  18104cac0b9943d941668aa3d84f3dc65643c83e (commit)
       via  1ce7279a0656fdadfdae220327a97dbf1a3291c6 (commit)
       via  1a3152f7df494e7469f5d12ee9a9a10356c56004 (commit)
      from  e66ff09adb22a42a859956a8da89785e2dbc3b52 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 4a46bc2a5f9a0d992c67e0be3eab64077b8421a6
Author: Mark H Weaver <address@hidden>
Date:   Thu Feb 10 15:40:57 2011 -0500

    Fixes and improvements to number-theoretic division operators
    
    * libguile/numbers.c (scm_euclidean_quotient, scm_euclidean_divide,
      scm_centered_quotient, scm_centered_divide): Fix bug in inum/inum
      case, where (quotient most-negative-fixnum -1) would not be converted
      to a bignum.
    
      (scm_euclidean_quotient): Be more anal-retentive about calling
      scm_remember_upto_here_1 after mpz_sgn, (even though mpz_sgn is
      documented as being implemented as a macro and certainly won't
      do any allocation).  It's better to be safe than sorry here.
    
      (scm_euclidean_quotient, scm_centered_quotient): In the bignum/inum
      case, check if the divisor is 1, since this will allow us to avoid
      allocating a new bignum.
    
      (scm_euclidean_divide, scm_centered_quotient, scm_centered_divide):
      When computing the intermediate truncated quotient (xx / yy) and
      remainder, use (xx % yy) instead of (xx - qq * yy), on the theory that
      the compiler is more likely to handle this case intelligently and
      maybe combine the operations.
    
      (scm_euclidean_divide): In the bignum/inum case, we know that the
      remainder will fit in an fixnum, so don't bother allocating a bignum
      for it.
    
      (scm_euclidean_quotient, scm_euclidean_remainder,
      scm_euclidean_divide, scm_centered_quotient, scm_centered_remainder,
      scm_centered_divide): Minor stylistic changes.
    
    * test-suite/tests/numbers.test: Rework testing framework for
      number-theoretic division operators to be more efficient and
      comprehensive in its testing of code paths and problem cases.

commit bc3d34f58785f843f588d3ed5dc76adf45e9811e
Author: Mark H Weaver <address@hidden>
Date:   Thu Feb 10 14:35:02 2011 -0500

    Add comment about handling of exactness specifiers
    
    * libguile/numbers.c: Add discussion on the handling of exactness
      specifiers to the comment above the string-to-number conversion
      functions.

commit 18104cac0b9943d941668aa3d84f3dc65643c83e
Author: Mark H Weaver <address@hidden>
Date:   Thu Feb 10 14:24:39 2011 -0500

    Fix extensibility of 1-argument atan
    
    * libguile/numbers.c (scm_atan): Call SCM_WTA_DISPATCH_1 instead of
      SCM_WTA_DISPATCH_2 if the second argument is unbound.  Arguably,
      SCM_WTA_DISPATCH_* should handle that case gracefully, but currently
      it doesn't.

commit 1ce7279a0656fdadfdae220327a97dbf1a3291c6
Author: Mark H Weaver <address@hidden>
Date:   Thu Feb 10 14:15:52 2011 -0500

    Fix mistake in comment in tags.h
    
    * libguile/tags.h: Fix comment in discussion of data representation.
      tc3-code #0b110 indicates a small integer and #0b100 indicates a
      non-integer immediate.  Previously, these were reversed.

commit 1a3152f7df494e7469f5d12ee9a9a10356c56004
Author: Mark H Weaver <address@hidden>
Date:   Thu Feb 10 14:12:12 2011 -0500

    Bump copyright date in REPL version string
    
    * module/system/repl/common.scm (*version*): Add 2011 to copyright
      date range.

-----------------------------------------------------------------------

Summary of changes:
 libguile/numbers.c            |  137 ++++++++++++++--------
 libguile/tags.h               |    4 +-
 module/system/repl/common.scm |    2 +-
 test-suite/tests/numbers.test |  261 +++++++++++++++++++++++------------------
 4 files changed, 241 insertions(+), 163 deletions(-)

diff --git a/libguile/numbers.c b/libguile/numbers.c
index bd9870f..05840ef 100644
--- a/libguile/numbers.c
+++ b/libguile/numbers.c
@@ -1089,6 +1089,7 @@ SCM_PRIMITIVE_GENERIC (scm_euclidean_quotient, 
"euclidean-quotient", 2, 0, 0,
 {
   if (SCM_LIKELY (SCM_I_INUMP (x)))
     {
+      scm_t_inum xx = SCM_I_INUM (x);
       if (SCM_LIKELY (SCM_I_INUMP (y)))
        {
          scm_t_inum yy = SCM_I_INUM (y);
@@ -1096,7 +1097,6 @@ SCM_PRIMITIVE_GENERIC (scm_euclidean_quotient, 
"euclidean-quotient", 2, 0, 0,
            scm_num_overflow (s_scm_euclidean_quotient);
          else
            {
-             scm_t_inum xx = SCM_I_INUM (x);
              scm_t_inum qq = xx / yy;
              if (xx < qq * yy)
                {
@@ -1105,19 +1105,25 @@ SCM_PRIMITIVE_GENERIC (scm_euclidean_quotient, 
"euclidean-quotient", 2, 0, 0,
                  else
                    qq++;
                }
-             return SCM_I_MAKINUM (qq);
+             if (SCM_LIKELY (SCM_FIXABLE (qq)))
+               return SCM_I_MAKINUM (qq);
+             else
+               return scm_i_inum2big (qq);
            }
        }
       else if (SCM_BIGP (y))
        {
-         if (SCM_I_INUM (x) >= 0)
+         if (xx >= 0)
            return SCM_INUM0;
          else
-           return SCM_I_MAKINUM (- mpz_sgn (SCM_I_BIG_MPZ (y)));
+           {
+             scm_t_inum qq = - mpz_sgn (SCM_I_BIG_MPZ (y));
+             scm_remember_upto_here_1 (y);
+             return SCM_I_MAKINUM (qq);
+           }
        }
       else if (SCM_REALP (y))
-       return scm_i_inexact_euclidean_quotient
-         (SCM_I_INUM (x), SCM_REAL_VALUE (y));
+       return scm_i_inexact_euclidean_quotient (xx, SCM_REAL_VALUE (y));
       else if (SCM_FRACTIONP (y))
        return scm_i_slow_exact_euclidean_quotient (x, y);
       else
@@ -1131,6 +1137,8 @@ SCM_PRIMITIVE_GENERIC (scm_euclidean_quotient, 
"euclidean-quotient", 2, 0, 0,
          scm_t_inum yy = SCM_I_INUM (y);
          if (SCM_UNLIKELY (yy == 0))
            scm_num_overflow (s_scm_euclidean_quotient);
+         else if (SCM_UNLIKELY (yy == 1))
+           return x;
          else
            {
              SCM q = scm_i_mkbig ();
@@ -1246,6 +1254,7 @@ SCM_PRIMITIVE_GENERIC (scm_euclidean_remainder, 
"euclidean-remainder", 2, 0, 0,
 {
   if (SCM_LIKELY (SCM_I_INUMP (x)))
     {
+      scm_t_inum xx = SCM_I_INUM (x);
       if (SCM_LIKELY (SCM_I_INUMP (y)))
        {
          scm_t_inum yy = SCM_I_INUM (y);
@@ -1253,7 +1262,7 @@ SCM_PRIMITIVE_GENERIC (scm_euclidean_remainder, 
"euclidean-remainder", 2, 0, 0,
            scm_num_overflow (s_scm_euclidean_remainder);
          else
            {
-             scm_t_inum rr = SCM_I_INUM (x) % yy;
+             scm_t_inum rr = xx % yy;
              if (rr >= 0)
                return SCM_I_MAKINUM (rr);
              else if (yy > 0)
@@ -1264,7 +1273,6 @@ SCM_PRIMITIVE_GENERIC (scm_euclidean_remainder, 
"euclidean-remainder", 2, 0, 0,
        }
       else if (SCM_BIGP (y))
        {
-         scm_t_inum xx = SCM_I_INUM (x);
          if (xx >= 0)
            return x;
          else if (mpz_sgn (SCM_I_BIG_MPZ (y)) > 0)
@@ -1284,8 +1292,7 @@ SCM_PRIMITIVE_GENERIC (scm_euclidean_remainder, 
"euclidean-remainder", 2, 0, 0,
            }
        }
       else if (SCM_REALP (y))
-       return scm_i_inexact_euclidean_remainder
-         (SCM_I_INUM (x), SCM_REAL_VALUE (y));
+       return scm_i_inexact_euclidean_remainder (xx, SCM_REAL_VALUE (y));
       else if (SCM_FRACTIONP (y))
        return scm_i_slow_exact_euclidean_remainder (x, y);
       else
@@ -1420,6 +1427,7 @@ SCM_PRIMITIVE_GENERIC (scm_euclidean_divide, 
"euclidean/", 2, 0, 0,
 {
   if (SCM_LIKELY (SCM_I_INUMP (x)))
     {
+      scm_t_inum xx = SCM_I_INUM (x);
       if (SCM_LIKELY (SCM_I_INUMP (y)))
        {
          scm_t_inum yy = SCM_I_INUM (y);
@@ -1427,9 +1435,10 @@ SCM_PRIMITIVE_GENERIC (scm_euclidean_divide, 
"euclidean/", 2, 0, 0,
            scm_num_overflow (s_scm_euclidean_divide);
          else
            {
-             scm_t_inum xx = SCM_I_INUM (x);
              scm_t_inum qq = xx / yy;
-             scm_t_inum rr = xx - qq * yy;
+             scm_t_inum rr = xx % yy;
+             SCM q;
+
              if (rr < 0)
                {
                  if (yy > 0)
@@ -1437,13 +1446,15 @@ SCM_PRIMITIVE_GENERIC (scm_euclidean_divide, 
"euclidean/", 2, 0, 0,
                  else
                    { rr -= yy; qq++; }
                }
-             return scm_values (scm_list_2 (SCM_I_MAKINUM (qq),
-                                            SCM_I_MAKINUM (rr)));
+             if (SCM_LIKELY (SCM_FIXABLE (qq)))
+               q = SCM_I_MAKINUM (qq);
+             else
+               q = scm_i_inum2big (qq);
+             return scm_values (scm_list_2 (q, SCM_I_MAKINUM (rr)));
            }
        }
       else if (SCM_BIGP (y))
        {
-         scm_t_inum xx = SCM_I_INUM (x);
          if (xx >= 0)
            return scm_values (scm_list_2 (SCM_INUM0, x));
          else if (mpz_sgn (SCM_I_BIG_MPZ (y)) > 0)
@@ -1464,8 +1475,7 @@ SCM_PRIMITIVE_GENERIC (scm_euclidean_divide, 
"euclidean/", 2, 0, 0,
            }
        }
       else if (SCM_REALP (y))
-       return scm_i_inexact_euclidean_divide
-         (SCM_I_INUM (x), SCM_REAL_VALUE (y));
+       return scm_i_inexact_euclidean_divide (xx, SCM_REAL_VALUE (y));
       else if (SCM_FRACTIONP (y))
        return scm_i_slow_exact_euclidean_divide (x, y);
       else
@@ -1482,19 +1492,19 @@ SCM_PRIMITIVE_GENERIC (scm_euclidean_divide, 
"euclidean/", 2, 0, 0,
          else
            {
              SCM q = scm_i_mkbig ();
-             SCM r = scm_i_mkbig ();
+             scm_t_inum rr;
              if (yy > 0)
-               mpz_fdiv_qr_ui (SCM_I_BIG_MPZ (q), SCM_I_BIG_MPZ (r),
-                               SCM_I_BIG_MPZ (x), yy);
+               rr = mpz_fdiv_q_ui (SCM_I_BIG_MPZ (q),
+                                   SCM_I_BIG_MPZ (x), yy);
              else
                {
-                 mpz_fdiv_qr_ui (SCM_I_BIG_MPZ (q), SCM_I_BIG_MPZ (r),
-                                 SCM_I_BIG_MPZ (x), -yy);
+                 rr = mpz_fdiv_q_ui (SCM_I_BIG_MPZ (q),
+                                     SCM_I_BIG_MPZ (x), -yy);
                  mpz_neg (SCM_I_BIG_MPZ (q), SCM_I_BIG_MPZ (q));
                }
              scm_remember_upto_here_1 (x);
              return scm_values (scm_list_2 (scm_i_normbig (q),
-                                            scm_i_normbig (r)));
+                                            SCM_I_MAKINUM (rr)));
            }
        }
       else if (SCM_BIGP (y))
@@ -1607,6 +1617,7 @@ SCM_PRIMITIVE_GENERIC (scm_centered_quotient, 
"centered-quotient", 2, 0, 0,
 {
   if (SCM_LIKELY (SCM_I_INUMP (x)))
     {
+      scm_t_inum xx = SCM_I_INUM (x);
       if (SCM_LIKELY (SCM_I_INUMP (y)))
        {
          scm_t_inum yy = SCM_I_INUM (y);
@@ -1614,9 +1625,8 @@ SCM_PRIMITIVE_GENERIC (scm_centered_quotient, 
"centered-quotient", 2, 0, 0,
            scm_num_overflow (s_scm_centered_quotient);
          else
            {
-             scm_t_inum xx = SCM_I_INUM (x);
              scm_t_inum qq = xx / yy;
-             scm_t_inum rr = xx - qq * yy;
+             scm_t_inum rr = xx % yy;
              if (SCM_LIKELY (xx > 0))
                {
                  if (SCM_LIKELY (yy > 0))
@@ -1643,19 +1653,20 @@ SCM_PRIMITIVE_GENERIC (scm_centered_quotient, 
"centered-quotient", 2, 0, 0,
                        qq++;
                    }
                }
-             return SCM_I_MAKINUM (qq);
+             if (SCM_LIKELY (SCM_FIXABLE (qq)))
+               return SCM_I_MAKINUM (qq);
+             else
+               return scm_i_inum2big (qq);
            }
        }
       else if (SCM_BIGP (y))
        {
          /* Pass a denormalized bignum version of x (even though it
             can fit in a fixnum) to scm_i_bigint_centered_quotient */
-         return scm_i_bigint_centered_quotient
-           (scm_i_long2big (SCM_I_INUM (x)), y);
+         return scm_i_bigint_centered_quotient (scm_i_long2big (xx), y);
        }
       else if (SCM_REALP (y))
-       return scm_i_inexact_centered_quotient
-         (SCM_I_INUM (x), SCM_REAL_VALUE (y));
+       return scm_i_inexact_centered_quotient (xx, SCM_REAL_VALUE (y));
       else if (SCM_FRACTIONP (y))
        return scm_i_slow_exact_centered_quotient (x, y);
       else
@@ -1669,6 +1680,8 @@ SCM_PRIMITIVE_GENERIC (scm_centered_quotient, 
"centered-quotient", 2, 0, 0,
          scm_t_inum yy = SCM_I_INUM (y);
          if (SCM_UNLIKELY (yy == 0))
            scm_num_overflow (s_scm_centered_quotient);
+         else if (SCM_UNLIKELY (yy == 1))
+           return x;
          else
            {
              SCM q = scm_i_mkbig ();
@@ -1833,6 +1846,7 @@ SCM_PRIMITIVE_GENERIC (scm_centered_remainder, 
"centered-remainder", 2, 0, 0,
 {
   if (SCM_LIKELY (SCM_I_INUMP (x)))
     {
+      scm_t_inum xx = SCM_I_INUM (x);
       if (SCM_LIKELY (SCM_I_INUMP (y)))
        {
          scm_t_inum yy = SCM_I_INUM (y);
@@ -1840,7 +1854,6 @@ SCM_PRIMITIVE_GENERIC (scm_centered_remainder, 
"centered-remainder", 2, 0, 0,
            scm_num_overflow (s_scm_centered_remainder);
          else
            {
-             scm_t_inum xx = SCM_I_INUM (x);
              scm_t_inum rr = xx % yy;
              if (SCM_LIKELY (xx > 0))
                {
@@ -1875,12 +1888,10 @@ SCM_PRIMITIVE_GENERIC (scm_centered_remainder, 
"centered-remainder", 2, 0, 0,
        {
          /* Pass a denormalized bignum version of x (even though it
             can fit in a fixnum) to scm_i_bigint_centered_remainder */
-         return scm_i_bigint_centered_remainder
-           (scm_i_long2big (SCM_I_INUM (x)), y);
+         return scm_i_bigint_centered_remainder (scm_i_long2big (xx), y);
        }
       else if (SCM_REALP (y))
-       return scm_i_inexact_centered_remainder
-         (SCM_I_INUM (x), SCM_REAL_VALUE (y));
+       return scm_i_inexact_centered_remainder (xx, SCM_REAL_VALUE (y));
       else if (SCM_FRACTIONP (y))
        return scm_i_slow_exact_centered_remainder (x, y);
       else
@@ -2062,6 +2073,7 @@ SCM_PRIMITIVE_GENERIC (scm_centered_divide, "centered/", 
2, 0, 0,
 {
   if (SCM_LIKELY (SCM_I_INUMP (x)))
     {
+      scm_t_inum xx = SCM_I_INUM (x);
       if (SCM_LIKELY (SCM_I_INUMP (y)))
        {
          scm_t_inum yy = SCM_I_INUM (y);
@@ -2069,9 +2081,10 @@ SCM_PRIMITIVE_GENERIC (scm_centered_divide, "centered/", 
2, 0, 0,
            scm_num_overflow (s_scm_centered_divide);
          else
            {
-             scm_t_inum xx = SCM_I_INUM (x);
              scm_t_inum qq = xx / yy;
-             scm_t_inum rr = xx - qq * yy;
+             scm_t_inum rr = xx % yy;
+             SCM q;
+
              if (SCM_LIKELY (xx > 0))
                {
                  if (SCM_LIKELY (yy > 0))
@@ -2098,20 +2111,21 @@ SCM_PRIMITIVE_GENERIC (scm_centered_divide, 
"centered/", 2, 0, 0,
                        { qq++; rr -= yy; }
                    }
                }
-             return scm_values (scm_list_2 (SCM_I_MAKINUM (qq),
-                                            SCM_I_MAKINUM (rr)));
+             if (SCM_LIKELY (SCM_FIXABLE (qq)))
+               q = SCM_I_MAKINUM (qq);
+             else
+               q = scm_i_inum2big (qq);
+             return scm_values (scm_list_2 (q, SCM_I_MAKINUM (rr)));
            }
        }
       else if (SCM_BIGP (y))
        {
          /* Pass a denormalized bignum version of x (even though it
             can fit in a fixnum) to scm_i_bigint_centered_divide */
-         return scm_i_bigint_centered_divide
-           (scm_i_long2big (SCM_I_INUM (x)), y);
+         return scm_i_bigint_centered_divide (scm_i_long2big (xx), y);
        }
       else if (SCM_REALP (y))
-       return scm_i_inexact_centered_divide
-         (SCM_I_INUM (x), SCM_REAL_VALUE (y));
+       return scm_i_inexact_centered_divide (xx, SCM_REAL_VALUE (y));
       else if (SCM_FRACTIONP (y))
        return scm_i_slow_exact_centered_divide (x, y);
       else
@@ -3834,14 +3848,15 @@ scm_bigprint (SCM exp, SCM port, scm_print_state 
*pstate SCM_UNUSED)
  * in R5RS.  Thus, the functions resemble syntactic units (<ureal R>,
  * <uinteger R>, ...) that are used to build up numbers in the grammar.  Some
  * points should be noted about the implementation:
+ *
  * * Each function keeps a local index variable 'idx' that points at the
  * current position within the parsed string.  The global index is only
  * updated if the function could parse the corresponding syntactic unit
  * successfully.
+ *
  * * Similarly, the functions keep track of indicators of inexactness ('#',
- * '.' or exponents) using local variables ('hash_seen', 'x').  Again, the
- * global exactness information is only updated after each part has been
- * successfully parsed.
+ * '.' or exponents) using local variables ('hash_seen', 'x').
+ *
  * * Sequences of digits are parsed into temporary variables holding fixnums.
  * Only if these fixnums would overflow, the result variables are updated
  * using the standard functions scm_add, scm_product, scm_divide etc.  Then,
@@ -3850,6 +3865,34 @@ scm_bigprint (SCM exp, SCM port, scm_print_state *pstate 
SCM_UNUSED)
  * digits, a number 1234567890 would be parsed in two parts 12345 and 67890,
  * and the result was computed as 12345 * 100000 + 67890.  In other words,
  * only every five digits two bignum operations were performed.
+ *
+ * Notes on the handling of exactness specifiers:
+ *
+ * When parsing non-real complex numbers, we apply exactness specifiers on
+ * per-component basis, as is done in PLT Scheme.  For complex numbers
+ * written in rectangular form, exactness specifiers are applied to the
+ * real and imaginary parts before calling scm_make_rectangular.  For
+ * complex numbers written in polar form, exactness specifiers are applied
+ * to the magnitude and angle before calling scm_make_polar.
+ * 
+ * There are two kinds of exactness specifiers: forced and implicit.  A
+ * forced exactness specifier is a "#e" or "#i" prefix at the beginning of
+ * the entire number, and applies to both components of a complex number.
+ * "#e" causes each component to be made exact, and "#i" causes each
+ * component to be made inexact.  If no forced exactness specifier is
+ * present, then the exactness of each component is determined
+ * independently by the presence or absence of a decimal point or hash mark
+ * within that component.  If a decimal point or hash mark is present, the
+ * component is made inexact, otherwise it is made exact.
+ *  
+ * After the exactness specifiers have been applied to each component, they
+ * are passed to either scm_make_rectangular or scm_make_polar to produce
+ * the final result.  Note that this will result in a real number if the
+ * imaginary part, magnitude, or angle is an exact 0.
+ * 
+ * For example, (string->number "#i5.0+0i") does the equivalent of:
+ * 
+ *   (make-rectangular (exact->inexact 5) (exact->inexact 0))
  */
 
 enum t_exactness {NO_EXACTNESS, INEXACT, EXACT};
@@ -7025,7 +7068,7 @@ SCM_PRIMITIVE_GENERIC (scm_atan, "atan", 1, 1, 0,
                              scm_c_make_rectangular (0, 2));
         }
       else
-        SCM_WTA_DISPATCH_2 (g_scm_atan, z, y, SCM_ARG1, s_scm_atan);
+        SCM_WTA_DISPATCH_1 (g_scm_atan, z, SCM_ARG1, s_scm_atan);
     }
   else if (scm_is_real (z))
     {
diff --git a/libguile/tags.h b/libguile/tags.h
index 9e0e305..39d2eaa 100644
--- a/libguile/tags.h
+++ b/libguile/tags.h
@@ -258,8 +258,8 @@ typedef scm_t_uintptr scm_t_bits;
  *
  * If the cell holds a scheme pair, then we already know that the first
  * scm_t_bits variable of the cell will hold a scheme object with one of the
- * following tc3-codes: #b000 (non-immediate), #b010 (small integer), #b100
- * (small integer), #b110 (non-integer immediate).  All these tc3-codes have
+ * following tc3-codes: #b000 (non-immediate), #b010 (small integer), #b110
+ * (small integer), #b100 (non-integer immediate).  All these tc3-codes have
  * in common, that their least significant bit is #b0.  This fact is used by
  * the garbage collector to identify cells that hold pairs.  The remaining
  * tc3-codes are assigned as follows: #b001 (class instance or, more
diff --git a/module/system/repl/common.scm b/module/system/repl/common.scm
index e03bf93..5405bb8 100644
--- a/module/system/repl/common.scm
+++ b/module/system/repl/common.scm
@@ -36,7 +36,7 @@
 
 (define *version*
   (format #f "GNU Guile ~A
-Copyright (C) 1995-2010 Free Software Foundation, Inc.
+Copyright (C) 1995-2011 Free Software Foundation, Inc.
 
 Guile comes with ABSOLUTELY NO WARRANTY; for details type `,show w'.
 This program is free software, and you are welcome to redistribute it
diff --git a/test-suite/tests/numbers.test b/test-suite/tests/numbers.test
index 1c4630e..f738189 100644
--- a/test-suite/tests/numbers.test
+++ b/test-suite/tests/numbers.test
@@ -4116,6 +4116,7 @@
   (pass-if "-100i swings back to 45deg down"
     (eqv-loosely? +7.071-7.071i (sqrt -100.0i))))
 
+
 ;;;
 ;;; euclidean/
 ;;; euclidean-quotient
@@ -4127,130 +4128,164 @@
 
 (with-test-prefix "Number-theoretic division"
 
-  ;; Tests that (lo <= x < hi),
+  ;; Tests that (lo <1 x <2 hi),
   ;; but allowing for imprecision
   ;; if x is inexact.
-  (define (test-within-range? lo hi x)
+  (define (test-within-range? lo <1 x <2 hi)
     (if (exact? x)
-        (and (<= lo x) (< x hi))
+        (and (<1 lo x) (<2 x hi))
         (let ((lo (- lo test-epsilon))
               (hi (+ hi test-epsilon)))
           (<= lo x hi))))
 
-  ;; (cartesian-product-map list '(a b) '(1 2))
-  ;; ==> ((a 1) (a 2) (b 1) (b 2))
-  (define (cartesian-product-map f . lsts)
-    (define (cartmap rev-head lsts)
-      (if (null? lsts)
-          (list (apply f (reverse rev-head)))
-          (append-map (lambda (x) (cartmap (cons x rev-head) (cdr lsts)))
-                      (car lsts))))
-    (cartmap '() lsts))
-
-  (define (cartesian-product-for-each f . lsts)
-    (define (cartfor rev-head lsts)
-      (if (null? lsts)
-          (apply f (reverse rev-head))
-          (for-each (lambda (x) (cartfor (cons x rev-head) (cdr lsts)))
-                    (car lsts))))
-    (cartfor '() lsts))
-
-  (define (safe-euclidean-quotient x y)
-    (cond ((not (and (real? x) (real? y))) (throw 'wrong-type-arg))
-          ((zero? y) (throw 'divide-by-zero))
-          ((nan?  y) (nan))
-          ((positive? y) (floor   (/ x y)))
-          ((negative? y) (ceiling (/ x y)))
-          (else (throw 'unknown-problem))))
-
-  (define (safe-euclidean-remainder x y)
-    (let ((q (safe-euclidean-quotient x y)))
-      (- x (* y q))))
-
   (define (valid-euclidean-answer? x y q r)
-    (if (and (finite? x) (finite? y))
-        (and (eq? (exact? q)
-                  (exact? r)
-                  (and (exact? x) (exact? y)))
-             (integer? q)
-             (test-eqv? r (- x (* q y)))
-             (test-within-range? 0 (abs y) r))
-        (and (test-eqv? q (safe-euclidean-quotient  x y))
-             (test-eqv? r (safe-euclidean-remainder x y)))))
-
-  (define (safe-centered-quotient x y)
-    (cond ((not (and (real? x) (real? y))) (throw 'wrong-type-arg))
-          ((zero? y) (throw 'divide-by-zero))
-          ((nan?  y) (nan))
-          ((positive? y) (floor   (+  1/2 (/ x y))))
-          ((negative? y) (ceiling (+ -1/2 (/ x y))))
-          (else (throw 'unknown-problem))))
-
-  (define (safe-centered-remainder x y)
-    (let ((q (safe-centered-quotient x y)))
-      (- x (* y q))))
+    (and (eq? (exact? q)
+              (exact? r)
+              (and (exact? x) (exact? y)))
+         (test-eqv? r (- x (* q y)))
+         (if (and (finite? x) (finite? y))
+             (and (integer? q)
+                  (test-within-range? 0 <= r < (abs y)))
+             (test-eqv? q (/ x y)))))
 
   (define (valid-centered-answer? x y q r)
-    (if (and (finite? x) (finite? y))
-        (and (eq? (exact? q)
-                  (exact? r)
-                  (and (exact? x) (exact? y)))
-             (integer? q)
-             (test-eqv? r (- x (* q y)))
-             (test-within-range? (* -1/2 (abs y))
-                                 (* +1/2 (abs y))
-                                 r))
-        (and (test-eqv? q (safe-centered-quotient  x y))
-             (test-eqv? r (safe-centered-remainder x y)))))
-
-  (define test-numerators
-    (append (cartesian-product-map * '(1 -1)
-                                   '(123 125 127 130 3 5 10
-                                         123.2 125.0 127.2 130.0
-                                         123/7 125/7 127/7 130/7))
-            (cartesian-product-map * '(1 -1)
-                                   '(123 125 127 130 3 5 10)
-                                   (list 1
-                                         (+ 1 most-positive-fixnum)
-                                         (+ 2 most-positive-fixnum)))
-            (list 0 +0.0 -0.0 +inf.0 -inf.0 +nan.0
-                  most-negative-fixnum
-                  (1+ most-positive-fixnum)
-                  (1- most-negative-fixnum))))
-
-  (define test-denominators
-    (list   10  5  10/7  127/2  10.0  63.5
-            -10 -5 -10/7 -127/2 -10.0 -63.5
-            +inf.0 -inf.0 +nan.0 most-negative-fixnum
-            (+ 1 most-positive-fixnum) (+ -1 most-negative-fixnum)
-            (+ 2 most-positive-fixnum) (+ -2 most-negative-fixnum)))
+    (and (eq? (exact? q)
+              (exact? r)
+              (and (exact? x) (exact? y)))
+         (test-eqv? r (- x (* q y)))
+         (if (and (finite? x) (finite? y))
+             (and (integer? q)
+                  (test-within-range?
+                   (* -1/2 (abs y)) <= r < (* +1/2 (abs y))))
+             (test-eqv? q (/ x y)))))
+
+  (define (for lsts f) (apply for-each f lsts))
+
+  (define big (expt 10 (1+ (inexact->exact (ceiling (log10 fixnum-max))))))
+
+  (define (run-division-tests quo+rem quo rem valid-answer?)
+    (define (test n d)
+      (run-test (list n d) #t
+                (lambda ()
+                  (let-values (((q r) (quo+rem n d)))
+                    (and (test-eqv? q (quo n d))
+                         (test-eqv? r (rem n d))
+                         (valid-answer? n d q r))))))
+    (define (test+/- n d)
+      (test n    d )
+      (test n (- d))
+      (cond ((not (zero? n))
+             (test (- n)    d )
+             (test (- n) (- d)))))
+
+    (define (test-for-exception n d exception)
+      (let ((name (list n d)))
+        (pass-if-exception name exception (quo+rem n d))
+        (pass-if-exception name exception (quo n d))
+        (pass-if-exception name exception (rem n d))))
+
+    (run-test "documented?" #t
+              (lambda ()
+                (and (documented? quo+rem)
+                     (documented? quo)
+                     (documented? rem))))
+
+    (with-test-prefix "inum / inum"
+      (with-test-prefix "fixnum-min / -1"
+        (test fixnum-min -1))
+      (for '((1 2 5 10))  ;; denominators
+           (lambda (d)
+             (for '((0 1 2 5 10))  ;; multiples
+                  (lambda (m)
+                    (for '((-2 -1 0 1 2 3 4 5 7 10
+                               12 15 16 19 20))  ;; offsets
+                         (lambda (b)
+                           (test+/- (+ b (* m d))
+                                    d))))))))
+
+    (with-test-prefix "inum / big"
+      (with-test-prefix "fixnum-min / -fixnum-min"
+        (test fixnum-min (- fixnum-min)))
+      (with-test-prefix "fixnum-max / (2*fixnum-max)"
+        (test+/- fixnum-max (* 2 fixnum-max)))
+      (for `((0 1 2 10 ,(1- fixnum-max) ,fixnum-max))
+           (lambda (n)
+             (test    n  (1+ fixnum-max))
+             (test (- n) (1+ fixnum-max))
+             (test    n  (1- fixnum-min))
+             (test (- n) (1- fixnum-min)))))
+
+    (with-test-prefix "big / inum"
+      (with-test-prefix "-fixnum-min / fixnum-min"
+        (test (- fixnum-min) fixnum-min))
+      (for '((1 4 5 10))  ;; denominators
+           (lambda (d)
+             (for `((1 2 5 ,@(if (even? d)
+                                 '(1/2 3/2 5/2)
+                                 '())))  ;; multiples
+                  (lambda (m)
+                    (for '((-2 -1 0 1 2))  ;; offsets
+                         (lambda (b)
+                           (test+/- (+ b (* m d big))
+                                    d))))))))
+
+    (with-test-prefix "big / big"
+      (for `((,big ,(1+ big)))  ;; denominators
+           (lambda (d)
+             (for `((1 2 5 ,@(if (even? d)
+                                 '(1/2 3/2 5/2)
+                                 '())))  ;; multiples
+                  (lambda (m)
+                    (for '((-2 -1 0 1 2))  ;; offsets
+                         (lambda (b)
+                           (test+/- (+ b (* m d))
+                                    d))))))))
+
+    (with-test-prefix "inexact"
+      (for '((0.5 1.5 2.25 5.75))  ;; denominators
+           (lambda (d)
+             (for '((0 1 2 5 1/2 3/2 5/2))  ;; multiples
+                  (lambda (m)
+                    (for '((-2 -1 0 1 2))  ;; offsets
+                         (lambda (b)
+                           (test+/- (+ b (* m d))
+                                    d))))))))
+
+    (with-test-prefix "fractions"
+      (for '((1/10 16/3 10/7))  ;; denominators
+           (lambda (d)
+             (for '((0 1 2 5 1/2 3/2 5/2))  ;; multiples
+                  (lambda (m)
+                    (for '((-2/9 -1/11 0 1/3 2/3))  ;; offsets
+                         (lambda (b)
+                           (test+/- (+ b (* m d))
+                                    d))))))))
+
+    (with-test-prefix "mixed types"
+      (for `((10 ,big 12.0 10/7 +inf.0 -inf.0 +nan.0))  ;; denominators
+           (lambda (d)
+             (for `((25 ,(* 3/2 big) 130.0 15/7
+                        0 0.0 -0.0 +inf.0 -inf.0 +nan.0))  ;; numerators
+                  (lambda (n)
+                    (test+/- n d))))))
+
+    (with-test-prefix "divide by zero"
+      (for `((0 0.0 +0.0))  ;; denominators
+           (lambda (d)
+             (for `((15 ,(* 3/2 big) 18.0 33/7
+                        0 0.0 -0.0 +inf.0 -inf.0 +nan.0))  ;; numerators
+                  (lambda (n)
+                    (test-for-exception
+                     n d exception:numerical-overflow)))))))
 
   (with-test-prefix "euclidean/"
-    (pass-if (documented? euclidean/))
-    (pass-if (documented? euclidean-quotient))
-    (pass-if (documented? euclidean-remainder))
-
-    (cartesian-product-for-each
-     (lambda (n d)
-       (run-test (list 'euclidean/ n d) #t
-                 (lambda ()
-                   (let-values (((q r) (euclidean/ n d)))
-                     (and (test-eqv? q (euclidean-quotient n d))
-                          (test-eqv? r (euclidean-remainder n d))
-                          (valid-euclidean-answer? n d q r))))))
-     test-numerators test-denominators))
+    (run-division-tests euclidean/
+                        euclidean-quotient
+                        euclidean-remainder
+                        valid-euclidean-answer?))
 
   (with-test-prefix "centered/"
-    (pass-if (documented? centered/))
-    (pass-if (documented? centered-quotient))
-    (pass-if (documented? centered-remainder))
-
-    (cartesian-product-for-each
-     (lambda (n d)
-       (run-test (list 'centered/ n d) #t
-                 (lambda ()
-                   (let-values (((q r) (centered/ n d)))
-                     (and (test-eqv? q (centered-quotient n d))
-                          (test-eqv? r (centered-remainder n d))
-                          (valid-centered-answer? n d q r))))))
-     test-numerators test-denominators)))
+    (run-division-tests centered/
+                        centered-quotient
+                        centered-remainder
+                        valid-centered-answer?)))


hooks/post-receive
-- 
GNU Guile



reply via email to

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