Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add searchsorted_interval #109

Merged
merged 2 commits into from
May 31, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name = "IntervalSets"
uuid = "8197267c-284f-5f27-9208-e0e47529a953"
version = "0.7.0"
version = "0.7.1"

[deps]
Dates = "ade2ca70-3891-5945-98fb-dc099432e06a"
Expand Down
3 changes: 2 additions & 1 deletion src/IntervalSets.jl
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ export AbstractInterval, Interval, OpenInterval, ClosedInterval,
⊇, .., ±, ordered, width, leftendpoint, rightendpoint, endpoints,
isopenset, isclosedset, isleftclosed, isrightclosed,
isleftopen, isrightopen, closedendpoints,
infimum, supremum
infimum, supremum,
searchsorted_interval

"""
A subtype of `Domain{T}` represents a subset of type `T`, that provides `in`.
Expand Down
25 changes: 25 additions & 0 deletions src/findall.jl
Original file line number Diff line number Diff line change
Expand Up @@ -83,3 +83,28 @@ function Base._findin(a::Union{AbstractArray, Tuple}, b::Interval)
end
ind
end

"""
searchsorted_interval(a, i::Interval)

Return the range of indices of `a` which is inside of the interval `i` (using binary search), assuming that
`a` is already sorted. Return an empty range located at the insertion point if a does not contain values in `i`.

# Examples
```jldoctest
julia> searchsorted_interval([1,2,3,5], 2..4)
2:3

julia> searchsorted_interval([1,2,3,5], 4..1)
4:3

julia> searchsorted_interval(Float64[], 1..3)
1:0
```
"""
function searchsorted_interval end

searchsorted_interval(X, i::Interval{:closed, :closed}) = searchsortedfirst(X, leftendpoint(i)) :searchsortedlast(X, rightendpoint(i))
searchsorted_interval(X, i::Interval{:closed, :open}) = searchsortedfirst(X, leftendpoint(i)) :(searchsortedfirst(X, rightendpoint(i)) - 1)
searchsorted_interval(X, i::Interval{ :open, :closed}) = (searchsortedlast(X, leftendpoint(i)) + 1):searchsortedlast(X, rightendpoint(i))
searchsorted_interval(X, i::Interval{ :open, :open}) = (searchsortedlast(X, leftendpoint(i)) + 1):(searchsortedfirst(X, rightendpoint(i)) - 1)
29 changes: 29 additions & 0 deletions test/findall.jl
Original file line number Diff line number Diff line change
Expand Up @@ -149,4 +149,33 @@ end
assert_in_interval(reverse(x), interval)
end
end

@testset "searchsorted" begin
x = [-10, 0, 1, 1 + eps(), 1.2, 1.5, 1.9, 2 - eps(), 2]
@test searchsorted_interval(x, -Inf..Inf) == 1:9
i = Interval{:closed, :closed}(1, 2)
@test searchsorted_interval(x, i) == findall(in(i),x) == 3:9
i = Interval{:open , :closed}(1, 2)
@test searchsorted_interval(x, i) == findall(in(i),x) == 4:9
i = Interval{:closed, :open }(1, 2)
@test searchsorted_interval(x, i) == findall(in(i),x) == 3:8
i = Interval{:open , :open }(1, 2)
@test searchsorted_interval(x, i) == findall(in(i),x) == 4:8
i = Interval{:closed, :closed}(1, 1)
@test searchsorted_interval(x, i) == findall(in(i),x) == 3:3
i = Interval{:open , :closed}(1, 1)
@test searchsorted_interval(x, i) == findall(in(i),x) == 3:2
i = Interval{:closed, :open }(1, 1)
@test searchsorted_interval(x, i) == findall(in(i),x) == 3:2
i = Interval{:open , :open }(1, 1)
@test searchsorted_interval(x, i) == findall(in(i),x) == 3:2
i = Interval{:closed, :closed}(2, 1)
@test searchsorted_interval(x, i) == findall(in(i),x) == 9:8
i = Interval{:open , :closed}(2, 1)
@test searchsorted_interval(x, i) == findall(in(i),x) == 9:8
i = Interval{:closed, :open }(2, 1)
@test searchsorted_interval(x, i) == findall(in(i),x) == 9:8
i = Interval{:open , :open }(2, 1)
@test searchsorted_interval(x, i) == findall(in(i),x) == 9:8
end
end