Skip to content

Commit 92c033a

Browse files
aplavinhyrodium
andauthored
rev=true in searchsorted_interval (#111)
* rev=true in searchsorted_interval Co-authored-by: hyrodium <[email protected]> * add zero-step range tests * use searchsorted(lt=<) --------- Co-authored-by: hyrodium <[email protected]>
1 parent c1f78d6 commit 92c033a

File tree

2 files changed

+20
-45
lines changed

2 files changed

+20
-45
lines changed

src/findall.jl

Lines changed: 14 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -34,45 +34,8 @@ julia> findall(in(Interval{:open,:closed}(1,6)), y) # (1,6], does not include 1
3434
5:14
3535
```
3636
"""
37-
function Base.findall(interval_d::Base.Fix2{typeof(in),Interval{L,R,T}}, x::AbstractRange) where {L,R,T}
38-
isempty(x) && return 1:0
39-
40-
interval = interval_d.x
41-
il, ir = firstindex(x), lastindex(x)
42-
δx = step(x)
43-
a,b = if δx < zero(δx)
44-
rev = findall(in(interval), reverse(x))
45-
isempty(rev) && return rev
46-
47-
a = (il+ir)-last(rev)
48-
b = (il+ir)-first(rev)
49-
50-
a,b
51-
else
52-
lx, rx = first(x), last(x)
53-
l = max(leftendpoint(interval), lx - oneunit(δx))
54-
r = min(rightendpoint(interval), rx + oneunit(δx))
55-
56-
(l > rx || r < lx) && return 1:0
57-
58-
a = il + max(0, round(Int, cld(l-lx, δx)))
59-
a += (a ir && (x[a] == l && L == :open || x[a] < l))
60-
61-
b = min(ir, round(Int, cld(r-lx, δx)) + il)
62-
b -= (b il && (x[b] == r && R == :open || x[b] > r))
63-
64-
a,b
65-
end
66-
# Reversing a range could change sign of values close to zero (cf
67-
# sign of the smallest element in x and reverse(x), where x =
68-
# range(BigFloat(-0.5),stop=BigFloat(1.0),length=10)), or more
69-
# generally push elements in or out of the interval (as can cld),
70-
# so we need to check once again.
71-
a += +(a < ir && x[a] interval) - (il < a && x[a-1] interval)
72-
b += -(il < b && x[b] interval) + (b < ir && x[b+1] interval)
73-
74-
a:b
75-
end
37+
Base.findall(interval_d::Base.Fix2{typeof(in), <:Interval}, x::AbstractRange) =
38+
searchsorted_interval(x, interval_d.x; rev=step(x) < zero(step(x)))
7639

7740
# We overload Base._findin to avoid an ambiguity that arises with
7841
# Base.findall(interval_d::Base.Fix2{typeof(in),Interval{L,R,T}}, x::AbstractArray)
@@ -85,7 +48,7 @@ function Base._findin(a::Union{AbstractArray, Tuple}, b::Interval)
8548
end
8649

8750
"""
88-
searchsorted_interval(a, i::Interval)
51+
searchsorted_interval(a, i::Interval; [rev=false])
8952
9053
Return the range of indices of `a` which is inside of the interval `i` (using binary search), assuming that
9154
`a` is already sorted. Return an empty range located at the insertion point if a does not contain values in `i`.
@@ -102,9 +65,15 @@ julia> searchsorted_interval(Float64[], 1..3)
10265
1:0
10366
```
10467
"""
105-
function searchsorted_interval end
68+
function searchsorted_interval(X, i::Interval{L, R}; rev=false) where {L, R}
69+
if rev === true
70+
_searchsorted_begin(X, rightendpoint(i), Val(R); rev):_searchsorted_end(X, leftendpoint(i), Val(L); rev)
71+
else
72+
_searchsorted_begin(X, leftendpoint(i), Val(L); rev):_searchsorted_end(X, rightendpoint(i), Val(R); rev)
73+
end
74+
end
10675

107-
searchsorted_interval(X, i::Interval{:closed, :closed}) = searchsortedfirst(X, leftendpoint(i)) :searchsortedlast(X, rightendpoint(i))
108-
searchsorted_interval(X, i::Interval{:closed, :open}) = searchsortedfirst(X, leftendpoint(i)) :(searchsortedfirst(X, rightendpoint(i)) - 1)
109-
searchsorted_interval(X, i::Interval{ :open, :closed}) = (searchsortedlast(X, leftendpoint(i)) + 1):searchsortedlast(X, rightendpoint(i))
110-
searchsorted_interval(X, i::Interval{ :open, :open}) = (searchsortedlast(X, leftendpoint(i)) + 1):(searchsortedfirst(X, rightendpoint(i)) - 1)
76+
_searchsorted_begin(X, x, ::Val{:closed}; rev) = searchsortedfirst(X, x; rev, lt=<)
77+
_searchsorted_begin(X, x, ::Val{:open}; rev) = searchsortedlast(X, x; rev, lt=<) + 1
78+
_searchsorted_end(X, x, ::Val{:closed}; rev) = searchsortedlast(X, x; rev, lt=<)
79+
_searchsorted_end(X, x, ::Val{:open}; rev) = searchsortedfirst(X, x; rev, lt=<) - 1

test/findall.jl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,12 @@ end
150150
end
151151
end
152152

153+
@testset "zero-step ranges" begin
154+
r = range(1, 1, length=10)
155+
@test findall(in(1..3),r) == 1:10
156+
@test findall(in(2..3),r) |> isempty
157+
end
158+
153159
@testset "searchsorted" begin
154160
x = [-10, 0, 1, 1 + eps(), 1.2, 1.5, 1.9, 2 - eps(), 2]
155161
@test searchsorted_interval(x, -Inf..Inf) == 1:9

0 commit comments

Comments
 (0)