From 8566a996ddff794dec44b93ad31d27f9c175fdf1 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Thu, 15 Jan 2026 09:49:28 +0900 Subject: [PATCH] mruby-bigint: add in-place optimizations for mpz_neg, mpz_abs, ulshift When the output and input are the same variable, avoid unnecessary heap allocations by modifying in place: - mpz_neg: just flip the sign - mpz_abs: just make sign positive - ulshift: use mpn_lshift in-place (safe since it processes high-to-low) Co-authored-by: Claude --- mrbgems/mruby-bigint/core/bigint.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/mrbgems/mruby-bigint/core/bigint.c b/mrbgems/mruby-bigint/core/bigint.c index fade50c2d..d9682cd8c 100644 --- a/mrbgems/mruby-bigint/core/bigint.c +++ b/mrbgems/mruby-bigint/core/bigint.c @@ -2383,6 +2383,17 @@ ulshift(mpz_ctx_t *ctx, mpz_t *c1, mpz_t *a, size_t n) else if (uzero_p(a)) { zero(c1); } + else if (c1 == a) { + /* In-place optimization: mpn_lshift works from high to low, safe for aliasing */ + mp_limb carry; + size_t old_sz = a->sz; + + mpz_realloc(ctx, c1, old_sz + 1); + carry = mpn_lshift(c1->p, c1->p, old_sz, (unsigned int)n); + c1->p[old_sz] = carry; + c1->sz = old_sz + 1; + trim(c1); + } else { mpz_t c; mp_limb carry; @@ -3678,6 +3689,11 @@ mpz_div_2exp(mpz_ctx_t *ctx, mpz_t *z, mpz_t *x, mrb_int e) static void mpz_neg(mpz_ctx_t *ctx, mpz_t *x, mpz_t *y) { + /* In-place optimization: just flip the sign */ + if (x == y) { + x->sn = -(y->sn); + return; + } mpz_init_heap(ctx, x, y->sz); mpz_set(ctx, x, y); trim(x); @@ -4093,6 +4109,11 @@ mpz_abs_copy(mpz_ctx_t *ctx, mpz_t *result, mpz_t *operand) { static void mpz_abs(mpz_ctx_t *ctx, mpz_t *x, mpz_t *y) { + /* In-place optimization: just make sign positive */ + if (x == y) { + if (x->sn < 0) x->sn = -x->sn; + return; + } mpz_init_heap(ctx, x, y->sz); mpz_realloc(ctx, x, y->sz); mpz_abs_copy(ctx, x, y);