From 84f34a4bfd10338afc752e8def17607c0632837c Mon Sep 17 00:00:00 2001 From: Matt Bauman Date: Mon, 24 Apr 2017 03:17:07 -0500 Subject: [PATCH] Update for 0.5 inbounds * 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 --- REQUIRE | 2 +- src/RangeArrays.jl | 1 + src/matrix.jl | 27 +++++++++++++++++++++------ src/repeatedrange.jl | 28 ++++++++++++++++++++++------ 4 files changed, 45 insertions(+), 13 deletions(-) diff --git a/REQUIRE b/REQUIRE index 33ed633..9350d91 100644 --- a/REQUIRE +++ b/REQUIRE @@ -1,2 +1,2 @@ -julia 0.4 +julia 0.5 Compat 0.19 diff --git a/src/RangeArrays.jl b/src/RangeArrays.jl index c122bb0..a889a19 100644 --- a/src/RangeArrays.jl +++ b/src/RangeArrays.jl @@ -1,3 +1,4 @@ +__precompile__() module RangeArrays using Compat diff --git a/src/matrix.jl b/src/matrix.jl index 335fb10..a9cf789 100644 --- a/src/matrix.jl +++ b/src/matrix.jl @@ -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 diff --git a/src/repeatedrange.jl b/src/repeatedrange.jl index 9a45617..c83020b 100644 --- a/src/repeatedrange.jl +++ b/src/repeatedrange.jl @@ -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