Skip to content

Commit 4bd73b2

Browse files
sostockKristofferC
authored andcommitted
Make it easier to extend lcm/gcd/gcdx to custom types
(cherry picked from commit 85eb20f)
1 parent d3ba27d commit 4bd73b2

File tree

2 files changed

+21
-7
lines changed

2 files changed

+21
-7
lines changed

base/intfuncs.jl

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -82,13 +82,15 @@ end
8282

8383
gcd(a::Union{Integer,Rational}) = a
8484
lcm(a::Union{Integer,Rational}) = a
85-
gcd(a::Union{Integer,Rational}, b::Union{Integer,Rational}) = gcd(promote(a,b)...)
86-
lcm(a::Union{Integer,Rational}, b::Union{Integer,Rational}) = lcm(promote(a,b)...)
87-
gcd(a::Union{Integer,Rational}, b::Union{Integer,Rational}...) = gcd(a, gcd(b...))
88-
lcm(a::Union{Integer,Rational}, b::Union{Integer,Rational}...) = lcm(a, lcm(b...))
85+
gcd(a::Real, b::Real) = gcd(promote(a,b)...)
86+
lcm(a::Real, b::Real) = lcm(promote(a,b)...)
87+
gcd(a::Real, b::Real, c::Real...) = gcd(a, gcd(b, c...))
88+
lcm(a::Real, b::Real, c::Real...) = lcm(a, lcm(b, c...))
89+
gcd(a::T, b::T) where T<:Real = throw(MethodError(gcd, (a,b)))
90+
lcm(a::T, b::T) where T<:Real = throw(MethodError(lcm, (a,b)))
8991

90-
gcd(abc::AbstractArray{<:Union{Integer,Rational}}) = reduce(gcd, abc; init=zero(eltype(abc)))
91-
lcm(abc::AbstractArray{<:Union{Integer,Rational}}) = reduce(lcm, abc; init=one(eltype(abc)))
92+
gcd(abc::AbstractArray{<:Real}) = reduce(gcd, abc; init=zero(eltype(abc)))
93+
lcm(abc::AbstractArray{<:Real}) = reduce(lcm, abc; init=one(eltype(abc)))
9294

9395
function gcd(abc::AbstractArray{<:Integer})
9496
a = zero(eltype(abc))
@@ -147,7 +149,8 @@ function gcdx(a::T, b::T) where T<:Integer
147149
end
148150
a < 0 ? (-a, -s0, -t0) : (a, s0, t0)
149151
end
150-
gcdx(a::Union{Integer,Rational}, b::Union{Integer,Rational}) = gcdx(promote(a,b)...)
152+
gcdx(a::Real, b::Real) = gcdx(promote(a,b)...)
153+
gcdx(a::T, b::T) where T<:Real = throw(MethodError(gcdx, (a,b)))
151154

152155
# multiplicative inverse of n mod m, error if none
153156

test/intfuncs.jl

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,17 @@ end
6868
@test gcdx(5, -12) == (1, 5, 2)
6969
@test gcdx(-25, -4) == (1, -1, 6)
7070
end
71+
@testset "gcd/lcm/gcdx for custom types" begin
72+
struct MyRational <: Real
73+
val::Rational{Int}
74+
end
75+
Base.promote_rule(::Type{MyRational}, T::Type{<:Real}) = promote_type(Rational{Int}, T)
76+
(T::Type{<:Real})(x::MyRational) = T(x.val)
77+
78+
@test gcd(MyRational(2//3), 3) == gcd(2//3, 3) == gcd(Real[MyRational(2//3), 3])
79+
@test lcm(MyRational(2//3), 3) == lcm(2//3, 3) == lcm(Real[MyRational(2//3), 3])
80+
@test gcdx(MyRational(2//3), 3) == gcdx(2//3, 3)
81+
end
7182
@testset "invmod" begin
7283
@test invmod(6, 31) === 26
7384
@test invmod(-1, 3) === 2

0 commit comments

Comments
 (0)