Skip to content

Commit 2b723be

Browse files
authored
Annotate indexing with propagate_inbounds (#78)
Also add a checkindex method to allow specialization for AxisArrays that wrap specialized structures (like Ranges or RangeArrays)
1 parent 6c9eed9 commit 2b723be

File tree

1 file changed

+23
-19
lines changed

1 file changed

+23
-19
lines changed

src/indexing.jl

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,16 @@
11
const Idx = Union{Real,Colon,AbstractArray{Int}}
22

3-
using Base: ViewIndex
3+
using Base: ViewIndex, @propagate_inbounds
44

55
# Defer IndexStyle to the wrapped array
66
@compat Base.IndexStyle{T,N,D,Ax}(::Type{AxisArray{T,N,D,Ax}}) = IndexStyle(D)
77

88
# Simple scalar indexing where we just set or return scalars
9-
@inline Base.getindex(A::AxisArray, idxs::Int...) = A.data[idxs...]
10-
@inline Base.setindex!(A::AxisArray, v, idxs::Int...) = (A.data[idxs...] = v)
9+
@propagate_inbounds Base.getindex(A::AxisArray, idxs::Int...) = A.data[idxs...]
10+
@propagate_inbounds Base.setindex!(A::AxisArray, v, idxs::Int...) = (A.data[idxs...] = v)
1111

1212
# Cartesian iteration
1313
Base.eachindex(A::AxisArray) = eachindex(A.data)
14-
Base.getindex(A::AxisArray, idx::Base.IteratorsMD.CartesianIndex) = A.data[idx]
15-
Base.setindex!(A::AxisArray, v, idx::Base.IteratorsMD.CartesianIndex) = (A.data[idx] = v)
1614

1715
@generated function reaxis(A::AxisArray, I::Idx...)
1816
N = length(I)
@@ -56,48 +54,48 @@ Base.setindex!(A::AxisArray, v, idx::Base.IteratorsMD.CartesianIndex) = (A.data[
5654
end
5755
end
5856

59-
@inline function Base.getindex(A::AxisArray, idxs::Idx...)
57+
@propagate_inbounds function Base.getindex(A::AxisArray, idxs::Idx...)
6058
AxisArray(A.data[idxs...], reaxis(A, idxs...))
6159
end
6260

6361
# To resolve ambiguities, we need several definitions
6462
if VERSION >= v"0.6.0-dev.672"
6563
using Base.AbstractCartesianIndex
66-
Base.view(A::AxisArray, idxs::Idx...) = AxisArray(view(A.data, idxs...), reaxis(A, idxs...))
64+
@propagate_inbounds Base.view(A::AxisArray, idxs::Idx...) = AxisArray(view(A.data, idxs...), reaxis(A, idxs...))
6765
else
68-
@inline function Base.view{T,N}(A::AxisArray{T,N}, idxs::Vararg{Idx,N})
66+
@propagate_inbounds function Base.view{T,N}(A::AxisArray{T,N}, idxs::Vararg{Idx,N})
6967
AxisArray(view(A.data, idxs...), reaxis(A, idxs...))
7068
end
71-
function Base.view(A::AxisArray, idx::Idx)
69+
@propagate_inbounds function Base.view(A::AxisArray, idx::Idx)
7270
AxisArray(view(A.data, idx), reaxis(A, idx))
7371
end
74-
@inline function Base.view{N}(A::AxisArray, idxs::Vararg{Idx,N})
72+
@propagate_inbounds function Base.view{N}(A::AxisArray, idxs::Vararg{Idx,N})
7573
# this should eventually be deleted, see julia #14770
7674
AxisArray(view(A.data, idxs...), reaxis(A, idxs...))
7775
end
7876
end
7977

8078
# Setindex is so much simpler. Just assign it to the data:
81-
@inline Base.setindex!(A::AxisArray, v, idxs::Idx...) = (A.data[idxs...] = v)
79+
@propagate_inbounds Base.setindex!(A::AxisArray, v, idxs::Idx...) = (A.data[idxs...] = v)
8280

8381
### Fancier indexing capabilities provided only by AxisArrays ###
84-
@inline Base.getindex(A::AxisArray, idxs...) = A[to_index(A,idxs...)...]
85-
@inline Base.setindex!(A::AxisArray, v, idxs...) = (A[to_index(A,idxs...)...] = v)
82+
@propagate_inbounds Base.getindex(A::AxisArray, idxs...) = A[to_index(A,idxs...)...]
83+
@propagate_inbounds Base.setindex!(A::AxisArray, v, idxs...) = (A[to_index(A,idxs...)...] = v)
8684
# Deal with lots of ambiguities here
8785
if VERSION >= v"0.6.0-dev.672"
88-
Base.view(A::AxisArray, idxs::ViewIndex...) = view(A, to_index(A,idxs...)...)
89-
Base.view(A::AxisArray, idxs::Union{ViewIndex,AbstractCartesianIndex}...) = view(A, to_index(A,Base.IteratorsMD.flatten(idxs)...)...)
90-
Base.view(A::AxisArray, idxs...) = view(A, to_index(A,idxs...)...)
86+
@propagate_inbounds Base.view(A::AxisArray, idxs::ViewIndex...) = view(A, to_index(A,idxs...)...)
87+
@propagate_inbounds Base.view(A::AxisArray, idxs::Union{ViewIndex,AbstractCartesianIndex}...) = view(A, to_index(A,Base.IteratorsMD.flatten(idxs)...)...)
88+
@propagate_inbounds Base.view(A::AxisArray, idxs...) = view(A, to_index(A,idxs...)...)
9189
else
9290
for T in (:ViewIndex, :Any)
9391
@eval begin
94-
@inline function Base.view{T,N}(A::AxisArray{T,N}, idxs::Vararg{$T,N})
92+
@propagate_inbounds function Base.view{T,N}(A::AxisArray{T,N}, idxs::Vararg{$T,N})
9593
view(A, to_index(A,idxs...)...)
9694
end
97-
function Base.view(A::AxisArray, idx::$T)
95+
@propagate_inbounds function Base.view(A::AxisArray, idx::$T)
9896
view(A, to_index(A,idx)...)
9997
end
100-
@inline function Base.view{N}(A::AxisArray, idsx::Vararg{$T,N})
98+
@propagate_inbounds function Base.view{N}(A::AxisArray, idsx::Vararg{$T,N})
10199
# this should eventually be deleted, see julia #14770
102100
view(A, to_index(A,idxs...)...)
103101
end
@@ -229,3 +227,9 @@ end
229227
@inline getaxis{Ax<:Axis}(::Type{Ax}, ax::Ax, axs...) = ax
230228
@inline getaxis{Ax<:Axis}(::Type{Ax}, ax::Axis, axs...) = getaxis(Ax, axs...)
231229
@noinline getaxis{Ax<:Axis}(::Type{Ax}) = throw(ArgumentError("no axis of type $Ax was found"))
230+
231+
# Boundschecking specialization: defer to the data array.
232+
# Note that we could unwrap AxisArrays when they are used as indices into other
233+
# arrays within Base's to_index/to_indices methods, but that requires a bigger
234+
# refactor to merge our to_index method with Base's.
235+
@inline Base.checkindex(::Type{Bool}, inds::AbstractUnitRange, A::AxisArray) = Base.checkindex(Bool, inds, A.data)

0 commit comments

Comments
 (0)