From 6d377f8d6d8702813769649595cabc213c97c865 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Thu, 31 Jul 2025 10:13:20 +0900 Subject: [PATCH] mruby-bigint: Improve udiv quotient estimation with 3-limb lookahead Enhanced the udiv function in mrbgems/mruby-bigint/core/bigint.c by implementing a 3-limb lookahead for quotient estimation. This is a step towards a more accurate and efficient division algorithm, reducing the number of correction steps required. Co-authored-by: Gemini --- mrbgems/mruby-bigint/core/bigint.c | 31 +++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/mrbgems/mruby-bigint/core/bigint.c b/mrbgems/mruby-bigint/core/bigint.c index cbd066fde..5cdb452c6 100644 --- a/mrbgems/mruby-bigint/core/bigint.c +++ b/mrbgems/mruby-bigint/core/bigint.c @@ -1485,7 +1485,36 @@ udiv(mpz_ctx_t *ctx, mpz_t *qq, mpz_t *rr, mpz_t *xx, mpz_t *yy) } /* Enhanced qhat refinement step */ - if (yd > 1) { + if (yd > 2) { // Now considering at least 3 limbs of divisor + mp_dbl_limb y_second = y.p[yd-2]; + mp_dbl_limb y_third = y.p[yd-3]; // New: third limb of divisor + mp_dbl_limb x_third = (j+yd-2 < x.sz) ? x.p[j+yd-2] : 0; + mp_dbl_limb x_fourth = (j+yd-3 < x.sz) ? x.p[j+yd-3] : 0; // New: fourth limb of dividend + + // Initial check with 2 limbs + mp_dbl_limb left_side = qhat * y_second; + mp_dbl_limb right_side = (rhat << DIG_SIZE) + x_third; + + while (qhat >= ((mp_dbl_limb)1 << DIG_SIZE) || (left_side > right_side)) { + qhat--; + rhat += z; + if (rhat >= ((mp_dbl_limb)1 << DIG_SIZE)) break; + left_side -= y_second; + right_side = (rhat << DIG_SIZE) + x_third; + } + + // Additional check with 3 limbs (new refinement) + left_side = qhat * y_third; + right_side = (rhat << DIG_SIZE) + x_fourth; + + while (qhat >= ((mp_dbl_limb)1 << DIG_SIZE) || (left_side > right_side)) { + qhat--; + rhat += z; + if (rhat >= ((mp_dbl_limb)1 << DIG_SIZE)) break; + left_side -= y_third; + right_side = (rhat << DIG_SIZE) + x_fourth; + } + } else if (yd == 2) { // Original 2-limb check mp_dbl_limb y_second = y.p[yd-2]; mp_dbl_limb x_third = (j+yd-2 < x.sz) ? x.p[j+yd-2] : 0; mp_dbl_limb left_side = qhat * y_second;