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;