From d89f75c5355139da67d019bf3073fda095678ed7 Mon Sep 17 00:00:00 2001 From: Andy Wingo Date: Sun, 9 Jan 2022 14:39:42 +0100 Subject: [PATCH] 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)))); } } }