From c048ccc88a165f29bb2c59b75bd47e00739fc407 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Thu, 15 Jan 2026 08:03:56 +0900 Subject: [PATCH] mruby-bigint: add in-place right shift optimization when destination equals source in mpz_div_2exp(), use memmove and mpn_rshift in-place instead of allocating a temporary. reduces sqrt allocations by 49% since Newton iteration uses in-place division by 2 on each iteration. Co-authored-by: Claude --- mrbgems/mruby-bigint/core/bigint.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/mrbgems/mruby-bigint/core/bigint.c b/mrbgems/mruby-bigint/core/bigint.c index 026d0a9f6..0e068bc76 100644 --- a/mrbgems/mruby-bigint/core/bigint.c +++ b/mrbgems/mruby-bigint/core/bigint.c @@ -3373,8 +3373,29 @@ mpz_div_2exp(mpz_ctx_t *ctx, mpz_t *z, mpz_t *x, mrb_int e) return; } - mpz_t y; size_t new_size = x->sz - digs; + + /* In-place optimization: when z == x, no allocation needed */ + if (z == x) { + /* Shift by whole limbs: memmove in place */ + if (digs > 0) { + memmove(z->p, z->p + digs, new_size * sizeof(mp_limb)); + } + z->sz = new_size; + /* Shift by remaining bits: mpn_rshift supports in-place */ + if (bs) { + mpn_rshift(z->p, z->p, new_size, (unsigned int)bs); + } + trim(z); + if (uzero_p(z)) + z->sn = 0; + else + z->sn = sn; + return; + } + + /* General case: z != x, use temporary */ + mpz_t y; mpz_init_temp(ctx, &y, new_size); mpz_realloc(ctx, &y, new_size); for (size_t i = 0; i < new_size; i++)