Skip to content

Commit 6d9c642

Browse files
committed
Take advantage of updates in ArrayInterface
1 parent f993af0 commit 6d9c642

11 files changed

+155
-119
lines changed

Project.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "StaticRanges"
22
uuid = "d8176aec-3168-11e9-3c98-e3954798be3a"
33
authors = ["zchristensen "]
4-
version = "0.8.1"
4+
version = "0.8.2"
55

66
[deps]
77
ArrayInterface = "4fba245c-0d91-5ea0-9b3e-6abc04ee57a9"

src/GapRange/GapRange.jl

+56-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,59 @@
11

22
include("type.jl")
3-
include("getindex.jl")
3+
4+
# GapRange
5+
unsafe_index_first(gr::GapRange, i) = @inbounds(getindex(first_range(gr), i))
6+
function unsafe_index_last(gr::GapRange, i)
7+
return @inbounds(getindex(last_range(gr), i .- first_length(gr)))
8+
end
9+
10+
function Base.getindex(gr::GapRange, i::Integer)
11+
@boundscheck checkbounds(gr, i)
12+
return i <= first_length(gr) ? unsafe_index_first(gr, i) : unsafe_index_last(gr, i)
13+
end
14+
15+
@propagate_inbounds function Base.getindex(r::AbstractRange, gr::GapRange)
16+
fr = r[gr.first_range]
17+
lr = r[gr.last_range]
18+
return GapRange{eltype(r),typeof(fr),typeof(lr)}(fr, lr)
19+
end
20+
21+
@propagate_inbounds function Base.getindex(gr::GapRange, v::AbstractRange)
22+
@boundscheck checkbounds(gr, v)
23+
fr = first_range(gr)
24+
lr = last_range(gr)
25+
if checkindexhi(fr, minimum(v))
26+
if checkindexlo(lr, maximum(v))
27+
return unsafe_spanning_getindex(gr, v)
28+
else
29+
# largest value of `v` is not found in last segment so only index first segment
30+
return unsafe_index_first(gr, v)
31+
end
32+
else
33+
# smallest value of `v` is not found in first segment so only index last segment
34+
return unsafe_index_last(gr, v)
35+
end
36+
end
37+
38+
function unsafe_spanning_getindex(gr, v)
39+
ltfli = find_all(<=(first_lastindex(gr)), v)
40+
gtlfi = find_all(>=(last_firstindex(gr)), v)
41+
if is_forward(v)
42+
return _unsafe_gaprange(
43+
unsafe_index_first(gr, @inbounds(v[ltfli])),
44+
unsafe_index_last(gr, @inbounds(v[gtlfi]))
45+
)
46+
else # is_reverse(v)
47+
return _unsafe_gaprange(
48+
unsafe_index_last(gr, @inbounds(v[gtlfi])),
49+
unsafe_index_first(gr, @inbounds(v[ltfli]))
50+
)
51+
end
52+
end
53+
54+
Base.checkbounds(::Type{Bool}, gr::GapRange, i::Integer) = checkindex(Bool, gr, i)
55+
56+
function Base.checkindex(::Type{Bool}, gr::GapRange, i::Integer)
57+
return checkindexlo(gr, i) & checkindexhi(gr, i)
58+
end
459

src/GapRange/getindex.jl

-71
This file was deleted.

src/GapRange/type.jl

