1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-04-30 11:50:28 +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;
}
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))));
}
}
}