Skip to content

Commit

Permalink
Update docs (#186)
Browse files Browse the repository at this point in the history
* add docstring to `@iv_str`

* update autodocs

* update docs with `iv_str` macro

* update docs

* update docstrings

* add docs about `plot` visualization
  • Loading branch information
hyrodium authored Feb 12, 2024
1 parent ec3670b commit fe1c7cd
Show file tree
Hide file tree
Showing 5 changed files with 282 additions and 21 deletions.
1 change: 1 addition & 0 deletions docs/Project.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
[deps]
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
IntervalSets = "8197267c-284f-5f27-9208-e0e47529a953"
Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"

[compat]
Documenter = "1"
2 changes: 1 addition & 1 deletion docs/src/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@

```@autodocs
Modules = [IntervalSets]
Order = [:type, :function]
Order = [:type, :function, :macro]
```
46 changes: 41 additions & 5 deletions docs/src/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ 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`](@ref) is short for `Interval{:closed,:closed}`,
while [`OpenInterval`](@ref) is short for `Interval{:open,:open}`.
For example, the interval `Interval{:open,:closed}` corresponds to the set ``\{x \ | \ a < x ≤ b\}``.
For example, the interval `Interval{:open,:closed}` corresponds to the set ``(a,b] = \{x \ | \ a < x ≤ b\}``.

## More examples

Expand All @@ -51,13 +51,24 @@ using IntervalSets
ClosedInterval{Float64}(1,3)
OpenInterval{Float64}(1,3)
Interval{:open, :closed}(1,3)
0.5..2.5
1.5 ± 1
Interval{:open,:closed}(1,3)
OpenInterval(0.5..2.5) # construct `OpenInterval` from `ClosedInterval`
```

The [`±`](@ref) operator may be typed as `\pm<TAB>` (using Julia's LaTeX syntax tab-completion).
The [`±`](@ref) operator and [`..`](@ref) creates [`ClosedInterval`](@ref) instance.

```@repl more
0.5..2.5
1.5 ± 1 # \pm<TAB>
```

There is also a useful string macro [`@iv_str`](@ref) to define an interval with mathematical notations such as ``(a,b]``.

```@repl more
iv"[1,2]"
iv"[1,2)"
iv"(1,2]"
iv"(1,2)"
```

### Set operations

Expand All @@ -74,6 +85,31 @@ isleftopen(2..3)
(0.25..5) ∪ (6..7.4) # union of interval must be an interval
```

### Visualization
`Interval`s can be visulalized with `Plots.plot` function.

```@example plot
using IntervalSets, Plots
plot(iv"(1,2)")
plot!(iv"[3,6)")
plot!(iv"[5,7)")
savefig("plot-intervals.png") # hide
nothing # hide
```

![](plot-intervals.png)

The `offset` keyword argument is useful for avoid duplication.

```@example plot
plot(iv"[1,3]")
plot!(iv"(2,4)"; offset=-0.1, ylims=(-1,1))
savefig("plot-intervals-offset.png") # hide
nothing # hide
```

![](plot-intervals-offset.png)

### Importing the `..` operator

To import the [`..`](@ref) operator, use `import IntervalSets: (..)`.
Expand Down
217 changes: 203 additions & 14 deletions src/IntervalSets.jl
Original file line number Diff line number Diff line change
Expand Up @@ -25,37 +25,184 @@ A subtype of `AbstractInterval{T}` represents an interval subset of type `T`, th
"""
abstract type AbstractInterval{T} <: Domain{T} end

"""
endpoints(d::AI) where AI<:AbstractInterval
A tuple containing the left and right endpoints of the interval.
"A tuple containing the left and right endpoints of the interval."
# Examples
```jldoctest
julia> endpoints(iv"[1,2]")
(1, 2)
julia> endpoints(iv"(2,1)")
(2, 1)
```
"""
endpoints(d::AI) where AI<:AbstractInterval = error("Override endpoints(::$(AI))")

"The left endpoint of the interval."
"""
leftendpoint(d::AbstractInterval)
The left endpoint of the interval.
# Examples
```jldoctest
julia> leftendpoint(iv"[1,2]")
1
julia> leftendpoint(iv"(2,1)")
2
```
"""
leftendpoint(d::AbstractInterval) = endpoints(d)[1]

"The right endpoint of the interval."
"""
rightendpoint(d::AbstractInterval)
The right endpoint of the interval.
# Examples
```jldoctest
julia> rightendpoint(iv"[1,2]")
2
julia> rightendpoint(iv"(2,1)")
1
```
"""
rightendpoint(d::AbstractInterval) = endpoints(d)[2]

"A tuple of `Bool`'s encoding whether the left/right endpoints are closed."
"""
closedendpoints(d::AI) where AI<:AbstractInterval
A tuple of `Bool`'s encoding whether the left/right endpoints are closed.
# Examples
```jldoctest
julia> closedendpoints(iv"[1,2]")
(true, true)
julia> closedendpoints(iv"(1,2]")
(false, true)
julia> closedendpoints(iv"[2,1)")
(true, false)
julia> closedendpoints(iv"(2,1)")
(false, false)
```
"""
closedendpoints(d::AI) where AI<:AbstractInterval = error("Override closedendpoints(::$(AI))")

"Is the interval closed at the left endpoint?"
"""
isleftclosed(d::AbstractInterval)
Is the interval closed at the left endpoint?
# Examples
```jldoctest
julia> isleftclosed(iv"[1,2]")
true
julia> isleftclosed(iv"(2,1)")
false
```
"""
isleftclosed(d::AbstractInterval) = closedendpoints(d)[1]

"Is the interval closed at the right endpoint?"
"""
isrightclosed(d::AbstractInterval)
Is the interval closed at the right endpoint?
# Examples
```jldoctest
julia> isrightclosed(iv"[1,2]")
true
julia> isrightclosed(iv"(2,1)")
false
```
"""
isrightclosed(d::AbstractInterval) = closedendpoints(d)[2]

# open_left and open_right are implemented in terms of closed_* above, so those
# are the only ones that should be implemented for specific intervals
"Is the interval open at the left endpoint?"
"""
isleftopen(d::AbstractInterval)
Is the interval open at the left endpoint?
# Examples
```jldoctest
julia> isleftopen(iv"[1,2]")
false
julia> isleftopen(iv"(2,1)")
true
```
"""
isleftopen(d::AbstractInterval) = !isleftclosed(d)

"Is the interval open at the right endpoint?"
"""
isrightopen(d::AbstractInterval)
Is the interval open at the right endpoint?
# Examples
```jldoctest
julia> isrightopen(iv"[1,2]")
false
julia> isrightopen(iv"(2,1)")
true
```
"""
isrightopen(d::AbstractInterval) = !isrightclosed(d)

# Only closed if closed at both endpoints, and similar for open
"""
isclosedset(d::AbstractInterval)
Is the interval closed set?
# Examples
```jldoctest
julia> isclosedset(iv"[1,2]")
true
julia> isclosedset(iv"(1,2]")
false
julia> isclosedset(iv"[1,2)")
false
julia> isclosedset(iv"(1,2)")
false
```
"""
isclosedset(d::AbstractInterval) = isleftclosed(d) && isrightclosed(d)

"Is the interval open?"
"""
isopenset(d::AbstractInterval)
Is the interval open set?
# Examples
```jldoctest
julia> isopenset(iv"[1,2]")
false
julia> isopenset(iv"(1,2]")
false
julia> isopenset(iv"[1,2)")
false
julia> isopenset(iv"(1,2)")
true
```
"""
isopenset(d::AbstractInterval) = isleftopen(d) && isrightopen(d)

eltype(::Type{AbstractInterval{T}}) where {T} = T
Expand Down Expand Up @@ -94,6 +241,15 @@ mean(d::AbstractInterval) = (leftendpoint(d) + rightendpoint(d))/2
Calculate the width (max-min) of interval `iv`. Note that for integers
`l` and `r`, `width(l..r) = length(l:r) - 1`.
# Examples
```jldoctest
julia> width(2..7)
5
julia> length(2:7)
6
```
"""
function width(A::AbstractInterval)
_width = rightendpoint(A) - leftendpoint(A)
Expand Down Expand Up @@ -206,28 +362,61 @@ range(i::TypedEndpointsInterval{:closed,:closed,I}) where {I<:Integer} = UnitRan

"""
range(i::ClosedInterval; step, length)
range(i::ClosedInterval, len::Integer)
range(i::ClosedInterval, length::Integer)
Constructs a range of a specified step or length.
# Examples
```jldoctest
julia> range(1..2, 8)
1.0:0.14285714285714285:2.0
julia> range(1, 2, 8)
1.0:0.14285714285714285:2.0
julia> range(1..2, step=0.2)
1.0:0.2:2.0
julia> range(1, 2, step=0.2)
1.0:0.2:2.0
```
"""
range(i::TypedEndpointsInterval{:closed,:closed}; step=nothing, length=nothing) =
range(leftendpoint(i); stop=rightendpoint(i), step=step, length=length)
range(i::TypedEndpointsInterval{:closed,:closed}, len::Integer) = range(i; length=len)
range(i::TypedEndpointsInterval{:closed,:closed}, length::Integer) = range(i; length=length)

"""
range(i::Interval{:closed,:open}; length)
range(i::Interval{:closed,:open}, len::Integer)
range(i::Interval{:closed,:open}, length::Integer)
Constructs a range of a specified length with `step=width(i)/length`.
# Examples
```jldoctest
julia> range(iv"[1, 2)", 7) # Does not contain right endpoint
1.0:0.14285714285714285:1.8571428571428572
julia> range(1, 2, 8)
1.0:0.14285714285714285:2.0
```
"""
range(i::TypedEndpointsInterval{:closed,:open}; length::Integer) =
range(leftendpoint(i); step=width(i)/length, length=length)
range(i::TypedEndpointsInterval{:closed,:open}, len::Integer) = range(i; length=len)
range(i::TypedEndpointsInterval{:closed,:open}, length::Integer) = range(i; length=length)

"""
clamp(t, i::ClosedInterval)
Clamp the scalar `t` such that the result is in the interval `i`.
# Examples
```jldoctest
julia> clamp(1.2, 1..2)
1.2
julia> clamp(2.2, 1..2)
2.0
```
"""
clamp(t, i::TypedEndpointsInterval{:closed,:closed}) =
clamp(t, leftendpoint(i), rightendpoint(i))
Expand Down
Loading

0 comments on commit fe1c7cd

Please sign in to comment.