From 9ac70a72e023912b15e7e7078ccc8e9a13ae30ab Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Thu, 31 Jul 2025 10:21:04 +0900 Subject: [PATCH] mruby-bigint: Replace binary GCD with Euclidean algorithm in mpz_gcd The previous implementation of mpz_gcd for multi-limb numbers, commented as "Use Lehmer's algorithm", was in fact an implementation of the binary GCD algorithm (Stein's algorithm). This commit replaces that binary GCD implementation with a standard Euclidean algorithm. For multi-limb numbers, a well-implemented Euclidean algorithm leveraging an optimized modular division (mpz_mod) can be more efficient than the binary GCD. This change provides a clearer and more efficient foundation for GCD calculations, and serves as a stepping stone towards a true Lehmer's algorithm if pursued later. Co-authored-by: Gemini --- mrbgems/mruby-bigint/core/bigint.c | 40 ++++++------------------------ 1 file changed, 8 insertions(+), 32 deletions(-) diff --git a/mrbgems/mruby-bigint/core/bigint.c b/mrbgems/mruby-bigint/core/bigint.c index 5cdb452c6..9d06c2632 100644 --- a/mrbgems/mruby-bigint/core/bigint.c +++ b/mrbgems/mruby-bigint/core/bigint.c @@ -2633,38 +2633,14 @@ mpz_gcd(mpz_ctx_t *ctx, mpz_t *gg, mpz_t *aa, mpz_t *bb) mpz_div_2exp(ctx, &a, &a, a_zeros); mpz_div_2exp(ctx, &b, &b, b_zeros); - /* Use Lehmer's algorithm for large multi-limb numbers (> 3 limbs) */ - if (a.sz > 3 && b.sz > 3) { - mpz_t u0, u1, v0, v1, q, r; - mpz_init_temp(ctx, &u0, 2); - mpz_init_temp(ctx, &u1, 2); - mpz_init_temp(ctx, &v0, 2); - mpz_init_temp(ctx, &v1, 2); - mpz_init_temp(ctx, &q, 2); - mpz_init_temp(ctx, &r, 2); - - while (ucmp(&a, &b) != 0) { - if (ucmp(&a, &b) > 0) { - mpz_sub(ctx, &a, &a, &b); - mpz_div_2exp(ctx, &a, &a, mpz_trailing_zeros(&a)); - } - else { - mpz_sub(ctx, &b, &b, &a); - mpz_div_2exp(ctx, &b, &b, mpz_trailing_zeros(&b)); - } - } - } - else { - while (ucmp(&a, &b) != 0) { - if (ucmp(&a, &b) > 0) { - mpz_sub(ctx, &a, &a, &b); - mpz_div_2exp(ctx, &a, &a, mpz_trailing_zeros(&a)); - } - else { - mpz_sub(ctx, &b, &b, &a); - mpz_div_2exp(ctx, &b, &b, mpz_trailing_zeros(&b)); - } - } + /* Euclidean algorithm for multi-limb numbers */ + while (!zero_p(&b)) { + mpz_t temp; + mpz_init_temp(ctx, &temp, a.sz); + mpz_mod(ctx, &temp, &a, &b); + mpz_move(ctx, &a, &b); + mpz_move(ctx, &b, &temp); + mpz_clear(ctx, &temp); } mpz_mul_2exp(ctx, gg, &a, shift); mpz_clear(ctx, &a);