guile-commits
[Top][All Lists]
Advanced

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

[Guile-commits] 01/01: Fix (* x -1) for GOOPS types


From: Andy Wingo
Subject: [Guile-commits] 01/01: Fix (* x -1) for GOOPS types
Date: Tue, 28 Feb 2017 04:18:09 -0500 (EST)

wingo pushed a commit to branch stable-2.0
in repository guile.

commit f428e93ee7a4be76341444b228585755807b282f
Author: Andy Wingo <address@hidden>
Date:   Tue Feb 28 10:12:57 2017 +0100

    Fix (* x -1) for GOOPS types
    
    * libguile/numbers.c (scm_product): Only reduce (* x -1) to (- x) when X
      is a bignum.  Fixes weirdness when X is not a number and instead
      multiplication should dispatch to GOOPS.  Thanks to Alejandro Sanchez
      for the report.
---
 libguile/numbers.c | 28 +++++++++++++---------------
 1 file changed, 13 insertions(+), 15 deletions(-)

diff --git a/libguile/numbers.c b/libguile/numbers.c
index 1b63897..556dc78 100644
--- a/libguile/numbers.c
+++ b/libguile/numbers.c
@@ -8002,17 +8002,6 @@ scm_product (SCM x, SCM y)
          else
            SCM_WTA_DISPATCH_2 (g_product, x, y, SCM_ARGn, s_product);
          break;
-        case -1:
-         /*
-          * This case is important for more than just optimization.
-          * It handles the case of negating
-          * (+ 1 most-positive-fixnum) aka (- most-negative-fixnum),
-          * which is a bignum that must be changed back into a fixnum.
-          * Failure to do so will cause the following to return #f:
-          * (= most-negative-fixnum (* -1 (- most-negative-fixnum)))
-          */
-         return scm_difference(y, SCM_UNDEFINED);
-         break;
        }
 
       if (SCM_LIKELY (SCM_I_INUMP (y)))
@@ -8037,10 +8026,19 @@ scm_product (SCM x, SCM y)
        }
       else if (SCM_BIGP (y))
        {
-         SCM result = scm_i_mkbig ();
-         mpz_mul_si (SCM_I_BIG_MPZ (result), SCM_I_BIG_MPZ (y), xx);
-         scm_remember_upto_here_1 (y);
-         return result;
+          /* There is one bignum which, when multiplied by negative one,
+             becomes a non-zero fixnum: (1+ most-positive-fixum).  Since
+             we know the type of X and Y are numbers, delegate this
+             special case to scm_difference.  */
+          if (xx == -1)
+            return scm_difference (y, SCM_UNDEFINED);
+          else
+            {
+              SCM result = scm_i_mkbig ();
+              mpz_mul_si (SCM_I_BIG_MPZ (result), SCM_I_BIG_MPZ (y), xx);
+              scm_remember_upto_here_1 (y);
+              return result;
+            }
        }
       else if (SCM_REALP (y))
        return scm_i_from_double (xx * SCM_REAL_VALUE (y));



reply via email to

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