guile-commits
[Top][All Lists]
Advanced

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

[Guile-commits] 01/06: Optimize scm_integer_mul_zi


From: Andy Wingo
Subject: [Guile-commits] 01/06: Optimize scm_integer_mul_zi
Date: Sun, 9 Jan 2022 16:44:45 -0500 (EST)

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

commit 14bb53047d15bdea34d2cab21285d2adb03925b1
Author: Andy Wingo <wingo@pobox.com>
AuthorDate: Sun Jan 9 14:39:42 2022 +0100

    Optimize scm_integer_mul_zi
    
    * libguile/integers.c (bignum_trim1):
    (bignum_negate_if): New helpers.
    (scm_integer_mul_zi): Use the mpn API to avoid temporary allocation.
---
 libguile/integers.c | 30 +++++++++++++++++++++++++-----
 1 file changed, 25 insertions(+), 5 deletions(-)

diff --git a/libguile/integers.c b/libguile/integers.c
index 143683738..ee2907f30 100644
--- a/libguile/integers.c
+++ b/libguile/integers.c
@@ -167,6 +167,14 @@ allocate_bignum (size_t nlimbs)
   return z;
 }
 
+static struct scm_bignum *
+bignum_trim1 (struct scm_bignum *z)
+{
+  ASSERT (z->u.z.size > 0);
+  z->u.z.size -= (z->limbs[z->u.z.size - 1] == 0);
+  return z;
+}
+
 static struct scm_bignum *
 negate_bignum (struct scm_bignum *z)
 {
@@ -174,6 +182,12 @@ negate_bignum (struct scm_bignum *z)
   return z;
 }
 
+static struct scm_bignum *
+bignum_negate_if (int negate, struct scm_bignum *z)
+{
+  return negate ? negate_bignum (z) : z;
+}
+
 static struct scm_bignum *
 make_bignum_0 (void)
 {
@@ -2906,12 +2920,18 @@ scm_integer_mul_zi (struct scm_bignum *x, scm_t_inum y)
       return scm_from_bignum (x);
     default:
       {
-        mpz_t result, zx;
-        mpz_init (result);
-        alias_bignum_to_mpz (x, zx);
-        mpz_mul_si (result, zx, y);
+        size_t xn = bignum_limb_count (x);
+        if (xn == 0)
+          return SCM_INUM0;
+
+        struct scm_bignum *result = allocate_bignum (xn + 1);
+        const mp_limb_t *xd = bignum_limbs (x);
+        mp_limb_t yd[1] = { long_magnitude (y) };
+        int negate = bignum_is_negative (x) != (y < 0);
+        mpn_mul (bignum_limbs (result), xd, xn, yd, 1);
         scm_remember_upto_here_1 (x);
-        return take_mpz (result);
+        return normalize_bignum
+          (bignum_negate_if (negate, (bignum_trim1 (result))));
       }
     }
 }



reply via email to

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