+7
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
12
"""
23
GapRange{T,F,L}
34
@@ -173,3 +174,9 @@ Base.lastindex(gr::GapRange) = length(gr)
173174

174175
last_firstindex(gr::GapRange) = lastindex(first_range(gr)) + 1
175176

177+
function Base.AbstractArray{T}(gr::GapRange) where {T}
178+
fr = AbstractRange{T}(gr.first_range)
179+
lr = AbstractRange{T}(gr.last_range)
180+
return GapRange{T,typeof(fr),typeof(lr)}(fr, lr)
181+
end
182+

src/StaticRanges.jl

+2-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ using Reexport
1313
using ArrayInterface
1414
using ArrayInterface: can_change_size, can_setindex, parent_type
1515
using ArrayInterface: known_first, known_step, known_last, known_length
16-
using ArrayInterface: OptionallyStaticUnitRange
16+
using ArrayInterface: static_first, static_last
17+
using ArrayInterface: OptionallyStaticUnitRange, unsafe_reconstruct, StaticInt, OptionallyStaticRange
1718

1819
using IntervalSets
1920
using Requires

src/first.jl

+21-10
Original file line numberDiff line numberDiff line change
@@ -49,14 +49,12 @@ function set_first!(x::AbstractVector{T}, val) where {T}
4949
return x
5050
end
5151

52-
function set_first!(x::AbstractUnitRange{T}, val) where {T}
53-
can_set_first(x) || throw(MethodError(set_first!, (x, val)))
52+
function set_first!(x::UnitMRange{T}, val) where {T}
5453
setfield!(x, :start, T(val))
5554
return x
5655
end
5756

58-
function set_first!(x::OrdinalRange{T,S}, val) where {T,S}
59-
can_set_first(x) || throw(MethodError(set_first!, (x, val)))
57+
function set_first!(x::StepMRange{T,S}, val) where {T,S}
6058
val2 = T(val)
6159
setfield!(x, :start, val2)
6260
setfield!(x, :stop, Base.steprange_last(val2, step(x), last(x)))
@@ -67,6 +65,15 @@ function set_first!(x::StepMRangeLen{T,R}, val) where {T,R}
6765
return setfield!(x, :ref, R(val) - (1 - x.offset) * step_hp(x))
6866
end
6967
set_first!(x::LinMRange{T}, val) where {T} = (setfield!(x, :start, T(val)); x)
68+
function set_first!(x::AbstractRange, val)
69+
if parent_type(x) <: typeof(x)
70+
throw(MethodError(set_first!, (x, val)))
71+
else
72+
set_first!(parent(x), val)
73+
return x
74+
end
75+
end
76+
7077

7178
"""
7279
set_first(x, val)
@@ -90,14 +97,18 @@ function set_first(x::AbstractVector, val)
9097
return vcat(val, @inbounds(x[2:end]))
9198
end
9299
end
93-
94-
set_first(x::OrdinalRange, val) = typeof(x)(val, step(x), last(x))
95-
96-
set_first(x::AbstractUnitRange{T}, val) where {T} = typeof(x)(T(val), last(x))
97-
100+
set_first(x::OptionallyStaticRange, val) = val:ArrayInterface.static_step(x):static_last(x)
101+
function set_first(x::AbstractRange{T}, val) where {T}
102+
if parent_type(x) <: typeof(x)
103+
throw(MethodError(set_first, (x, val)))
104+
else
105+
return ArrayInterface.unsafe_reconstruct(x, set_first(parent(x), val))
106+
end
107+
end
108+
set_first(x::Union{<:StepRange,<:StepSRange,<:StepMRange}, val) = typeof(x)(val, step(x), last(x))
109+
set_first(x::Union{<:UnitRange,<:UnitSRange,<:UnitMRange}, val) = typeof(x)(val, last(x))
98110
set_first(x::AbstractStepRangeLen, val) = typeof(x)(val, step(x), x.len, x.offset)
99111
set_first(x::StepRangeLen, val) = typeof(x)(val, step(x), x.len, x.offset)
100-
101112
set_first(x::LinRange, val) = typeof(x)(val, last(x), x.len)
102113
set_first(x::AbstractLinRange, val) = typeof(x)(val, last(x), x.len)
103114

src/last.jl

+37-22
Original file line numberDiff line numberDiff line change
@@ -46,33 +46,37 @@ function set_last!(x::AbstractVector, val)
4646
setindex!(x, val, lastindex(x))
4747
return x
4848
end
49-
50-
function set_last!(x::OrdinalRange{T}, val) where {T}
51-
can_set_last(x) || throw(MethodError(set_last!, (x, val)))
52-
if known_step(x) === oneunit(eltype(x))
53-
if known_first(x) === oneunit(T)
54-
setfield!(x, :stop, max(zero(T), T(val)))
55-
else
56-
setfield!(x, :stop, T(val))
57-
end
58-
else
59-
setfield!(x, :stop, T(Base.steprange_last(first(x), step(x), val)))
60-
end
61-
return x
62-
end
63-
6449
function set_last!(x::StepMRangeLen{T}, val) where {T}
6550
len = unsafe_find_value(val, x) # FIXME should not use unsafe_find_value at this point
6651
len >= 0 || throw(ArgumentError("length cannot be negative, got $len"))
6752
1 <= x.offset <= max(1, len) || throw(ArgumentError("StepSRangeLen: offset must be in [1,$len], got $(x.offset)"))
6853
setfield!(x, :len, len)
6954
return x
7055
end
71-
7256
function set_last!(x::LinMRange{T}, val) where {T}
7357
setfield!(x, :stop, T(val))
7458
return x
7559
end
60+
function set_last!(x::StepMRange{T}, val) where {T}
61+
setfield!(x, :stop, T(Base.steprange_last(first(x), step(x), val)))
62+
return x
63+
end
64+
function set_last!(x::UnitMRange{T}, val) where {T}
65+
setfield!(x, :stop, T(val))
66+
return x
67+
end
68+
function set_last!(x::OneToMRange{T}, val) where {T}
69+
setfield!(x, :stop, max(zero(T), T(val)))
70+
return x
71+
end
72+
function set_last!(x::AbstractRange, val)
73+
if parent_type(x) <: typeof(x)
74+
throw(MethodError(set_last!, (x, val)))
75+
else
76+
set_last!(parent(x), val)
77+
return x
78+
end
79+
end
7680

