diff --git a/base/rational.jl b/base/rational.jl index 05b4a062d8711..0462554664fcc 100644 --- a/base/rational.jl +++ b/base/rational.jl @@ -61,16 +61,16 @@ julia> (3 // 5) // (2 // 1) //(n::Integer, d::Integer) = Rational(n,d) function //(x::Rational, y::Integer) - xn, yn = divgcd(x.num,y) + xn, yn = divgcd(promote(x.num, y)...) checked_den(xn, checked_mul(x.den, yn)) end function //(x::Integer, y::Rational) - xn, yn = divgcd(x,y.num) + xn, yn = divgcd(promote(x, y.num)...) checked_den(checked_mul(xn, y.den), yn) end function //(x::Rational, y::Rational) - xn,yn = divgcd(x.num,y.num) - xd,yd = divgcd(x.den,y.den) + xn,yn = divgcd(promote(x.num, y.num)...) + xd,yd = divgcd(promote(x.den, y.den)...) checked_den(checked_mul(xn, yd), checked_mul(xd, yn)) end @@ -280,7 +280,7 @@ end for (op,chop) in ((:+,:checked_add), (:-,:checked_sub), (:rem,:rem), (:mod,:mod)) @eval begin function ($op)(x::Rational, y::Rational) - xd, yd = divgcd(x.den, y.den) + xd, yd = divgcd(promote(x.den, y.den)...) Rational(($chop)(checked_mul(x.num,yd), checked_mul(y.num,xd)), checked_mul(x.den,yd)) end @@ -305,16 +305,16 @@ for (op,chop) in ((:rem,:rem), (:mod,:mod)) end function *(x::Rational, y::Rational) - xn, yd = divgcd(x.num, y.den) - xd, yn = divgcd(x.den, y.num) + xn, yd = divgcd(promote(x.num, y.den)...) + xd, yn = divgcd(promote(x.den, y.num)...) unsafe_rational(checked_mul(xn, yn), checked_mul(xd, yd)) end function *(x::Rational, y::Integer) - xd, yn = divgcd(x.den, y) + xd, yn = divgcd(promote(x.den, y)...) unsafe_rational(checked_mul(x.num, yn), xd) end function *(y::Integer, x::Rational) - yn, xd = divgcd(y, x.den) + yn, xd = divgcd(promote(y, x.den)...) unsafe_rational(checked_mul(yn, x.num), xd) end /(x::Rational, y::Union{Rational, Integer, Complex{<:Union{Integer,Rational}}}) = x//y diff --git a/test/rational.jl b/test/rational.jl index 4b2d48305660b..81a9ab16c5ff7 100644 --- a/test/rational.jl +++ b/test/rational.jl @@ -575,3 +575,22 @@ end @test -Int32(1) // typemax(Int32) - Int32(1) == typemin(Int32) // typemax(Int32) @test 1 // (typemax(Int128) + BigInt(1)) - 2 == (1 + BigInt(2)*typemin(Int128)) // (BigInt(1) + typemax(Int128)) end + +@testset "Promotions on binary operations with Rationals (#36277)" begin + inttypes = (Base.BitInteger_types..., BigInt) + for T in inttypes, S in inttypes + U = Rational{promote_type(T, S)} + @test typeof(one(Rational{T}) + one(S)) == typeof(one(S) + one(Rational{T})) == typeof(one(Rational{T}) + one(Rational{S})) == U + @test typeof(one(Rational{T}) - one(S)) == typeof(one(S) - one(Rational{T})) == typeof(one(Rational{T}) - one(Rational{S})) == U + @test typeof(one(Rational{T}) * one(S)) == typeof(one(S) * one(Rational{T})) == typeof(one(Rational{T}) * one(Rational{S})) == U + @test typeof(one(Rational{T}) // one(S)) == typeof(one(S) // one(Rational{T})) == typeof(one(Rational{T}) // one(Rational{S})) == U + end + @test (-40//3) // 0x5 == 0x5 // (-15//8) == -8//3 + @test (-4//7) // (0x1//0x3) == (0x4//0x7) // (-1//3) == -12//7 + @test -3//2 + 0x1//0x1 == -3//2 + 0x1 == 0x1//0x1 + (-3//2) == 0x1 + (-3//2) == -1//2 + @test 0x3//0x5 - 2//3 == 3//5 - 0x2//0x3 == -1//15 + @test rem(-12//5, 0x2//0x1) == rem(-12//5, 0x2) == -2//5 + @test mod(0x3//0x1, -4//7) == mod(0x3, -4//7) == -3//7 + @test -1//5 * 0x3//0x2 == 0x3//0x2 * -1//5 == -3//10 + @test -2//3 * 0x1 == 0x1 * -2//3 == -2//3 +end