Skip to content

Commit

Permalink
Merge 48615cd into 1d76371
Browse files Browse the repository at this point in the history
  • Loading branch information
daanhb committed Feb 12, 2020
2 parents 1d76371 + 48615cd commit 08de3dc
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 32 deletions.
4 changes: 2 additions & 2 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
name = "IntervalSets"
uuid = "8197267c-284f-5f27-9208-e0e47529a953"
version = "0.4.0"
version = "0.5.0"

[deps]
Dates = "ade2ca70-3891-5945-98fb-dc099432e06a"
EllipsisNotation = "da5c29d0-fa7d-589e-88eb-ea29b0a81949"
Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"

[compat]
julia = "0.7, 1"
EllipsisNotation = "0.4"
julia = "0.7, 1"

[extras]
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
Expand Down
17 changes: 15 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,16 @@ intervals upon which other packages might build. In particular, we
for the reason that only one interval package can
unambiguously define the `..` and `±` operators (see below).

Currently this package defines one concrete type, `ClosedInterval`.
These define the closed set spanning from `a` to `b`, meaning the
Currently this package defines one concrete type, `Interval`.
These define the set spanning from `a` to `b`, meaning the
interval is defined as the set `{x}` satisfying `a ≤ x ≤ b`. This is
sometimes written `[a,b]` (mathematics syntax, not Julia syntax) or
`a..b`.

Optionally, `Interval{L,R}` can represent open and half-open intervals. The type
parameters `L` and `R` correspond to the left and right endpoint respectively.
The notation `ClosedInterval` is short for `Interval{:closed,:closed}`, while `OpenInterval` is short for `Interval{:open,:open}`. For example, the interval `Interval{:open,:closed}` corresponds to the set `{x}` satisfying `a < x ≤ b`.

## Usage

You can construct `ClosedInterval`s in a variety of ways:
Expand Down Expand Up @@ -73,6 +77,15 @@ true

julia> (0.25..5) (3..7.4) # \cup<TAB>; can also use union()
0.25..7.4

julia> isclosedset(0.5..2.0)
true

julia> isopenset(OpenInterval(0.5..2.5))
true

