From 6fe43301aa66f898f3b27d604c45c93da5286e12 Mon Sep 17 00:00:00 2001 From: Andy Wingo Date: Mon, 10 Jan 2022 11:12:36 +0100 Subject: [PATCH] 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. --- libguile/integers.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/libguile/integers.c b/libguile/integers.c index de1d2b3d5..a173d01f2 100644 --- a/libguile/integers.c +++ b/libguile/integers.c @@ -2265,6 +2265,27 @@ SCM scm_integer_expt_ii (scm_t_inum n, scm_t_inum k) { 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_init (res); mpz_ui_pow_ui (res, inum_magnitude (n), k);