mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
8e91554c6d
Replace the classical Euclidean main loop (mpz_mod per iteration)
with Stein's binary GCD: subtract + factor out trailing 2s on
odd-maintained operands. Keep an mpz_mod fallback for heavily
unbalanced pairs (the smaller operand has at least two fewer limbs)
where one long division replaces many Stein subtracts.
The old loop allocated a temporary mpz_t every iteration to hold the
mod result; the Stein loop is allocation-free thanks to the in-place
paths in mpz_sub and mpz_div_2exp. This matches the "memory first"
priority and also happens to be faster on typical inputs because
mpz_mod's setup cost dominates when the quotient is small (the
classical Fibonacci-neighbor worst case).
Also add a small mpz_swap helper used by the new loop.
Benchmark (bin/mruby benchmark/bm_bigint_gcd.rb, median of 3):
case before after ratio
single-limb 42 ms 50 ms 1.19 (fast-path
unchanged;
noise)
fib(200) vs fib(201) 82 ms 23 ms 0.28
balanced ~700-bit shared 46 ms 32 ms 0.70
unbalanced big vs small 35 ms 28 ms 0.80
power-of-2 path 38 ms 42 ms 1.11 (fast-path
unchanged;
noise)
balanced ~2800-bit shared 19 ms 15 ms 0.79
Co-authored-by: Claude <noreply@anthropic.com>