diff --git a/base/intfuncs.jl b/base/intfuncs.jl index dc81f2bd3e489..09fb169e08db0 100644 --- a/base/intfuncs.jl +++ b/base/intfuncs.jl @@ -96,6 +96,8 @@ end Least common (positive) multiple (or zero if any argument is zero). The arguments may be integer and rational numbers. +``a`` is a multiple of ``b`` if there exists an integer ``m`` such +that ``b*m=a``. ``a`` is a multiple of ``b`` if there exists an integer ``m`` such that ``a=mb``. diff --git a/base/rational.jl b/base/rational.jl index 69d39770b2095..d9d067b20465d 100644 --- a/base/rational.jl +++ b/base/rational.jl @@ -564,8 +564,18 @@ end float(::Type{Rational{T}}) where {T<:Integer} = float(T) -gcd(x::Rational, y::Rational) = unsafe_rational(gcd(x.num, y.num), lcm(x.den, y.den)) -lcm(x::Rational, y::Rational) = unsafe_rational(lcm(x.num, y.num), gcd(x.den, y.den)) +function gcd(x::Rational, y::Rational) + if (isinf(x) && !isinf(y)) || (!isinf(x) && isinf(y)) + throw(ArgumentError("lcm is not defined")) + end + return unsafe_rational(gcd(x.num, y.num), lcm(x.den, y.den)) +end +function lcm(x::Rational, y::Rational) + if (isinf(x) && !isinf(y)) || (!isinf(x) && isinf(y)) + throw(ArgumentError("lcm is not defined")) + end + return unsafe_rational(lcm(x.num, y.num), gcd(x.den, y.den)) +end function gcdx(x::Rational, y::Rational) c = gcd(x, y) if iszero(c.num) diff --git a/test/rational.jl b/test/rational.jl index 90b5414a6fe89..47fac8b4c0e01 100644 --- a/test/rational.jl +++ b/test/rational.jl @@ -649,49 +649,24 @@ end @test lcm(a, T(0)//T(1)) === T(0)//T(1) @test gcdx(a, T(0)//T(1)) === (a, T(1), T(0)) - @test gcdx(T(1)//T(0), T(1)//T(2)) === (T(1)//T(0), T(1), T(0)) - @test gcdx(T(1)//T(2), T(1)//T(0)) === (T(1)//T(0), T(0), T(1)) - @test gcdx(T(1)//T(0), T(1)//T(1)) === (T(1)//T(0), T(1), T(0)) - @test gcdx(T(1)//T(1), T(1)//T(0)) === (T(1)//T(0), T(0), T(1)) @test gcdx(T(1)//T(0), T(1)//T(0)) === (T(1)//T(0), T(1), T(1)) - @test gcdx(T(1)//T(0), T(0)//T(1)) === (T(1)//T(0), T(1), T(0)) @test gcdx(T(0)//T(1), T(0)//T(1)) === (T(0)//T(1), T(0), T(0)) if T <: Signed - @test gcdx(T(-1)//T(0), T(1)//T(2)) === (T(1)//T(0), T(1), T(0)) - @test gcdx(T(1)//T(2), T(-1)//T(0)) === (T(1)//T(0), T(0), T(1)) - @test gcdx(T(-1)//T(0), T(1)//T(1)) === (T(1)//T(0), T(1), T(0)) - @test gcdx(T(1)//T(1), T(-1)//T(0)) === (T(1)//T(0), T(0), T(1)) @test gcdx(T(-1)//T(0), T(1)//T(0)) === (T(1)//T(0), T(1), T(1)) @test gcdx(T(1)//T(0), T(-1)//T(0)) === (T(1)//T(0), T(1), T(1)) @test gcdx(T(-1)//T(0), T(-1)//T(0)) === (T(1)//T(0), T(1), T(1)) - @test gcdx(T(-1)//T(0), T(0)//T(1)) === (T(1)//T(0), T(1), T(0)) - @test gcdx(T(0)//T(1), T(-1)//T(0)) === (T(1)//T(0), T(0), T(1)) end @test gcdx(T(1)//T(3), T(2)) === (T(1)//T(3), T(1), T(0)) @test lcm(T(1)//T(3), T(1)) === T(1)//T(1) - @test lcm(T(3)//T(1), T(1)//T(0)) === T(3)//T(1) - @test lcm(T(0)//T(1), T(1)//T(0)) === T(0)//T(1) - - @test lcm(T(1)//T(0), T(1)//T(2)) === T(1)//T(2) - @test lcm(T(1)//T(2), T(1)//T(0)) === T(1)//T(2) - @test lcm(T(1)//T(0), T(1)//T(1)) === T(1)//T(1) - @test lcm(T(1)//T(1), T(1)//T(0)) === T(1)//T(1) @test lcm(T(1)//T(0), T(1)//T(0)) === T(1)//T(0) - @test lcm(T(1)//T(0), T(0)//T(1)) === T(0)//T(1) @test lcm(T(0)//T(1), T(0)//T(1)) === T(0)//T(1) if T <: Signed - @test lcm(T(-1)//T(0), T(1)//T(2)) === T(1)//T(2) - @test lcm(T(1)//T(2), T(-1)//T(0)) === T(1)//T(2) - @test lcm(T(-1)//T(0), T(1)//T(1)) === T(1)//T(1) - @test lcm(T(1)//T(1), T(-1)//T(0)) === T(1)//T(1) @test lcm(T(-1)//T(0), T(1)//T(0)) === T(1)//T(0) @test lcm(T(1)//T(0), T(-1)//T(0)) === T(1)//T(0) @test lcm(T(-1)//T(0), T(-1)//T(0)) === T(1)//T(0) - @test lcm(T(-1)//T(0), T(0)//T(1)) === T(0)//T(1) - @test lcm(T(0)//T(1), T(-1)//T(0)) === T(0)//T(1) end @test gcd([T(5), T(2), T(1)//T(2)]) === T(1)//T(2) @@ -699,9 +674,14 @@ end @test lcm([T(5), T(2), T(1)//T(2)]) === T(10)//T(1) @test lcm(T(5), T(2), T(1)//T(2)) === T(10)//T(1) + + @test_throws ArgumentError gcd(T(1)//T(1), T(1)//T(0)) + @test_throws ArgumentError gcd(T(1)//T(0), T(0)//T(1)) + + @test_throws ArgumentError lcm(T(1)//T(1), T(1)//T(0)) + @test_throws ArgumentError lcm(T(1)//T(0), T(1)//T(1)) end end - @testset "gcdx for 1 and 3+ arguments" begin # one-argument @test gcdx(7) == (7, 1)