1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-04-30 03:40:34 +02:00

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.
This commit is contained in:
Andy Wingo 2022-01-09 14:39:42 +01:00
parent 5481222670
commit d89f75c535

View file

@ -167,6 +167,14 @@ allocate_bignum (size_t nlimbs)
return z; 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 * static struct scm_bignum *
negate_bignum (struct scm_bignum *z) negate_bignum (struct scm_bignum *z)
{ {
@ -174,6 +182,12 @@ negate_bignum (struct scm_bignum *z)
return 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 * static struct scm_bignum *
make_bignum_0 (void) 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); return scm_from_bignum (x);
default: default:
{ {
mpz_t result, zx; size_t xn = bignum_limb_count (x);
mpz_init (result); if (xn == 0)
alias_bignum_to_mpz (x, zx); return SCM_INUM0;
mpz_mul_si (result, zx, y);
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); scm_remember_upto_here_1 (x);
return take_mpz (result); return normalize_bignum
(bignum_negate_if (negate, (bignum_trim1 (result))));
} }
} }
} }