diff --git a/base/intfuncs.jl b/base/intfuncs.jl index 2e1ec8fc50a1b..a3218f82c606b 100644 --- a/base/intfuncs.jl +++ b/base/intfuncs.jl @@ -82,13 +82,15 @@ end gcd(a::Union{Integer,Rational}) = a lcm(a::Union{Integer,Rational}) = a -gcd(a::Union{Integer,Rational}, b::Union{Integer,Rational}) = gcd(promote(a,b)...) -lcm(a::Union{Integer,Rational}, b::Union{Integer,Rational}) = lcm(promote(a,b)...) -gcd(a::Union{Integer,Rational}, b::Union{Integer,Rational}...) = gcd(a, gcd(b...)) -lcm(a::Union{Integer,Rational}, b::Union{Integer,Rational}...) = lcm(a, lcm(b...)) +gcd(a::Real, b::Real) = gcd(promote(a,b)...) +lcm(a::Real, b::Real) = lcm(promote(a,b)...) +gcd(a::Real, b::Real, c::Real...) = gcd(a, gcd(b, c...)) +lcm(a::Real, b::Real, c::Real...) = lcm(a, lcm(b, c...)) +gcd(a::T, b::T) where T<:Real = throw(MethodError(gcd, (a,b))) +lcm(a::T, b::T) where T<:Real = throw(MethodError(lcm, (a,b))) -gcd(abc::AbstractArray{<:Union{Integer,Rational}}) = reduce(gcd, abc; init=zero(eltype(abc))) -lcm(abc::AbstractArray{<:Union{Integer,Rational}}) = reduce(lcm, abc; init=one(eltype(abc))) +gcd(abc::AbstractArray{<:Real}) = reduce(gcd, abc; init=zero(eltype(abc))) +lcm(abc::AbstractArray{<:Real}) = reduce(lcm, abc; init=one(eltype(abc))) function gcd(abc::AbstractArray{<:Integer}) a = zero(eltype(abc)) @@ -147,7 +149,8 @@ function gcdx(a::T, b::T) where T<:Integer end a < 0 ? (-a, -s0, -t0) : (a, s0, t0) end -gcdx(a::Union{Integer,Rational}, b::Union{Integer,Rational}) = gcdx(promote(a,b)...) +gcdx(a::Real, b::Real) = gcdx(promote(a,b)...) +gcdx(a::T, b::T) where T<:Real = throw(MethodError(gcdx, (a,b))) # multiplicative inverse of n mod m, error if none diff --git a/test/intfuncs.jl b/test/intfuncs.jl index 1214172c20b73..2e492a01a539f 100644 --- a/test/intfuncs.jl +++ b/test/intfuncs.jl @@ -68,6 +68,17 @@ end @test gcdx(5, -12) == (1, 5, 2) @test gcdx(-25, -4) == (1, -1, 6) end +@testset "gcd/lcm/gcdx for custom types" begin + struct MyRational <: Real + val::Rational{Int} + end + Base.promote_rule(::Type{MyRational}, T::Type{<:Real}) = promote_type(Rational{Int}, T) + (T::Type{<:Real})(x::MyRational) = T(x.val) + + @test gcd(MyRational(2//3), 3) == gcd(2//3, 3) == gcd(Real[MyRational(2//3), 3]) + @test lcm(MyRational(2//3), 3) == lcm(2//3, 3) == lcm(Real[MyRational(2//3), 3]) + @test gcdx(MyRational(2//3), 3) == gcdx(2//3, 3) +end @testset "invmod" begin @test invmod(6, 31) === 26 @test invmod(-1, 3) === 2