Skip to content

Commit fc36f76

Browse files
authored
Idempotent indexing in range[IdOffsetRange] (#161)
* Idempotent indexing range[IdOffsetRange] * Add methods to index a UnitRange{<:Integer}
1 parent 5e09f12 commit fc36f76

File tree

3 files changed

+51
-32
lines changed

3 files changed

+51
-32
lines changed

src/OffsetArrays.jl

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -308,21 +308,20 @@ end
308308
@propagate_inbounds Base.getindex(a::OffsetRange, r::AbstractRange) = a.parent[r .- a.offsets[1]]
309309
@propagate_inbounds Base.getindex(a::AbstractRange, r::OffsetRange) = OffsetArray(a[parent(r)], r.offsets)
310310

311-
@propagate_inbounds Base.getindex(r::UnitRange, s::IIUR) =
312-
OffsetArray(r[s.indices], s)
313-
314-
@propagate_inbounds Base.getindex(r::StepRange, s::IIUR) =
315-
OffsetArray(r[s.indices], s)
316-
317-
# this method is needed for ambiguity resolution
318-
@propagate_inbounds Base.getindex(r::StepRangeLen{T,<:Base.TwicePrecision,<:Base.TwicePrecision}, s::IIUR) where T =
319-
OffsetArray(r[s.indices], s)
311+
for OR in [:IIUR, :IdOffsetRange]
312+
for R in [:StepRange, :StepRangeLen, :LinRange, :UnitRange]
313+
@eval @propagate_inbounds Base.getindex(r::$R, s::$OR) = OffsetArray(r[_unwrap(s)], axes(s))
314+
end
320315

321-
@propagate_inbounds Base.getindex(r::StepRangeLen{T}, s::IIUR) where {T} =
322-
OffsetArray(r[s.indices], s)
316+
# this method is needed for ambiguity resolution
317+
@eval @propagate_inbounds Base.getindex(r::StepRangeLen{T,<:Base.TwicePrecision,<:Base.TwicePrecision}, s::$OR) where T =
318+
OffsetArray(r[_unwrap(s)], axes(s))
319+
end
323320

324-
@propagate_inbounds Base.getindex(r::LinRange, s::IIUR) =
325-
OffsetArray(r[s.indices], s)
321+
#= Integer UnitRanges may return an appropriate AbstractUnitRange{<:Integer}, as the result may be used in indexing, and
322+
indexing is faster with ranges =#
323+
@propagate_inbounds Base.getindex(r::UnitRange{<:Integer}, s::IdOffsetRange) = IdOffsetRange(r[_unwrap(s)] .- s.offset, s.offset)
324+
@propagate_inbounds Base.getindex(r::UnitRange{<:Integer}, s::IIUR) = IdentityUnitRange(r[_unwrap(s)])
326325

327326
function Base.show(io::IO, r::OffsetRange)
328327
show(io, r.parent)

src/utils.jl

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,4 +70,7 @@ _checkindices(A::AbstractArray, indices, label) = _checkindices(ndims(A), indice
7070
function _checkindices(N::Integer, indices, label)
7171
throw_argumenterror(N, indices, label) = throw(ArgumentError(label*" $indices are not compatible with a $(N)D array"))
7272
N == length(indices) || throw_argumenterror(N, indices, label)
73-
end
73+
end
74+
75+
_unwrap(r::IdOffsetRange) = r.parent .+ r.offset
76+
_unwrap(r::IdentityUnitRange) = r.indices

test/runtests.jl

Lines changed: 35 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -110,27 +110,44 @@ end
110110
check_indexed_by(r3, 0:2)
111111

112112
@testset "Idempotent indexing" begin
113-
r = OffsetArrays.IdOffsetRange(3:5, -1)
114-
115-
# Indexing with IdentityUnitRange
116-
s = IdentityUnitRange(0:2)
117-
@test axes(r[s]) == axes(s)
118-
for i in eachindex(s)
119-
@test r[s[i]] == r[s][i]
120-
end
113+
@testset "Indexing into an IdOffsetRange" begin
114+
r = OffsetArrays.IdOffsetRange(3:5, -1)
115+
# Indexing with IdentityUnitRange
116+
s = IdentityUnitRange(0:2)
117+
@test axes(r[s]) == axes(s)
118+
for i in eachindex(s)
119+
@test r[s[i]] == r[s][i]
120+
end
121121

122-
# Indexing with IdOffsetRange
123-
s = OffsetArrays.IdOffsetRange(-4:-2, 4)
124-
@test axes(r[s]) == axes(s)
125-
for i in eachindex(s)
126-
@test r[s[i]] == r[s][i]
122+
# Indexing with IdOffsetRange
123+
s = OffsetArrays.IdOffsetRange(-4:-2, 4)
124+
@test axes(r[s]) == axes(s)
125+
for i in eachindex(s)
126+
@test r[s[i]] == r[s][i]
127+
end
128+
129+
# Indexing with UnitRange
130+
s = 0:2
131+
@test axes(r[s]) == axes(s)
132+
for i in eachindex(s)
133+
@test r[s[i]] == r[s][i]
134+
end
127135
end
136+
@testset "Indexing using an IdOffsetRange" begin
137+
r = OffsetArrays.IdOffsetRange(3:5, -1)
138+
# Indexing into an IdentityUnitRange
139+
s = IdentityUnitRange(-1:5)
140+
@test axes(s[r]) == axes(r)
141+
for i in eachindex(r)
142+
@test s[r[i]] == s[r][i]
143+
end
128144

129-
# Indexing with UnitRange
130-
s = 0:2
131-
@test axes(r[s]) == axes(s)
132-
for i in eachindex(s)
133-
@test r[s[i]] == r[s][i]
145+
# Indexing into an UnitRange
146+
s = -3:6
147+
@test axes(s[r]) == axes(r)
148+
for i in eachindex(r)
149+
@test s[r[i]] == s[r][i]
150+
end
134151
end
135152
end
136153

0 commit comments

Comments
 (0)