diff --git a/base/range.jl b/base/range.jl index f2f3e26edf2f2..86fdba42375c2 100644 --- a/base/range.jl +++ b/base/range.jl @@ -1168,6 +1168,16 @@ function ==(r::AbstractRange, s::AbstractRange) return true end +function cmp(r1::AbstractRange{T}, r2::AbstractRange{T}) where {T} + firstindex(r1) == firstindex(r2) || return cmp(firstindex(r1), firstindex(r2)) + (isempty(r1) || isempty(r2)) && return cmp(isempty(r2), isempty(r1)) + first(r1) != first(r2) && return cmp(first(r1), first(r2)) + # Assume that ranges are monotonic and use the last shared element as a high precision proxy for step. + x1, x2 = last(zip(r1, r2)) + x1 != x2 && return cmp(x1, x2) + cmp(length(r1), length(r2)) +end + intersect(r::OneTo, s::OneTo) = OneTo(min(r.stop,s.stop)) union(r::OneTo, s::OneTo) = OneTo(max(r.stop,s.stop)) diff --git a/test/ranges.jl b/test/ranges.jl index 9bad12e6692d2..d903f7c16cf43 100644 --- a/test/ranges.jl +++ b/test/ranges.jl @@ -2831,3 +2831,30 @@ end @test StepRange(r) == r @test StepRange(r) isa StepRange{Date,Day} end + +const EXAMPLE_RANGES = AbstractRange[ + 1:10, + 1:5, + 1:0, + 1:1, + 3:2, + 3:0, + 10:-1:1, + 1:2:10, + 10:-2:1, + LinRange(1.0, 10.0, 10), + LinRange(10.0, 1.0, 10), + 1e10:1.99:(1e10 + 2), + 1e10:(1.99+eps()):(1e10 + 2), + StepRangeLen(1, 2, 5), + StepRangeLen(10, -2, 5), + UInt8(1):UInt8(10), + UInt8(10):-UInt8(1):UInt8(1), + 'a':'z', +] + +@testset "cmp(::AbstractRange, ::AbstractRange)" begin + for a in EXAMPLE_RANGES, b in EXAMPLE_RANGES + @test try cmp(a, b) catch e; e end == try cmp(collect(a), collect(b)) catch e; e end + end +end