Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: crystal-lang/crystal
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: b7e792e4d399
Choose a base ref
...
head repository: crystal-lang/crystal
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: ca5540941808
Choose a head ref
  • 2 commits
  • 3 files changed
  • 2 contributors

Commits on Jul 25, 2016

  1. BigInts now uses gmp implementation of gcd and lcm

    endSly authored and Endika Gutiérrez committed Jul 25, 2016
    Copy the full SHA
    bd222bf View commit details
  2. Merge pull request #3039 from endSly/master

    BigInts should use gmp implementation of gcd and lcm
    Ary Borenszweig authored Jul 25, 2016
    Copy the full SHA
    ca55409 View commit details
Showing with 56 additions and 0 deletions.
  1. +24 −0 spec/std/big/big_int_spec.cr
  2. +25 −0 src/big/big_int.cr
  3. +7 −0 src/big/lib_gmp.cr
24 changes: 24 additions & 0 deletions spec/std/big/big_int_spec.cr
Original file line number Diff line number Diff line change
@@ -179,6 +179,30 @@ describe "BigInt" do
a.to_s(32).should eq(d)
end

it "does gcd and lcm" do
# 3 primes
a = BigInt.new("48112959837082048697")
b = BigInt.new("12764787846358441471")
c = BigInt.new("36413321723440003717")
abc = a * b * c
a_17 = a * 17

(abc * b).gcd(abc * c).should eq(abc)
(abc * b).lcm(abc * c).should eq(abc * b * c)
(abc * b).gcd(abc * c).should be_a(BigInt)

(a_17).gcd(17).should eq(17)
(17).gcd(a_17).should eq(17)
(-a_17).gcd(17).should eq(17)
(-17).gcd(a_17).should eq(17)

(a_17).gcd(17).should be_a(Int::Unsigned)
(17).gcd(a_17).should be_a(Int::Unsigned)

(a_17).lcm(17).should eq(a_17)
(17).lcm(a_17).should eq(a_17)
end

it "can use Number::[]" do
a = BigInt[146, "3464", 97, "545"]
b = [BigInt.new(146), BigInt.new(3464), BigInt.new(97), BigInt.new(545)]
25 changes: 25 additions & 0 deletions src/big/big_int.cr
Original file line number Diff line number Diff line change
@@ -201,6 +201,23 @@ struct BigInt < Int
BigInt.new { |mpz| LibGMP.pow_ui(mpz, self, other) }
end

def gcd(other : BigInt) : BigInt
BigInt.new { |mpz| LibGMP.gcd(mpz, self, other) }
end

def gcd(other : Int) : Int
result = LibGMP.gcd_ui(nil, self, other.abs.to_u64)
result == 0 ? self : result
end

def lcm(other : BigInt) : BigInt
BigInt.new { |mpz| LibGMP.lcm(mpz, self, other) }
end

def lcm(other : Int) : BigInt
BigInt.new { |mpz| LibGMP.lcm_ui(mpz, self, other.abs.to_u64) }
end

def inspect
to_s
end
@@ -366,6 +383,14 @@ struct Int
to_big_i % other
end

def gcm(other : BigInt) : Int
other.gcm(self)
end

def lcm(other : BigInt) : BigInt
other.lcm(self)
end

# Returns a BigInt representing this integer.
def to_big_i : BigInt
BigInt.new(self)
7 changes: 7 additions & 0 deletions src/big/lib_gmp.cr
Original file line number Diff line number Diff line change
@@ -84,6 +84,13 @@ lib LibGMP
fun cmp_ui = __gmpz_cmp_ui(op1 : MPZ*, op2 : ULong) : Int
fun cmp_d = __gmpz_cmp_d(op1 : MPZ*, op2 : Double) : Int

# # Number Theoretic Functions

fun gcd = __gmpz_gcd(rop : MPZ*, op1 : MPZ*, op2 : MPZ*)
fun gcd_ui = __gmpz_gcd_ui(rop : MPZ*, op1 : MPZ*, op2 : ULong) : ULong
fun lcm = __gmpz_lcm(rop : MPZ*, op1 : MPZ*, op2 : MPZ*)
fun lcm_ui = __gmpz_lcm_ui(rop : MPZ*, op1 : MPZ*, op2 : ULong)

# MPQ
struct MPQ
_mp_num : MPZ