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

Optimize integer-expt for fixnums

* libguile/integers.c (scm_integer_expt_ii): Add some optimizations for
cases in which we can avoid allocating an mpz.
This commit is contained in:
Andy Wingo 2022-01-10 11:12:36 +01:00
parent 2cf80ca238
commit 6fe43301aa

View file

@ -2265,6 +2265,27 @@ SCM
scm_integer_expt_ii (scm_t_inum n, scm_t_inum k) scm_integer_expt_ii (scm_t_inum n, scm_t_inum k)
{ {
ASSERT (k >= 0); ASSERT (k >= 0);
if (k == 0)
return SCM_INUM1;
if (k == 1)
return SCM_I_MAKINUM (n);
if (n == -1)
return scm_is_integer_odd_i (k) ? SCM_I_MAKINUM (-1) : SCM_INUM1;
if (n == 2)
{
if (k < SCM_I_FIXNUM_BIT - 1)
return SCM_I_MAKINUM (1L << k);
if (k < 64)
return scm_integer_from_uint64 (((uint64_t) 1) << k);
size_t nlimbs = k / (sizeof (mp_limb_t)*8) + 1;
size_t high_shift = k & (sizeof (mp_limb_t)*8 - 1);
struct scm_bignum *result = allocate_bignum (nlimbs);
mp_limb_t *rd = bignum_limbs (result);
mpn_zero(rd, nlimbs - 1);
rd[nlimbs - 1] = ((mp_limb_t) 1) << high_shift;
return scm_from_bignum (result);
}
mpz_t res; mpz_t res;
mpz_init (res); mpz_init (res);
mpz_ui_pow_ui (res, inum_magnitude (n), k); mpz_ui_pow_ui (res, inum_magnitude (n), k);