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 <noreply@anthropic.com>
This commit is contained in:
Yukihiro "Matz" Matsumoto
2026-01-15 08:03:56 +09:00
parent 6baa9b7119
commit c048ccc88a
+22 -1
View File
@@ -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++)