Skip to content

Commit

Permalink
Update for 0.5 inbounds
Browse files Browse the repository at this point in the history
* Take advantage of the 0.5 user-extensible boundschecking mechanism
* Add O(n) checkindex specialization when RangeArrays are used as indices (instead of the O(m*n) base implementation)
* Precompile
  • Loading branch information
mbauman committed Apr 24, 2017
1 parent b0ee8f1 commit 84f34a4
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 13 deletions.
2 changes: 1 addition & 1 deletion REQUIRE
@@ -1,2 +1,2 @@
julia 0.4
julia 0.5
Compat 0.19
1 change: 1 addition & 0 deletions src/RangeArrays.jl
@@ -1,3 +1,4 @@
__precompile__()
module RangeArrays

using Compat
Expand Down
27 changes: 21 additions & 6 deletions src/matrix.jl
Expand Up @@ -27,12 +27,27 @@ Base.size(R::RangeMatrix) = R.dims
@compat Base.IndexStyle(::Type{<:RangeMatrix}) = IndexCartesian()

# Scalar indexing
Base.getindex(R::RangeMatrix, i::Int, j::Int) = (checkbounds(R, i, j); Base.unsafe_getindex(R, i, j))
Base.unsafe_getindex(R::RangeMatrix, i::Int, j::Int) = @inbounds return R.rs[j][i]
@inline function Base.getindex(R::RangeMatrix, i::Int, j::Int)
@boundscheck checkbounds(R, i, j);
@inbounds return R.rs[j][i]
end

# For non-scalar indexing, only specialize with inner Ranges and Colons to
# return Ranges or RangeMatrixes. For everything else, we can use the fallbacks.
Base.getindex(R::RangeMatrix, I::Union{Range, Colon}, J) = (checkbounds(R, I, J); Base.unsafe_getindex(R, I, J))
Base.unsafe_getindex(R::RangeMatrix, I::Union{Range, Colon}, j::Real) = @inbounds return R.rs[j][I]
Base.unsafe_getindex(R::RangeMatrix, I::Union{Range, Colon}, ::Colon) = @inbounds return RangeMatrix([R.rs[j][I] for j=1:length(R.rs)])
Base.unsafe_getindex(R::RangeMatrix, I::Union{Range, Colon}, J) = @inbounds return RangeMatrix([R.rs[j][I] for j in J])
@inline function Base.getindex(R::RangeMatrix, I::Union{Range, Colon}, J)
@boundscheck checkbounds(R, I, J)
unsafe_getindex(R, I, J)
end
@inline unsafe_getindex(R::RangeMatrix, I::Union{Range, Colon}, j::Real) = @inbounds return R.rs[j][I]
@inline unsafe_getindex(R::RangeMatrix, I::Union{Range, Colon}, ::Colon) = @inbounds return RangeMatrix([R.rs[j][I] for j=1:length(R.rs)])
@inline unsafe_getindex(R::RangeMatrix, I::Union{Range, Colon}, J) = @inbounds return RangeMatrix([R.rs[j][I] for j in J])

# We can also optimize bounds checks to only look at each range's endpoints
function Base.checkindex(::Type{Bool}, inds::AbstractUnitRange, R::RangeMatrix)
b = true
@inbounds for r in R.rs
b &= checkindex(Bool, inds, r[1])
b &= checkindex(Bool, inds, r[end])
end
b
end
28 changes: 22 additions & 6 deletions src/repeatedrange.jl
Expand Up @@ -15,12 +15,28 @@ Base.size(R::RepeatedRangeMatrix) = (length(R.r), length(R.at))
@compat Base.IndexStyle(::Type{<:RepeatedRangeMatrix}) = IndexCartesian()

# Scalar indexing
Base.getindex(R::RepeatedRangeMatrix, i::Int, j::Int) = (checkbounds(R, i, j); Base.unsafe_getindex(R, i, j))
Base.unsafe_getindex(R::RepeatedRangeMatrix, i::Int, j::Int) = @inbounds return R.r[i] + R.at[j]
@inline function Base.getindex(R::RepeatedRangeMatrix, i::Int, j::Int)
@boundscheck checkbounds(R, i, j)
@inbounds return R.r[i] + R.at[j]
end

# For non-scalar indexing, only specialize with inner Ranges and Colons to
# return Ranges or RangeMatrixes. For everything else, we can use the fallbacks.
Base.getindex(R::RepeatedRangeMatrix, I::Union{Range, Colon}, J) = (checkbounds(R, I, J); Base.unsafe_getindex(R, I, J))
Base.unsafe_getindex(R::RepeatedRangeMatrix, I::Union{Range, Colon}, j::Real) = @inbounds return R.r[I] + R.at[j]
Base.unsafe_getindex(R::RepeatedRangeMatrix, I::Union{Range, Colon}, ::Colon) = @inbounds return RepeatedRangeMatrix(R.r[I], R.at[:])
Base.unsafe_getindex(R::RepeatedRangeMatrix, I::Union{Range, Colon}, J) = @inbounds return RepeatedRangeMatrix(R.r[I], R.at[J])
@inline function Base.getindex(R::RepeatedRangeMatrix, I::Union{Range, Colon}, j::Real)
@boundscheck checkbounds(R, I, j)
@inbounds return R.r[I] + R.at[j]
end
@inline function Base.getindex(R::RepeatedRangeMatrix, I::Union{Range, Colon}, J)
@boundscheck checkbounds(R, I, J)
@inbounds return RepeatedRangeMatrix(R.r[I], R.at[J])
end

# We can also optimize bounds checks to only look at the range's endpoints
function Base.checkindex(::Type{Bool}, inds::AbstractUnitRange, R::RepeatedRangeMatrix)
b = true
@inbounds for a in R.at
b &= checkindex(Bool, inds, R.r[1] + a)
b &= checkindex(Bool, inds, R.r[end] + a)
end
b
end

0 comments on commit 84f34a4

Please sign in to comment.