7781
"""
7882
set_last(x, val)
@@ -98,14 +102,25 @@ function set_last(x::AbstractVector, val)
98102
return vcat(@inbounds(x[1:end-1]), val)
99103
end
100104
end
101-
102-
set_last(x::OrdinalRange, val) = typeof(x)(first(x), step(x), val)
103-
set_last(x::AbstractUnitRange, val) = typeof(x)(first(x), val)
104-
set_last(x::OneTo, val) = typeof(x)(val)
105-
set_last(x::OneToSRange, val) = typeof(x)(val)
106-
set_last(x::OneToMRange, val) = typeof(x)(val)
105+
set_last(x::OptionallyStaticRange, val) = static_first(x):ArrayInterface.static_step(x):val
106+
function set_last(x::AbstractRange{T}, val) where {T}
107+
if parent_type(x) <: typeof(x)
108+
throw(MethodError(set_last, (x, val)))
109+
else
110+
return ArrayInterface.unsafe_reconstruct(x, set_last(parent(x), val))
111+
end
112+
end
113+
set_last(x::Union{<:StepRange,<:StepSRange,<:StepMRange}, val) = typeof(x)(first(x), step(x), val)
114+
set_last(x::Union{<:UnitRange,<:UnitSRange,<:UnitMRange}, val) = typeof(x)(first(x), val)
107115
set_last(x::Union{<:LinRange,<:LinMRange,<:LinSRange}, val) = typeof(x)(first(x), val, x.len)
108116
function set_last(x::Union{<:StepRangeLen,<:StepMRangeLen,<:StepSRangeLen}, val)
109117
return typeof(x)(x.ref, x.step, unsafe_find_value(val, x), x.offset)
110118
end
119+
@inline function set_last(x::Union{<:OneTo,<:OneToSRange,<:OneToMRange}, val)
120+
if val isa StaticInt
121+
return One():val
122+
else
123+
typeof(x)(val)
124+
end
125+
end
111126

src/length.jl

+16-11
Original file line numberDiff line numberDiff line change
@@ -124,22 +124,29 @@ function set_length!(x::StepMRangeLen, len)
124124
return x
125125
end
126126

127-
function set_length!(x::OrdinalRange{T}, len) where {T}
127+
function set_length!(x::StepMRange{T}, len) where {T}
128128
can_set_length(x) || throw(MethodError(set_length!, (x, len)))
129129
setfield!(x, :stop, convert(T, first(x) + step(x) * (len - 1)))
130130
return x
131131
end
132-
133-
function set_length!(x::AbstractUnitRange{T}, len) where {T}
134-
can_set_length(x) || throw(MethodError(set_length!, (x, len)))
135-
if known_first(x) === one(T)
136-
set_last!(x, len)
132+
function set_length!(x::OneToMRange{T}, len) where {T}
133+
set_last!(x, T(max(zero(T), len)))
134+
return x
135+
end
136+
function set_length!(x::UnitMRange{T}, len) where {T}
137+
set_last!(x, T(first(x)+len-1))
138+
return x
139+
end
140+
function set_length!(x::AbstractRange, len)
141+
if parent_type(x) <: typeof(x)
142+
error("Cannot use set_length! for instances of typeof $(typeof(x)).")
137143
else
138-
set_last!(x, T(first(x)+len-1))
144+
set_length!(parent(x), len)
145+
return x
139146
end
140-
return x
141147
end
142148

149+
143150
"""
144151
set_length(x, len)
145152
@@ -157,15 +164,13 @@ set_length(x::AbstractStepRangeLen, len) = typeof(x)(x.ref, x.step, len, x.offse
157164
set_length(x::StepRangeLen, len) = typeof(x)(x.ref, x.step, len, x.offset)
158165
set_length(x::LinRange, len) = typeof(x)(first(x), last(x), len)
159166
set_length(x::AbstractLinRange, len) = typeof(x)(first(x), last(x), len)
160-
161167
function set_length(x::AbstractUnitRange{T}, len) where {T}
162168
if known_first(x) === oneunit(T)
163169
return set_last(x, len)
164170
else
165-
return set_last(x, T(first(x)+len-1))
171+
return set_last(x, static_first(x) + len - one(len))
166172
end
167173
end
168-
169174
function set_length(x::OrdinalRange{T}, len) where {T}
170175
return set_last(x, convert(T, first(x) + step(x) * (len - 1)))
171176
end

src/onetorange.jl

+3
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ struct OneToSRange{T<:Integer,E} <: OneToRange{T}
3030

3131
OneToSRange{T,L}(stop) where {T<:Integer,L} = OneToSRange{T,T(stop)}()
3232

33+
OneToSRange{T,L}(r::AbstractRange) where {T<:Integer,L} = OneToSRange{T}(r)
34+
35+
3336
function OneToSRange{T}(r::AbstractRange) where {T<:Integer}
3437
first(r) == 1 || (Base.@_noinline_meta; throw(ArgumentError("first element must be 1, got $(first(r))")))
3538
step(r) == 1 || (Base.@_noinline_meta; throw(ArgumentError("step must be 1, got $(step(r))")))

0 commit comments

Comments
 (0)