diff --git a/base/array.jl b/base/array.jl index fcaa3009a2c9e6..b8a53046702730 100644 --- a/base/array.jl +++ b/base/array.jl @@ -241,21 +241,25 @@ collect(itr) = collect(eltype(itr), itr) ## Indexing: getindex ## -getindex(a::Array) = arrayref(a,1) - -getindex(A::Array, i0::Real) = arrayref(A,to_index(i0)) -getindex(A::Array, i0::Real, i1::Real) = arrayref(A,to_index(i0),to_index(i1)) -getindex(A::Array, i0::Real, i1::Real, i2::Real) = - arrayref(A,to_index(i0),to_index(i1),to_index(i2)) -getindex(A::Array, i0::Real, i1::Real, i2::Real, i3::Real) = - arrayref(A,to_index(i0),to_index(i1),to_index(i2),to_index(i3)) -getindex(A::Array, i0::Real, i1::Real, i2::Real, i3::Real, i4::Real) = - arrayref(A,to_index(i0),to_index(i1),to_index(i2),to_index(i3),to_index(i4)) -getindex(A::Array, i0::Real, i1::Real, i2::Real, i3::Real, i4::Real, i5::Real) = - arrayref(A,to_index(i0),to_index(i1),to_index(i2),to_index(i3),to_index(i4),to_index(i5)) - -getindex(A::Array, i0::Real, i1::Real, i2::Real, i3::Real, i4::Real, i5::Real, I::Real...) = - arrayref(A,to_index(i0),to_index(i1),to_index(i2),to_index(i3),to_index(i4),to_index(i5),to_index(I)...) +for (getindexfn, transform) in ((:getindex, x->x), (:unsafe_getindex, x->:(@boundscheck false return $x))) + @eval begin + $getindexfn(a::Array) = $(transform(:(arrayref(a,1)))) + + $getindexfn(A::Array, i0::Real) = $(transform(:(arrayref(A,to_index(i0))))) + $getindexfn(A::Array, i0::Real, i1::Real) = $(transform(:(arrayref(A,to_index(i0),to_index(i1))))) + $getindexfn(A::Array, i0::Real, i1::Real, i2::Real) = + $(transform(:(arrayref(A,to_index(i0),to_index(i1),to_index(i2))))) + $getindexfn(A::Array, i0::Real, i1::Real, i2::Real, i3::Real) = + $(transform(:(arrayref(A,to_index(i0),to_index(i1),to_index(i2),to_index(i3))))) + $getindexfn(A::Array, i0::Real, i1::Real, i2::Real, i3::Real, i4::Real) = + $(transform(:(arrayref(A,to_index(i0),to_index(i1),to_index(i2),to_index(i3),to_index(i4))))) + $getindexfn(A::Array, i0::Real, i1::Real, i2::Real, i3::Real, i4::Real, i5::Real) = + $(transform(:(arrayref(A,to_index(i0),to_index(i1),to_index(i2),to_index(i3),to_index(i4),to_index(i5))))) + + $getindexfn(A::Array, i0::Real, i1::Real, i2::Real, i3::Real, i4::Real, i5::Real, I::Real...) = + $(transform(:(arrayref(A,to_index(i0),to_index(i1),to_index(i2),to_index(i3),to_index(i4),to_index(i5),to_index(I)...)))) + end +end # Fast copy using copy! for UnitRange function getindex(A::Array, I::UnitRange{Int}) @@ -278,6 +282,8 @@ function getindex(A::Range, I::AbstractVector{Bool}) return [ A[i] for i in to_index(I) ] end +unsafe_getindex(args...) = getindex(args...) + # logical indexing @@ -302,21 +308,26 @@ getindex(A::Array, I::AbstractArray{Bool}) = getindex_bool_1d(A, I) ## Indexing: setindex! ## -setindex!{T}(A::Array{T}, x) = arrayset(A, convert(T,x), 1) - -setindex!{T}(A::Array{T}, x, i0::Real) = arrayset(A, convert(T,x), to_index(i0)) -setindex!{T}(A::Array{T}, x, i0::Real, i1::Real) = - arrayset(A, convert(T,x), to_index(i0), to_index(i1)) -setindex!{T}(A::Array{T}, x, i0::Real, i1::Real, i2::Real) = - arrayset(A, convert(T,x), to_index(i0), to_index(i1), to_index(i2)) -setindex!{T}(A::Array{T}, x, i0::Real, i1::Real, i2::Real, i3::Real) = - arrayset(A, convert(T,x), to_index(i0), to_index(i1), to_index(i2), to_index(i3)) -setindex!{T}(A::Array{T}, x, i0::Real, i1::Real, i2::Real, i3::Real, i4::Real) = - arrayset(A, convert(T,x), to_index(i0), to_index(i1), to_index(i2), to_index(i3), to_index(i4)) -setindex!{T}(A::Array{T}, x, i0::Real, i1::Real, i2::Real, i3::Real, i4::Real, i5::Real) = - arrayset(A, convert(T,x), to_index(i0), to_index(i1), to_index(i2), to_index(i3), to_index(i4), to_index(i5)) -setindex!{T}(A::Array{T}, x, i0::Real, i1::Real, i2::Real, i3::Real, i4::Real, i5::Real, I::Real...) = - arrayset(A, convert(T,x), to_index(i0), to_index(i1), to_index(i2), to_index(i3), to_index(i4), to_index(i5), to_index(I)...) + +for (setindexfn, transform) in ((:setindex!, x->x), (:unsafe_setindex!, x->:(@boundscheck false return $x))) + @eval begin + $setindexfn{T}(A::Array{T}, x) = $(transform(:(arrayset(A, convert(T,x), 1)))) + + $setindexfn{T}(A::Array{T}, x, i0::Real) = $(transform(:(arrayset(A, convert(T,x), to_index(i0))))) + $setindexfn{T}(A::Array{T}, x, i0::Real, i1::Real) = + $(transform(:(arrayset(A, convert(T,x), to_index(i0), to_index(i1))))) + $setindexfn{T}(A::Array{T}, x, i0::Real, i1::Real, i2::Real) = + $(transform(:(arrayset(A, convert(T,x), to_index(i0), to_index(i1), to_index(i2))))) + $setindexfn{T}(A::Array{T}, x, i0::Real, i1::Real, i2::Real, i3::Real) = + $(transform(:(arrayset(A, convert(T,x), to_index(i0), to_index(i1), to_index(i2), to_index(i3))))) + $setindexfn{T}(A::Array{T}, x, i0::Real, i1::Real, i2::Real, i3::Real, i4::Real) = + $(transform(:(arrayset(A, convert(T,x), to_index(i0), to_index(i1), to_index(i2), to_index(i3), to_index(i4))))) + $setindexfn{T}(A::Array{T}, x, i0::Real, i1::Real, i2::Real, i3::Real, i4::Real, i5::Real) = + $(transform(:(arrayset(A, convert(T,x), to_index(i0), to_index(i1), to_index(i2), to_index(i3), to_index(i4), to_index(i5))))) + $setindexfn{T}(A::Array{T}, x, i0::Real, i1::Real, i2::Real, i3::Real, i4::Real, i5::Real, I::Real...) = + $(transform(:(arrayset(A, convert(T,x), to_index(i0), to_index(i1), to_index(i2), to_index(i3), to_index(i4), to_index(i5), to_index(I)...)))) + end +end function setindex!{T<:Real}(A::Array, x, I::AbstractVector{T}) for i in I @@ -348,6 +359,7 @@ function setindex!{T<:Real}(A::Array, X::AbstractArray, I::AbstractVector{T}) return A end +unsafe_setindex!(args...) = setindex!(args...) # logical indexing diff --git a/base/base.jl b/base/base.jl index 05b8c2a9e20ed5..550f45cd67c45c 100644 --- a/base/base.jl +++ b/base/base.jl @@ -206,8 +206,118 @@ macro boundscheck(yesno,blk) $(Expr(:boundscheck,:pop))) end -macro inbounds(blk) - :(@boundscheck false $(esc(blk))) + +expand_end!(var, dim::Int, sym::Symbol) = + sym === :end ? (:(size($var, $dim))) : sym +function expand_end!(var, dim::Int, ast::Expr) + if ast.head === :ref + expand_ref!(ast) + else + args = ast.args + for i = 1:arraylen(args) + arrayset(args, expand_end!(var, dim, arrayref(ast.args, i)), i) + end + end + ast +end +expand_end!(::Any, ::Int, x) = x + +function expand_ref!(ast::Expr) + args = ast.args + var = arrayref(args, 1) + for i = 2:arraylen(args) + arg = arrayref(args, i) + arrayset(args, arg === :(:) ? :(1:size($var, $(i-1))) : expand_end!(var, i-1, arg), i) + end +end + +function rewrite_ref(getindexfn, setindexfn, ast::Expr) + head = ast.head + if head === :ref + expand_ref!(ast) + out = Expr(:call) + out.args = Array(Any, arraylen(ast.args)+1) + arrayset(out.args, getindexfn, 1) + for i = 1:arraylen(ast.args) + arrayset(out.args, arrayref(ast.args, i), i+1) + end + out + elseif head === :(=) && isa(arrayref(ast.args, 1), Expr) + lhs = arrayref(ast.args, 1) + rhs = arrayref(ast.args, 2) + if isa(lhs, Expr) && (lhs.head === :tuple || lhs.head === :ref) + if lhs.head === :tuple + out = Expr(:block) + if isa(rhs, Expr) && rhs.head === :tuple && arraylen(rhs.args) == arraylen(lhs.args) + n = arraylen(lhs.args) + out.args = Array(Any, 2*n) + for i = 1:n + x = gensym() + arrayset(out.args, :($x = $(rewrite_ref(getindexfn, setindexfn, arrayref(rhs.args, i)))), i) + arrayset(out.args, rewrite_ref(getindexfn, setindexfn, :($(arrayref(lhs.args, i)) = $x)), n+i) + end + else + out.args = Array(Any, arraylen(lhs.args)+1) + rhsval = gensym() + stateval = gensym() + arrayset(out.args, quote + $rhsval = $(rewrite_ref(getindexfn, setindexfn, rhs)) + $stateval = $start($rhsval) + end, 1) + for i = 1:arraylen(lhs.args) + nextval = gensym() + arrayset(out.args, quote + $nextval = $indexed_next($rhsval, $i, $stateval) + $(rewrite_ref(getindexfn, setindexfn, + :($(arrayref(lhs.args, i)) = $tupleref($nextval, 1)))) + $stateval = $tupleref($nextval, 2) + end, i+1) + end + end + else + expand_ref!(lhs) + out = Expr(:call) + out.args = Array(Any, arraylen(lhs.args)+2) + arrayset(out.args, setindexfn, 1) + arrayset(out.args, arrayref(lhs.args, 1), 2) + arrayset(out.args, rewrite_ref(getindexfn, setindexfn, rhs), 3) + for i = 2:arraylen(lhs.args) + arrayset(out.args, rewrite_ref(getindexfn, setindexfn, arrayref(lhs.args, i)), i+2) + end + end + out + else + :($lhs = $(rewrite_ref(getindexfn, setindexfn, rhs))) + end + elseif (head === :(+=) || head === :(-=) || head === :(*=) || + head === :(.*=) || head === :(/=) || head === :(./=) || head === :(//=) || + head === :(.//=) || head === :(\=) || head === :(.\=) || head === :(.+=) || + head === :(.-=) || head === :(^=) || head === :(.^=) || head === :(%=) || + head === :(.%=) || head === :(|=) || head === :(&=) || head === :($=) || + head === :(<<=) || head === :(>>=) || head === :(>>>=)) && + isa(arrayref(ast.args, 1), Expr) + lhs = arrayref(ast.args, 1) + rhs = arrayref(ast.args, 2) + nonupdating_sym = head === :+= ? (:+) : head === :-= ? (:-) : head === :*= ? (:*) : + head === :.*= ? (:.*) : head === :/= ? (:/) : head === :./= ? (:./) : + head === ://= ? (://) : head === :.//= ? (:.//) : head === :\= ? (:\) : + head === :.\= ? (:.\) : head === :.+= ? (:.+) : head === :.-= ? (:.-) : + head === :^= ? (:^) : head === :.^= ? (:.^) : head === :%= ? (:%) : + head === :.%= ? (:.%) : head === :|= ? (:|) : head === :&= ? (:&) : + head === :$= ? (:$) : head === :<<= ? (:<<) : head === :>>= ? (:>>) : (:>>>) + out = :($lhs = $nonupdating_sym($lhs, $rhs)) + rewrite_ref(getindexfn, setindexfn, out) + else + for i = 1:arraylen(ast.args) + arrayset(ast.args, rewrite_ref(getindexfn, setindexfn, arrayref(ast.args, i)), i) + end + ast + end +end +rewrite_ref(getindexfn, setindexfn, ast) = ast + +macro inbounds(ex) + esc(rewrite_ref(:(Base.unsafe_getindex), :(Base.unsafe_setindex!), ex)) end macro label(name::Symbol) diff --git a/base/bitarray.jl b/base/bitarray.jl index 0c5dfbf6e6198c..de82077a077796 100644 --- a/base/bitarray.jl +++ b/base/bitarray.jl @@ -342,8 +342,9 @@ end ## Indexing: getindex ## function unsafe_bitgetindex(Bc::Vector{Uint64}, i::Int) - return (Bc[@_div64(i-1)+1] & (uint64(1)<<@_mod64(i-1))) != 0 + return @inbounds (Bc[@_div64(i-1)+1] & (uint64(1)<<@_mod64(i-1))) != 0 end +unsafe_getindex(v::BitArray, ind::Int) = Base.unsafe_bitgetindex(v.chunks, ind) function getindex(B::BitArray, i::Int) 1 <= i <= length(B) || throw(BoundsError()) @@ -408,6 +409,7 @@ function unsafe_bitsetindex!(Bc::Array{Uint64}, x::Bool, i::Int) end end end +unsafe_setindex!(v::BitArray, x::Bool, ind::Int) = (Base.unsafe_bitsetindex!(v.chunks, x, ind); v) setindex!(B::BitArray, x) = setindex!(B, convert(Bool,x), 1) diff --git a/base/multidimensional.jl b/base/multidimensional.jl index c25e3984a31fe9..d99b56899ed9e8 100644 --- a/base/multidimensional.jl +++ b/base/multidimensional.jl @@ -5,16 +5,6 @@ nothing end -unsafe_getindex(v::Real, ind::Int) = v -unsafe_getindex(v::Range, ind::Int) = first(v) + (ind-1)*step(v) -unsafe_getindex(v::BitArray, ind::Int) = Base.unsafe_bitgetindex(v.chunks, ind) -unsafe_getindex(v::AbstractArray, ind::Int) = v[ind] -unsafe_getindex(v, ind::Real) = unsafe_getindex(v, to_index(ind)) - -unsafe_setindex!{T}(v::AbstractArray{T}, x::T, ind::Int) = (v[ind] = x; v) -unsafe_setindex!(v::BitArray, x::Bool, ind::Int) = (Base.unsafe_bitsetindex!(v.chunks, x, ind); v) -unsafe_setindex!{T}(v::AbstractArray{T}, x::T, ind::Real) = unsafe_setindex!(v, x, to_index(ind)) - # Version that uses cartesian indexing for src @ngenerate N typeof(dest) function _getindex!(dest::Array, src::AbstractArray, I::NTuple{N,Union(Int,AbstractVector)}...) checksize(dest, I...) diff --git a/base/range.jl b/base/range.jl index fdfd451b45a14e..562adb9705152b 100644 --- a/base/range.jl +++ b/base/range.jl @@ -509,7 +509,7 @@ function vcat{T}(r::Range{T}) a = Array(T,n) i = 1 for x in r - @inbounds a[i] = x + @boundscheck false a[i] = x i += 1 end return a @@ -523,7 +523,7 @@ function vcat{T}(rs::Range{T}...) i = 1 for r in rs for x in r - @inbounds a[i] = x + @boundscheck false a[i] = x i += 1 end end