Skip to content

Commit

Permalink
Restore old SubArray bounds check semantics
Browse files Browse the repository at this point in the history
That is, don't check bounds and instead let the parent array do the bounds checking.  Due to the abstract fallbacks, it's still advantageous to define both `getindex` and `unsafe_getindex`.  It'd be nice to use metaprogramming here to loop over the two names and define both at once, but it seems like `subarray.jl` lives too early in the bootstrap for the required machinery.
  • Loading branch information
mbauman committed Jun 10, 2015
1 parent c7e2b33 commit c83ba47
Showing 1 changed file with 40 additions and 2 deletions.
42 changes: 40 additions & 2 deletions base/subarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -527,7 +527,30 @@ function parentdims(s::SubArray)
end

## Scalar indexing
getindex(V::SubArray, I::Int...) = (@_inline_meta; checkbounds(V, I...); unsafe_getindex(V, I...))

# While it'd be nice to explicitly check bounds against the SubArray dimensions,
# the lack of an extensible @inbounds mechanism makes it difficult for users to
# avoid the cost of the bounds check without rewriting their syntax to use the
# unwieldy unsafe_getindex/unsafe_setindex! function calls. So instead we define
# getindex to rely upon the bounds checks in the parent array. It's still
# advantageous to define the unsafe_ variants without any bounds checks since
# the abstract indexing fallbacks can make use of them.
@generated function getindex{T,N,P,IV,LD}(V::SubArray{T,N,P,IV,LD}, I::Int...)
ni = length(I)
if ni == 1 && length(IV.parameters) == LD # linear indexing
meta = Expr(:meta, :inline)
if iscontiguous(V)
return :($meta; getindex(V.parent, V.first_index + I[1] - 1))
end
return :($meta; getindex(V.parent, V.first_index + V.stride1*(I[1]-1)))
end
Isyms = [:(I[$d]) for d = 1:ni]
exhead, idxs = index_generate(ndims(P), IV, :V, Isyms)
quote
$exhead
getindex(V.parent, $(idxs...))
end
end
@generated function unsafe_getindex{T,N,P,IV,LD}(V::SubArray{T,N,P,IV,LD}, I::Int...)
ni = length(I)
if ni == 1 && length(IV.parameters) == LD # linear indexing
Expand All @@ -544,7 +567,22 @@ getindex(V::SubArray, I::Int...) = (@_inline_meta; checkbounds(V, I...); unsafe_
unsafe_getindex(V.parent, $(idxs...))
end
end
setindex!(V::SubArray, v, I::Int...) = (@_inline_meta; checkbounds(V, I...); unsafe_setindex!(V, v, I...))
@generated function setindex!{T,N,P,IV,LD}(V::SubArray{T,N,P,IV,LD}, v, I::Int...)
ni = length(I)
if ni == 1 && length(IV.parameters) == LD # linear indexing
meta = Expr(:meta, :inline)
if iscontiguous(V)
return :($meta; setindex!(V.parent, v, V.first_index + I[1] - 1))
end
return :($meta; setindex!(V.parent, v, V.first_index + V.stride1*(I[1]-1)))
end
Isyms = [:(I[$d]) for d = 1:ni]
exhead, idxs = index_generate(ndims(P), IV, :V, Isyms)
quote
$exhead
setindex!(V.parent, v, $(idxs...))
end
end
@generated function unsafe_setindex!{T,N,P,IV,LD}(V::SubArray{T,N,P,IV,LD}, v, I::Int...)
ni = length(I)
if ni == 1 && length(IV.parameters) == LD # linear indexing
Expand Down

0 comments on commit c83ba47

Please sign in to comment.