guile-commits
[Top][All Lists]
Advanced

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

[Guile-commits] 02/02: Optimize scm_integer_mul_ii


From: Andy Wingo
Subject: [Guile-commits] 02/02: Optimize scm_integer_mul_ii
Date: Sun, 9 Jan 2022 17:19:51 -0500 (EST)

wingo pushed a commit to branch wip-inline-digits
in repository guile.

commit 08d5ab38b6d2a075b185be1af841c48611eb2143
Author: Andy Wingo <wingo@pobox.com>
AuthorDate: Sun Jan 9 23:10:18 2022 +0100

    Optimize scm_integer_mul_ii
    
    * libguile/integers.c (make_bignum_2): Always include.
    (scm_integer_mul_ii): Avoid making a temporary allocation.
---
 libguile/integers.c | 28 +++++++++++++++++-----------
 1 file changed, 17 insertions(+), 11 deletions(-)

diff --git a/libguile/integers.c b/libguile/integers.c
index 3e7df7c12..de1d2b3d5 100644
--- a/libguile/integers.c
+++ b/libguile/integers.c
@@ -211,7 +211,6 @@ make_bignum_1 (int is_negative, mp_limb_t limb)
   return is_negative ? negate_bignum(z) : z;
 }
 
-#if SCM_SIZEOF_LONG == 4
 static struct scm_bignum *
 make_bignum_2 (int is_negative, mp_limb_t lo, mp_limb_t hi)
 {
@@ -220,7 +219,6 @@ make_bignum_2 (int is_negative, mp_limb_t lo, mp_limb_t hi)
   z->limbs[1] = hi;
   return is_negative ? negate_bignum(z) : z;
 }
-#endif
 
 static struct scm_bignum *
 make_bignum_from_uint64 (uint64_t val)
@@ -3024,17 +3022,25 @@ scm_integer_mul_ii (scm_t_inum x, scm_t_inum y)
   int64_t k = x * (int64_t) y;
   if (SCM_FIXABLE (k))
     return SCM_I_MAKINUM (k);
-#else
-  if (x == 0)
-    return SCM_INUM0;
-  scm_t_inum ax = (x > 0) ? x : -x;
-  scm_t_inum ay = (y > 0) ? y : -y;
-  if (SCM_MOST_POSITIVE_FIXNUM / ax >= ay)
-    return SCM_I_MAKINUM (x * y);
 #endif
 
-  // FIXME: Use mpn_mul with two-limb result to avoid allocating.
-  return scm_integer_mul_zi (long_to_bignum (x), y);
+  mp_limb_t xd[1] = { long_magnitude (x) };
+  mp_limb_t lo;
+  int negative = (x < 0) != (y < 0);
+  mp_limb_t hi = mpn_mul_1 (&lo, xd, 1, long_magnitude (y));
+  if (!hi)
+    {
+      if (negative)
+        {
+          if (lo <= long_magnitude (SCM_MOST_NEGATIVE_FIXNUM))
+            return SCM_I_MAKINUM (negative_long (lo));
+        }
+      else if (lo <= SCM_MOST_POSITIVE_FIXNUM)
+        return SCM_I_MAKINUM (lo);
+      return scm_from_bignum (make_bignum_1 (negative, lo));
+    }
+
+  return scm_from_bignum (make_bignum_2 (negative, lo, hi));
 }
 
 SCM



reply via email to

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