From 1af945821b0dd730ab57bcdeca0d5645dba15f70 Mon Sep 17 00:00:00 2001 From: Jutho Haegeman Date: Mon, 20 Apr 2015 23:03:47 +0200 Subject: [PATCH 1/2] ind2sub / sub2ind redesign --- base/abstractarray.jl | 155 ++++++++++++++++-------------------------- base/deprecated.jl | 3 + 2 files changed, 61 insertions(+), 97 deletions(-) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index dccc6c27fa6ad..b41286c57ec59 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -1007,97 +1007,66 @@ function repmat(a::AbstractVector, m::Int) return b end -sub2ind(dims) = 1 -sub2ind(dims, i::Integer) = Int(i) -sub2ind(dims, i::Integer, j::Integer) = sub2ind(dims, Int(i), Int(j)) -sub2ind(dims, i::Int, j::Int) = (j-1)*dims[1] + i -sub2ind(dims, i0::Integer, i1::Integer, i2::Integer) = sub2ind(dims, Int(i0),Int(i1),Int(i2)) -sub2ind(dims, i0::Int, i1::Int, i2::Int) = - i0 + dims[1]*((i1-1) + dims[2]*(i2-1)) -sub2ind(dims, i0::Integer, i1::Integer, i2::Integer, i3::Integer) = - sub2ind(dims, Int(i0),Int(i1),Int(i2),Int(i3)) -sub2ind(dims, i0::Int, i1::Int, i2::Int, i3::Int) = - i0 + dims[1]*((i1-1) + dims[2]*((i2-1) + dims[3]*(i3-1))) - -function sub2ind(dims, I::Integer...) - ndims = length(dims) - index = Int(I[1]) - stride = 1 - for k=2:ndims - stride = stride * dims[k-1] - index += (Int(I[k])-1) * stride - end - return index -end - -function sub2ind{T<:Integer}(dims::Array{T}, sub::Array{T}) - ndims = length(dims) - ind = sub[1] - stride = 1 - for k in 2:ndims - stride = stride * dims[k - 1] - ind += (sub[k] - 1) * stride - end - return ind -end - -sub2ind{T<:Integer}(dims, I::AbstractVector{T}...) = - [ sub2ind(dims, map(X->X[i], I)...)::Int for i=1:length(I[1]) ] - -function ind2sub(dims::Tuple{Integer,Vararg{Integer}}, ind::Int) - ndims = length(dims) - stride = dims[1] - for i=2:ndims-1 - stride *= dims[i] - end - - sub = () - for i=(ndims-1):-1:1 - rest = rem(ind-1, stride) + 1 - sub = tuple(div(ind - rest, stride) + 1, sub...) - ind = rest - stride = div(stride, dims[i]) - end - return tuple(ind, sub...) -end +sub2ind(dims::Tuple{}) = 1 +sub2ind(dims::Tuple{},I::Integer...) = sum(I) - length(I) + 1 +sub2ind(dims::Tuple{Integer,Vararg{Integer}}, i1::Integer) = i1 +sub2ind(dims::Tuple{Integer,Vararg{Integer}}, i1::Integer, I::Integer...) = i1 + dims[1]*(sub2ind(tail(dims),I...)-1) -ind2sub(dims::Tuple{Vararg{Integer}}, ind::Integer) = ind2sub(dims, Int(ind)) ind2sub(dims::Tuple{}, ind::Integer) = ind==1 ? () : throw(BoundsError()) -ind2sub(dims::Tuple{Integer,}, ind::Int) = (ind,) -ind2sub(dims::Tuple{Integer,Integer}, ind::Int) = - (rem(ind-1,dims[1])+1, div(ind-1,dims[1])+1) -ind2sub(dims::Tuple{Integer,Integer,Integer}, ind::Int) = - (rem(ind-1,dims[1])+1, div(rem(ind-1,dims[1]*dims[2]), dims[1])+1, - div(rem(ind-1,dims[1]*dims[2]*dims[3]), dims[1]*dims[2])+1) -ind2sub(a::AbstractArray, ind::Integer) = ind2sub(size(a), Int(ind)) - -function ind2sub{T<:Integer}(dims::Tuple{Integer,Vararg{Integer}}, ind::AbstractVector{T}) - n = length(dims) - l = length(ind) - t = ntuple(n, x->Array(Int, l)) - for i = 1:l - s = ind2sub(dims, ind[i]) - for j = 1:n - t[j][i] = s[j] +ind2sub(dims::Tuple{Integer}, ind::Integer) = (ind,) +function ind2sub(dims::Tuple{Integer,Vararg{Integer}}, ind::Integer) + @_inline_meta() + ind2 = div(ind-1,dims[1])+1 + tuple(ind-dims[1]*(ind2-1), ind2sub(tail(dims),ind2)...) +end + +# TODO in v0.5: either deprecate line 1 or add line 2 +ind2sub(a::AbstractArray, ind::Integer) = ind2sub(size(a), ind) +# sub2ind(a::AbstractArray, I::Integer...) = sub2ind(size(a), I...) + +function sub2ind{T<:Integer}(dims::Tuple{Vararg{Integer}}, I::AbstractVector{T}...) + N = length(dims) + M = length(I[1]) + indices = Array{T}(length(I[1])) + copy!(indices,I[1]) + + s = dims[1] + for j=2:length(I) + Ij = I[j] + for i=1:M + indices[i] += s*(Ij[i]-1) + end + s*= (j <= N ? dims[j] : 1) + end + return indices +end + +function ind2sub{N,T<:Integer}(dims::NTuple{N,Integer}, ind::AbstractVector{T}) + M = length(ind) + t = NTuple{N,Vector{T}}(ntuple(N,n->Array{T}(M))) + copy!(t[1],ind) + for j = 1:N-1 + d = dims[j] + tj = t[j] + tj2 = t[j+1] + for i = 1:M + ind2 = div(tj[i]-1, d) + tj[i] -= d*ind2 + tj2[i] = ind2+1 end end return t end -function ind2sub!{T<:Integer}(sub::Array{T}, dims::Array{T}, ind::T) +function ind2sub!{T<:Integer}(sub::Array{T}, dims::Tuple{Vararg{T}}, ind::T) ndims = length(dims) - stride = dims[1] - for i in 2:(ndims - 1) - stride *= dims[i] - end - for i in (ndims - 1):-1:1 - rest = rem1(ind, stride) - sub[i + 1] = div(ind - rest, stride) + 1 - ind = rest - stride = div(stride, dims[i]) + for i=1:ndims-1 + ind2 = div(ind-1,dims[i])+1 + sub[i] = ind - dims[i]*(ind2-1) + ind = ind2 end - sub[1] = ind - return + sub[ndims] = ind + return sub end # Generalized repmat @@ -1113,26 +1082,18 @@ function repeat{T}(A::Array{T}; throw(ArgumentError("inner/outer repetitions must be set for all input dimensions")) end - size_in = Array(Int, ndims_in) - size_out = Array(Int, ndims_out) - inner_size_out = Array(Int, ndims_out) + inner = vcat(inner, ones(Int,ndims_out-length_inner)) + outer = vcat(outer, ones(Int,ndims_out-length_outer)) - for i in 1:ndims_in - size_in[i] = size(A, i) - end - for i in 1:ndims_out - t1 = ndims_in < i ? 1 : size_in[i] - t2 = length_inner < i ? 1 : inner[i] - t3 = length_outer < i ? 1 : outer[i] - size_out[i] = t1 * t2 * t3 - inner_size_out[i] = t1 * t2 - end + size_in = size(A) + size_out = ntuple(i->inner[i]*size(A,i)*outer[i],ndims_out)::Dims + inner_size_out = ntuple(i->inner[i]*size(A,i),ndims_out)::Dims indices_in = Array(Int, ndims_in) indices_out = Array(Int, ndims_out) length_out = prod(size_out) - R = Array(T, size_out...) + R = Array(T, size_out) for index_out in 1:length_out ind2sub!(indices_out, size_out, index_out) @@ -1144,7 +1105,7 @@ function repeat{T}(A::Array{T}; indices_in[t] = fld1(indices_in[t], inner[t]) end end - index_in = sub2ind(size_in, indices_in) + index_in = sub2ind(size_in, indices_in...) R[index_out] = A[index_in] end diff --git a/base/deprecated.jl b/base/deprecated.jl index 1c7d15b2e2451..fc87f8d920fcf 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -319,6 +319,9 @@ end @deprecate flipud(A::AbstractArray) flipdim(A, 1) @deprecate fliplr(A::AbstractArray) flipdim(A, 2) +@deprecate sub2ind{T<:Integer}(dims::Array{T}, sub::Array{T}) sub2ind(tuple(dims...), sub...) +@deprecate ind2sub!{T<:Integer}(sub::Array{T}, dims::Array{T}, ind::T) ind2sub!(sub, tuple(dims...), ind) + @deprecate strftime Libc.strftime @deprecate strptime Libc.strptime @deprecate flush_cstdio Libc.flush_cstdio From 8c718f1498e44adcd83931a57d5d299f79e333ab Mon Sep 17 00:00:00 2001 From: Jutho Haegeman Date: Thu, 30 Apr 2015 14:41:54 +0200 Subject: [PATCH 2/2] generated ind2sub / sub2ind definitions --- base/abstractarray.jl | 37 ++++++++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index b41286c57ec59..bf65b5378fa90 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -1007,17 +1007,32 @@ function repmat(a::AbstractVector, m::Int) return b end -sub2ind(dims::Tuple{}) = 1 -sub2ind(dims::Tuple{},I::Integer...) = sum(I) - length(I) + 1 -sub2ind(dims::Tuple{Integer,Vararg{Integer}}, i1::Integer) = i1 -sub2ind(dims::Tuple{Integer,Vararg{Integer}}, i1::Integer, I::Integer...) = i1 + dims[1]*(sub2ind(tail(dims),I...)-1) - -ind2sub(dims::Tuple{}, ind::Integer) = ind==1 ? () : throw(BoundsError()) -ind2sub(dims::Tuple{Integer}, ind::Integer) = (ind,) -function ind2sub(dims::Tuple{Integer,Vararg{Integer}}, ind::Integer) - @_inline_meta() - ind2 = div(ind-1,dims[1])+1 - tuple(ind-dims[1]*(ind2-1), ind2sub(tail(dims),ind2)...) +sub2ind(dims::Tuple{Vararg{Integer}}) = 1 +sub2ind(dims::Tuple{Vararg{Integer}}, I::Integer...) = _sub2ind(dims,I) +@generated function _sub2ind{N,M}(dims::NTuple{N,Integer}, I::NTuple{M,Integer}) + meta = Expr(:meta,:inline) + ex = :(I[$M] - 1) + for i = M-1:-1:1 + if i > N + ex = :(I[$i] - 1 + $ex) + else + ex = :(I[$i] - 1 + dims[$i]*$ex) + end + end + Expr(:block, meta,:($ex + 1)) +end + +@generated function ind2sub{N}(dims::NTuple{N,Integer}, ind::Integer) + meta = Expr(:meta,:inline) + N==0 && return :($meta; ind==1 ? () : throw(BoundsError())) + exprs = Expr[:(ind = ind-1)] + for i = 1:N-1 + push!(exprs,:(ind2 = div(ind,dims[$i]))) + push!(exprs,Expr(:(=),symbol(:s,i),:(ind-dims[$i]*ind2+1))) + push!(exprs,:(ind=ind2)) + end + push!(exprs,Expr(:(=),symbol(:s,N),:(ind+1))) + Expr(:block,meta,exprs...,Expr(:tuple,[symbol(:s,i) for i=1:N]...)) end # TODO in v0.5: either deprecate line 1 or add line 2