julia> isleftopen(2..3)
false
```

When computing the union, the result must also be an interval:
Expand Down
12 changes: 9 additions & 3 deletions src/IntervalSets.jl
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ import EllipsisNotation: Ellipsis

export AbstractInterval, Interval, OpenInterval, ClosedInterval,
, .., ±, ordered, width, duration, leftendpoint, rightendpoint, endpoints,
isclosed, isleftclosed, isrightclosed, isleftopen, isrightopen, closedendpoints,
isopenset, isclosedset, isleftclosed, isrightclosed,
isleftopen, isrightopen, closedendpoints,
infimum, supremum

"""
Expand Down Expand Up @@ -59,8 +60,13 @@ isleftopen(d::AbstractInterval) = !isleftclosed(d)
isrightopen(d::AbstractInterval) = !isrightclosed(d)

# Only closed if closed at both endpoints, and similar for open
isclosed(d::AbstractInterval) = isleftclosed(d) && isrightclosed(d)
isopen(d::AbstractInterval) = isleftopen(d) && isrightopen(d)
isclosedset(d::AbstractInterval) = isleftclosed(d) && isrightclosed(d)

"Is the interval open?"
isopenset(d::AbstractInterval) = isleftopen(d) && isrightopen(d)

@deprecate isopen(d) isopenset(d) false
@deprecate isclosed(d) isclosedset(d)

eltype(::Type{AbstractInterval{T}}) where {T} = T
@pure eltype(::Type{I}) where {I<:AbstractInterval} = eltype(supertype(I))
Expand Down
4 changes: 2 additions & 2 deletions src/interval.jl
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,11 @@ end
convert(::Type{Interval}, i::Interval) = i

function convert(::Type{II}, i::AbstractInterval) where II<:ClosedInterval
isclosed(i) || throw(InexactError(:convert,II,i))
isclosedset(i) || throw(InexactError(:convert,II,i))
II(i)
end
function convert(::Type{II}, i::AbstractInterval) where II<:OpenInterval
isopen(i) || throw(InexactError(:convert,II,i))
isopenset(i) || throw(InexactError(:convert,II,i))
II(i)
end
function convert(::Type{II}, i::AbstractInterval) where II<:Interval{:open,:closed}
Expand Down
46 changes: 23 additions & 23 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ struct IncompleteInterval <: AbstractInterval{Int} end

@testset "IntervalSets" begin
if VERSION >= v"1.1"
# Julia 1.0 defines getindex(a::GenericArray, i...) in Test,
# Julia 1.0 defines getindex(a::GenericArray, i...) in Test,
# which could cause an ambiguity with getindex(A::AbstractArray, ::EllipsisNotation.Ellipsis)
@test isempty(detect_ambiguities(IntervalSets, Base, Core))
end
Expand Down Expand Up @@ -146,17 +146,17 @@ struct IncompleteInterval <: AbstractInterval{Int} end
@test @inferred(convert(ClosedInterval{Float64}, I)) ===
@inferred(convert(AbstractInterval{Float64}, I)) ===
@inferred(convert(Domain{Float64}, I)) ===
@inferred(ClosedInterval{Float64}(I)) ===
@inferred(convert(TypedEndpointsInterval{:closed,:closed,Float64},I)) ===
@inferred(ClosedInterval{Float64}(I)) ===
@inferred(convert(TypedEndpointsInterval{:closed,:closed,Float64},I)) ===
0.0..3.0
@test @inferred(convert(ClosedInterval, I)) ===
@inferred(convert(Interval, I)) ===
@inferred(ClosedInterval(I)) ===
@inferred(Interval(I)) ===
@inferred(convert(AbstractInterval, I)) ===
@inferred(convert(Domain, I)) ===
@inferred(convert(TypedEndpointsInterval{:closed,:closed}, I)) ===
@inferred(convert(TypedEndpointsInterval{:closed,:closed,Int}, I)) ===
@inferred(convert(Domain, I)) ===
@inferred(convert(TypedEndpointsInterval{:closed,:closed}, I)) ===
@inferred(convert(TypedEndpointsInterval{:closed,:closed,Int}, I)) ===
@inferred(convert(ClosedInterval{Int}, I)) === I
@test_throws InexactError convert(OpenInterval, I)
@test_throws InexactError convert(Interval{:open,:closed}, I)
Expand All @@ -175,8 +175,8 @@ struct IncompleteInterval <: AbstractInterval{Int} end
@inferred(convert(Interval, J)) ===
@inferred(convert(AbstractInterval, J)) ===
@inferred(convert(Domain, J)) ===
@inferred(OpenInterval(J)) ===
@inferred(OpenInterval{Int}(J)) ===
@inferred(OpenInterval(J)) ===
@inferred(OpenInterval{Int}(J)) ===
@inferred(convert(OpenInterval{Int},J)) === OpenInterval(J)
J = Interval{:open,:closed}(I)
@test_throws InexactError convert(Interval{:closed,:open}, J)
Expand Down Expand Up @@ -244,27 +244,27 @@ struct IncompleteInterval <: AbstractInterval{Int} end
@test minimum(d) == infimum(d) == leftendpoint(d)
@test maximum(d) == supremum(d) == rightendpoint(d)

@test IntervalSets.isclosed(d)
@test !IntervalSets.isopen(d)
@test IntervalSets.isclosedset(d)
@test !IntervalSets.isopenset(d)
@test IntervalSets.isleftclosed(d)
@test !IntervalSets.isleftopen(d)
@test !IntervalSets.isrightopen(d)
@test IntervalSets.isrightclosed(d)
@test IntervalSets.isrightclosed(d)

@test convert(AbstractInterval, d) d
@test convert(AbstractInterval{T}, d) d
@test convert(IntervalSets.Domain, d) d
@test convert(IntervalSets.Domain{T}, d) d

d = OpenInterval(zero(T) .. one(T))
@test IntervalSets.isopen(d)
@test !IntervalSets.isclosed(d)
@test IntervalSets.isopen(d)
@test !IntervalSets.isclosed(d)
@test IntervalSets.isopenset(d)
@test !IntervalSets.isclosedset(d)
@test IntervalSets.isopenset(d)
@test !IntervalSets.isclosedset(d)
@test !IntervalSets.isleftclosed(d)
@test IntervalSets.isleftopen(d)
@test IntervalSets.isrightopen(d)
@test !IntervalSets.isrightclosed(d)
@test !IntervalSets.isrightclosed(d)
@test leftendpoint(d) d
@test BigFloat(leftendpoint(d)) d
@test nextfloat(leftendpoint(d)) d
Expand All @@ -285,12 +285,12 @@ struct IncompleteInterval <: AbstractInterval{Int} end
@test isempty(OpenInterval(1,1))

d = Interval{:open,:closed}(zero(T) .. one(T))
@test !IntervalSets.isopen(d)
@test !IntervalSets.isclosed(d)
@test !IntervalSets.isopenset(d)
@test !IntervalSets.isclosedset(d)
@test !IntervalSets.isleftclosed(d)
@test IntervalSets.isleftopen(d)
@test !IntervalSets.isrightopen(d)
@test IntervalSets.isrightclosed(d)
@test IntervalSets.isrightclosed(d)
@test leftendpoint(d) d
@test BigFloat(leftendpoint(d)) d
@test nextfloat(leftendpoint(d)) d
Expand All @@ -308,12 +308,12 @@ struct IncompleteInterval <: AbstractInterval{Int} end
@test_throws ArgumentError minimum(d)

d = Interval{:closed,:open}(zero(T) .. one(T))
@test !IntervalSets.isopen(d)
@test !IntervalSets.isclosed(d)
@test !IntervalSets.isopenset(d)
@test !IntervalSets.isclosedset(d)
@test IntervalSets.isleftclosed(d)
@test !IntervalSets.isleftopen(d)
@test IntervalSets.isrightopen(d)
@test !IntervalSets.isrightclosed(d)
@test !IntervalSets.isrightclosed(d)
@test leftendpoint(d) d
@test BigFloat(leftendpoint(d)) d
@test nextfloat(leftendpoint(d)) d
Expand Down Expand Up @@ -651,7 +651,7 @@ struct IncompleteInterval <: AbstractInterval{Int} end
@test ismissing(missing in Interval{:closed, :open}(0, 1))
@test ismissing(missing in Interval{:open, :closed}(0, 1))
end

@testset "complex in" begin
@test 0+im 0..2
@test 0+0im 0..2
Expand Down

0 comments on commit 08de3dc

Please sign in to comment.