Skip to content

Commit

Permalink
Replace in with issubset and fix #61 (#62)
Browse files Browse the repository at this point in the history
  • Loading branch information
hyrodium authored Apr 11, 2020
1 parent d7e4642 commit 9c7cc1c
Show file tree
Hide file tree
Showing 2 changed files with 104 additions and 48 deletions.
77 changes: 62 additions & 15 deletions src/IntervalSets.jl
Original file line number Diff line number Diff line change
Expand Up @@ -99,12 +99,6 @@ end

mean(d::AbstractInterval) = (leftendpoint(d) + rightendpoint(d))/2

issubset(A::AbstractInterval, B::AbstractInterval) = ((leftendpoint(A) in B) && (rightendpoint(A) in B)) || isempty(A)
(A::AbstractInterval, B::AbstractInterval) = issubset(B, A)
if VERSION < v"1.1.0-DEV.123"
issubset(x, B::AbstractInterval) = issubset(convert(AbstractInterval, x), B)
end

"""
w = width(iv)
Expand Down Expand Up @@ -143,22 +137,49 @@ in(::Missing, I::TypedEndpointsInterval{:open,:open}) = !isempty(I) && missing
in(::Missing, I::TypedEndpointsInterval{:closed,:open}) = !isempty(I) && missing
in(::Missing, I::TypedEndpointsInterval{:open,:closed}) = !isempty(I) && missing

in(a::AbstractInterval, b::TypedEndpointsInterval{:closed,:closed}) =
# The code below can be defined as
# ```
# function in(a::AbstractInterval, b::AbstractInterval)
# Base.depwarn("`in(a::AbstractInterval, b::AbstractInterval)` (equivalently, `a ∈ b`) is deprecated in favor of `issubset(a, b)` (equivalently, `a ⊆ b`). Note that the behavior for empty intervals is also changing.", :in)
# return in_deprecation(a, b)
# end
# ```
# but that makes ambiguity definition.
function in(a::AbstractInterval, b::TypedEndpointsInterval{:closed,:closed})
Base.depwarn("`in(a::AbstractInterval, b::AbstractInterval)` (equivalently, `a ∈ b`) is deprecated in favor of `issubset(a, b)` (equivalently, `a ⊆ b`). Note that the behavior for empty intervals is also changing.", :in)
return in_deprecation(a, b)
end
function in(a::AbstractInterval, b::TypedEndpointsInterval{:open,:open})
Base.depwarn("`in(a::AbstractInterval, b::AbstractInterval)` (equivalently, `a ∈ b`) is deprecated in favor of `issubset(a, b)` (equivalently, `a ⊆ b`). Note that the behavior for empty intervals is also changing.", :in)
return in_deprecation(a, b)
end
function in(a::AbstractInterval, b::TypedEndpointsInterval{:closed,:open})
Base.depwarn("`in(a::AbstractInterval, b::AbstractInterval)` (equivalently, `a ∈ b`) is deprecated in favor of `issubset(a, b)` (equivalently, `a ⊆ b`). Note that the behavior for empty intervals is also changing.", :in)
return in_deprecation(a, b)
end
function in(a::AbstractInterval, b::TypedEndpointsInterval{:open,:closed})
Base.depwarn("`in(a::AbstractInterval, b::AbstractInterval)` (equivalently, `a ∈ b`) is deprecated in favor of `issubset(a, b)` (equivalently, `a ⊆ b`). Note that the behavior for empty intervals is also changing.", :in)
return in_deprecation(a, b)
end

in_deprecation(a::AbstractInterval, b::TypedEndpointsInterval{:closed,:closed}) =
(leftendpoint(a) leftendpoint(b)) & (rightendpoint(a) rightendpoint(b))
in(a::TypedEndpointsInterval{:open,:open}, b::TypedEndpointsInterval{:open,:open}) =
in_deprecation(a::TypedEndpointsInterval{:open,:open}, b::TypedEndpointsInterval{:open,:open} ) =
(leftendpoint(a) leftendpoint(b)) & (rightendpoint(a) rightendpoint(b))
in(a::TypedEndpointsInterval{:closed,:open}, b::TypedEndpointsInterval{:open,:open}) =
in_deprecation(a::TypedEndpointsInterval{:closed,:open}, b::TypedEndpointsInterval{:open,:open} ) =
(leftendpoint(a) > leftendpoint(b)) & (rightendpoint(a) rightendpoint(b))
in(a::TypedEndpointsInterval{:open,:closed}, b::TypedEndpointsInterval{:open,:open}) =
in_deprecation(a::TypedEndpointsInterval{:open,:closed}, b::TypedEndpointsInterval{:open,:open} ) =
(leftendpoint(a) leftendpoint(b)) & (rightendpoint(a) < rightendpoint(b))
in(a::TypedEndpointsInterval{:closed,:closed}, b::TypedEndpointsInterval{:open,:open}) =
in_deprecation(a::TypedEndpointsInterval{:closed,:closed}, b::TypedEndpointsInterval{:open,:open} ) =
(leftendpoint(a) > leftendpoint(b)) & (rightendpoint(a) < rightendpoint(b))
in(a::TypedEndpointsInterval{:closed}, b::TypedEndpointsInterval{:open,:closed}) =
in_deprecation(a::TypedEndpointsInterval{:closed}, b::TypedEndpointsInterval{:open,:closed} ) =
(leftendpoint(a) > leftendpoint(b)) & (rightendpoint(a) rightendpoint(b))
in(a::TypedEndpointsInterval{:open}, b::TypedEndpointsInterval{:open,:closed}) =
in_deprecation(a::TypedEndpointsInterval{:open}, b::TypedEndpointsInterval{:open,:closed} ) =
(leftendpoint(a) leftendpoint(b)) & (rightendpoint(a) rightendpoint(b))
in_deprecation(a::TypedEndpointsInterval{L,:closed}, b::TypedEndpointsInterval{:closed,:open}) where L =
(leftendpoint(a) leftendpoint(b)) & (rightendpoint(a) < rightendpoint(b))
in_deprecation(a::TypedEndpointsInterval{L,:open}, b::TypedEndpointsInterval{:closed,:open}) where L =
(leftendpoint(a) leftendpoint(b)) & (rightendpoint(a) rightendpoint(b))
in(a::TypedEndpointsInterval{L,:closed}, b::TypedEndpointsInterval{:closed,:open}) where L = (leftendpoint(a) leftendpoint(b)) & (rightendpoint(a) < rightendpoint(b))
in(a::TypedEndpointsInterval{L,:open}, b::TypedEndpointsInterval{:closed,:open}) where L = (leftendpoint(a) leftendpoint(b)) & (rightendpoint(a) rightendpoint(b))

isempty(A::TypedEndpointsInterval{:closed,:closed}) = leftendpoint(A) > rightendpoint(A)
isempty(A::TypedEndpointsInterval) = leftendpoint(A) rightendpoint(A)
Expand All @@ -169,6 +190,32 @@ isequal(A::TypedEndpointsInterval, B::TypedEndpointsInterval) = isempty(A) & ise
==(A::TypedEndpointsInterval{L,R}, B::TypedEndpointsInterval{L,R}) where {L,R} = (leftendpoint(A) == leftendpoint(B) && rightendpoint(A) == rightendpoint(B)) || (isempty(A) && isempty(B))
==(A::TypedEndpointsInterval, B::TypedEndpointsInterval) = isempty(A) && isempty(B)

function issubset(A::TypedEndpointsInterval, B::TypedEndpointsInterval)
Al, Ar = endpoints(A)
Bl, Br = endpoints(B)
return isempty(A) | ( (Bl Al) & (Ar Br) )
end
function issubset(A::TypedEndpointsInterval{:closed,R1} where R1, B::TypedEndpointsInterval{:open,R2} where R2)
Al, Ar = endpoints(A)
Bl, Br = endpoints(B)
return isempty(A) | ( (Bl < Al) & (Ar Br) )
end
function issubset(A::TypedEndpointsInterval{L1,:closed} where L1, B::TypedEndpointsInterval{L2,:open} where L2)
Al, Ar = endpoints(A)
Bl, Br = endpoints(B)
return isempty(A) | ( (Bl Al) & (Ar < Br) )
end
function issubset(A::TypedEndpointsInterval{:closed,:closed}, B::TypedEndpointsInterval{:open,:open})
Al, Ar = endpoints(A)
Bl, Br = endpoints(B)
return isempty(A) | ( (Bl < Al) & (Ar < Br) )
end

(A::AbstractInterval, B::AbstractInterval) = issubset(B, A)
if VERSION < v"1.1.0-DEV.123"
issubset(x, B::AbstractInterval) = issubset(convert(AbstractInterval, x), B)
end

const _interval_hash = UInt == UInt64 ? 0x1588c274e0a33ad4 : 0x1e3f7252

hash(I::TypedEndpointsInterval, h::UInt) = hash(leftendpoint(I), hash(rightendpoint(I), hash(_interval_hash, h)))
Expand Down
75 changes: 42 additions & 33 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ struct IncompleteInterval <: AbstractInterval{Int} end
@test extrema(I) === (0, 3)

@test 2 in I
@test 1..2 in 0.5..2.5
@test issubset(1..2, 0.5..2.5)

@test @inferred(I L) == ClosedInterval(0, 5)
@test @inferred(I L) == ClosedInterval(1, 3)
Expand Down Expand Up @@ -343,36 +343,36 @@ struct IncompleteInterval <: AbstractInterval{Int} end
end
end

@testset "In" begin
@testset "Issubset" begin
I = 0..3
J = 1..2
@test J I
@test I J
@test OpenInterval(J) I
@test OpenInterval(I) J
@test J OpenInterval(I)
@test I OpenInterval(J)
@test OpenInterval(J) OpenInterval(I)
@test OpenInterval(I) OpenInterval(J)
@test Interval{:closed,:open}(J) OpenInterval(I)
@test Interval{:open,:closed}(J) OpenInterval(I)
@test Interval{:open,:closed}(J) Interval{:open,:closed}(I)
@test OpenInterval(I) OpenInterval(J)

@test Interval{:closed,:open}(J) I
@test I Interval{:closed,:open}(J)


@test I I
@test OpenInterval(I) I
@test Interval{:open,:closed}(I) I
@test Interval{:closed,:open}(I) I
@test I OpenInterval(I)
@test I Interval{:open,:closed}(I)
@test I Interval{:closed,:open}(I)

@test Interval{:closed,:open}(I) Interval{:closed,:open}(I)
@test Interval{:open,:closed}(I) Interval{:closed,:open}(I)
@test J I
@test I J
@test OpenInterval(J) I
@test OpenInterval(I) J
@test J OpenInterval(I)
@test I OpenInterval(J)
@test OpenInterval(J) OpenInterval(I)
@test OpenInterval(I) OpenInterval(J)
@test Interval{:closed,:open}(J) OpenInterval(I)
@test Interval{:open,:closed}(J) OpenInterval(I)
@test Interval{:open,:closed}(J) Interval{:open,:closed}(I)
@test OpenInterval(I) OpenInterval(J)

@test Interval{:closed,:open}(J) I
@test I Interval{:closed,:open}(J)


@test I I
@test OpenInterval(I) I
@test Interval{:open,:closed}(I) I
@test Interval{:closed,:open}(I) I
@test I OpenInterval(I)
@test I Interval{:open,:closed}(I)
@test I Interval{:closed,:open}(I)

@test Interval{:closed,:open}(I) Interval{:closed,:open}(I)
@test Interval{:open,:closed}(I) Interval{:closed,:open}(I)

@test !isequal(I, OpenInterval(I))
@test !(I == OpenInterval(I))
Expand Down Expand Up @@ -637,11 +637,20 @@ struct IncompleteInterval <: AbstractInterval{Int} end
@test_broken ismissing(2 in missing..1) # would be fixed by julialang#31171
end

@testset "in" begin
@test in(0.1, 0.0..1.0) == true
@test in(0.0, 0.0..1.0) == true
@test in(1.1, 0.0..1.0) == false
@test in(0.0, nextfloat(0.0)..1.0) == false
end

@testset "issubset" begin
@test issubset(0.1, 0.0..1.0) == true
@test issubset(0.0, 0.0..1.0) == true
@test issubset(1.1, 0.0..1.0) == false
@test issubset(0.0, nextfloat(0.0)..1.0) == false
@test issubset(Interval{:closed,:closed}(1,2), Interval{:closed,:closed}(1,2)) == true
@test issubset(Interval{:closed,:closed}(1,2), Interval{:open ,:open }(1,2)) == false
@test issubset(Interval{:closed,:open }(1,2), Interval{:open ,:open }(1,2)) == false
@test issubset(Interval{:open ,:closed}(1,2), Interval{:open ,:open }(1,2)) == false
@test issubset(Interval{:closed,:closed}(1,2), Interval{:closed,:closed}(1,prevfloat(2.0))) == false
@test issubset(Interval{:closed,:open }(1,2), Interval{:open ,:open }(prevfloat(1.0),2)) == true
end

@testset "missing in" begin
Expand Down

2 comments on commit 9c7cc1c

@timholy
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JuliaRegistrator
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Registration pull request created: JuliaRegistries/General/12747

After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.

This will be done automatically if the Julia TagBot GitHub Action is installed, or can be done manually through the github interface, or via:

git tag -a v0.5.0 -m "<description of version>" 9c7cc1c0c13159496440605f8f220b7f9cfae87b
git push origin v0.5.0

Please sign in to comment.