mruby-bigint: add multi-precision gcd tests

Cover zero operands, power-of-2 fast path, negative operands,
balanced multi-limb pairs with a shared Fibonacci factor, highly
unbalanced pairs (to exercise the Euclidean fallback), and
Fibonacci neighbors (always coprime). Declare a test dependency
on mruby-numeric-ext since Integer#gcd is defined there.

Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
Yukihiro "Matz" Matsumoto
2026-04-23 22:56:44 +09:00
parent 8e91554c6d
commit ad8fc7d918
2 changed files with 43 additions and 0 deletions
+2
View File
@@ -4,6 +4,8 @@ MRuby::Gem::Specification.new('mruby-bigint') do |spec|
spec.summary = 'Integer class extension to multiple-precision'
spec.build.defines << "MRB_USE_BIGINT"
spec.add_test_dependency('mruby-numeric-ext', :core => 'mruby-numeric-ext')
spec.build.libmruby_core_objs << Dir.glob(File.join(__dir__, "core/**/*.c")).map { |fn|
objfile(fn.relative_path_from(__dir__).pathmap("#{spec.build_dir}/%X"))
}
+41
View File
@@ -155,3 +155,44 @@ assert 'Bigint abs' do
assert_equal 36893488147419103232, n.abs
assert_equal 36893488147419103232, (-n).abs
end
assert 'Bigint gcd' do
# zero cases
assert_equal 0, 0.gcd(0)
n = 1 << 200
assert_equal n, n.gcd(0)
assert_equal n, 0.gcd(n)
# power-of-2 fast path
assert_equal 1 << 100, (1 << 200).gcd(1 << 100)
assert_equal 1 << 100, (1 << 100).gcd(1 << 200)
assert_equal 1 << 40, (10 ** 50).gcd(1 << 40)
# negative operands: result is the positive GCD
a = 1 << 200
b = 3 << 200
assert_equal a, a.gcd(b)
assert_equal a, (-a).gcd(b)
assert_equal a, a.gcd(-b)
assert_equal a, (-a).gcd(-b)
# balanced multi-limb with known common factor
fib1000 = (1..1000).inject([0, 1]) { |(x, y), _| [y, x + y] }[0]
common = fib1000
k, m = 1_000_003, 1_000_033 # small coprime primes
assert_equal common, (common * k).gcd(common * m)
assert_equal common, (common * m).gcd(common * k)
# unbalanced: small coprime vs large
big = common * k
assert_equal 1, big.gcd(m)
assert_equal 1, m.gcd(big)
# Fibonacci neighbors are always coprime
f100 = (1..100).inject([0, 1]) { |(x, y), _| [y, x + y] }[0]
f101 = (1..101).inject([0, 1]) { |(x, y), _| [y, x + y] }[0]
assert_equal 1, f100.gcd(f101)
# Euclidean fallback path: operand sizes differ by several limbs
assert_equal 7, (7 * (1 << 4000)).gcd(7 * 13)
end