@@ -15,65 +15,83 @@ function searchsortednearest(vec::AbstractVector, x)
15
15
end
16
16
return idx
17
17
end
18
+ # Base only specializes searching ranges by Numbers; so optimize for Intervals
19
+ function Base. searchsorted (a:: Range , I:: ClosedInterval )
20
+ searchsortedfirst (a, I. left): searchsortedlast (a, I. right)
21
+ end
18
22
19
- # We depend upon extrapolative behaviors in searching ranges to shift axes.
20
- # This can be done by stealing Base's implementations and removing the bounds-
21
- # correcting min/max.
23
+ """
24
+ The internal `Extrapolated` module contains implementations for indexing and
25
+ searching into ranges beyond their bounds. The `@inbounds` macro is not
26
+ sufficient since it can be turned off by `--check-bounds=yes`.
27
+ """
28
+ module Extrapolated
29
+ using .. ClosedInterval
30
+
31
+ function searchsortednearest (vec:: Range , x)
32
+ idx = searchsortedfirst (vec, x) # Returns the first idx | vec[idx] >= x
33
+ if (getindex (vec, idx) - x) > (x - getindex (vec, idx- 1 ))
34
+ idx -= 1 # The previous element is closer
35
+ end
36
+ return idx
37
+ end
22
38
23
- # TODO : This could plug into the sorting system better, but it's fine for now
24
- # TODO : This needs to support Dates.
25
39
"""
26
- unsafe_searchsorted (a::Range, I::ClosedInterval)
40
+ searchsorted (a::Range, I::ClosedInterval)
27
41
28
42
Return the indices of the range that fall within an interval without checking
29
43
bounds, possibly extrapolating outside the range if needed.
30
44
"""
31
- function unsafe_searchsorted (a:: Range , I:: ClosedInterval )
32
- unsafe_searchsortedfirst (a, I. left): unsafe_searchsortedlast (a, I. right)
33
- end
34
- # Base only specializes searching ranges by Numbers; so optimize for Intervals
35
- function Base. searchsorted (a:: Range , I:: ClosedInterval )
45
+ function searchsorted (a:: Range , I:: ClosedInterval )
36
46
searchsortedfirst (a, I. left): searchsortedlast (a, I. right)
37
47
end
38
48
39
- # When running with "--check-bounds=yes" (like on Travis), the bounds-check isn't elided
40
- @inline function inbounds_getindex {T} (v:: Range{T} , i:: Integer )
49
+ # When running with "--check-bounds=yes` (like on Travis), the bounds-check isn't elided
50
+ @inline function getindex {T} (v:: Range{T} , i:: Integer )
41
51
convert (T, first (v) + (i- 1 )* step (v))
42
52
end
43
- @inline function inbounds_getindex {T<:Integer} (r:: Range , s:: Range{T} )
53
+ @inline function getindex {T<:Integer} (r:: Range , s:: Range{T} )
44
54
f = first (r)
45
55
st = oftype (f, f + (first (s)- 1 )* step (r))
46
56
range (st, step (r)* step (s), length (s))
47
57
end
48
- @inline inbounds_getindex (r:: StepRangeLen , i:: Integer ) = Base. unsafe_getindex (r, i)
49
- @inline function inbounds_getindex (r:: StepRangeLen , s:: OrdinalRange )
50
- vfirst = Base. unsafe_getindex (r, first (s))
51
- StepRangeLen (vfirst, step (r)* step (s), length (s))
58
+ getindex (r:: Range , I:: Array ) = [getindex (r, i) for i in I]
59
+ @inline getindex (r:: StepRangeLen , i:: Integer ) = Base. unsafe_getindex (r, i)
60
+ @inline function getindex (r:: StepRangeLen , s:: AbstractUnitRange )
61
+ soffset = 1 + (r. offset - first (s))
62
+ soffset = clamp (soffset, 1 , length (s))
63
+ ioffset = first (s) + (soffset- 1 )
64
+ if ioffset == r. offset
65
+ StepRangeLen (r. ref, r. step, length (s), max (1 ,soffset))
66
+ else
67
+ StepRangeLen (r. ref + (ioffset- r. offset)* r. step, r. step, length (s), max (1 ,soffset))
68
+ end
52
69
end
53
70
54
- function unsafe_searchsortedlast {T<:Number} (a:: Range{T} , x:: Number )
71
+ function searchsortedlast (a:: Range , x)
55
72
step (a) == 0 && throw (ArgumentError (" ranges with a zero step are unsupported" ))
56
73
n = round (Integer,(x- first (a))/ step (a))+ 1
57
- isless (x, inbounds_getindex (a, n)) ? n- 1 : n
74
+ isless (x, getindex (a, n)) ? n- 1 : n
58
75
end
59
- function unsafe_searchsortedfirst {T<:Number} (a:: Range{T} , x:: Number )
76
+ function searchsortedfirst (a:: Range , x)
60
77
step (a) == 0 && throw (ArgumentError (" ranges with a zero step are unsupported" ))
61
78
n = round (Integer,(x- first (a))/ step (a))+ 1
62
- isless (inbounds_getindex (a, n), x) ? n+ 1 : n
79
+ isless (getindex (a, n), x) ? n+ 1 : n
63
80
end
64
- function unsafe_searchsortedlast {T<:Integer} (a:: Range{T} , x:: Number )
81
+ function searchsortedlast {T<:Integer} (a:: Range{T} , x)
65
82
step (a) == 0 && throw (ArgumentError (" ranges with a zero step are unsupported" ))
66
83
fld (floor (Integer,x)- first (a),step (a))+ 1
67
84
end
68
- function unsafe_searchsortedfirst {T<:Integer} (a:: Range{T} , x:: Number )
85
+ function searchsortedfirst {T<:Integer} (a:: Range{T} , x)
69
86
step (a) == 0 && throw (ArgumentError (" ranges with a zero step are unsupported" ))
70
87
- fld (floor (Integer,- x)+ first (a),step (a))+ 1
71
88
end
72
- function unsafe_searchsortedfirst {T<:Integer} (a:: Range{T} , x:: Unsigned )
89
+ function searchsortedfirst {T<:Integer} (a:: Range{T} , x:: Unsigned )
73
90
step (a) == 0 && throw (ArgumentError (" ranges with a zero step are unsupported" ))
74
91
- fld (first (a)- signed (x),step (a))+ 1
75
92
end
76
- function unsafe_searchsortedlast {T<:Integer} (a:: Range{T} , x:: Unsigned )
93
+ function searchsortedlast {T<:Integer} (a:: Range{T} , x:: Unsigned )
77
94
step (a) == 0 && throw (ArgumentError (" ranges with a zero step are unsupported" ))
78
95
fld (signed (x)- first (a),step (a))+ 1
79
96
end
97
+ end
0 commit comments