Skip to content

Commit d0212fc

Browse files
committed
redo ind2sub / sub2ind redesign
1 parent dea3d0e commit d0212fc

File tree

2 files changed

+63
-98
lines changed

2 files changed

+63
-98
lines changed

base/abstractarray.jl

Lines changed: 60 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -1007,97 +1007,67 @@ function repmat(a::AbstractVector, m::Int)
10071007
return b
10081008
end
10091009

1010-
sub2ind(dims) = 1
1011-
sub2ind(dims, i::Integer) = Int(i)
1012-
sub2ind(dims, i::Integer, j::Integer) = sub2ind(dims, Int(i), Int(j))
1013-
sub2ind(dims, i::Int, j::Int) = (j-1)*dims[1] + i
1014-
sub2ind(dims, i0::Integer, i1::Integer, i2::Integer) = sub2ind(dims, Int(i0),Int(i1),Int(i2))
1015-
sub2ind(dims, i0::Int, i1::Int, i2::Int) =
1016-
i0 + dims[1]*((i1-1) + dims[2]*(i2-1))
1017-
sub2ind(dims, i0::Integer, i1::Integer, i2::Integer, i3::Integer) =
1018-
sub2ind(dims, Int(i0),Int(i1),Int(i2),Int(i3))
1019-
sub2ind(dims, i0::Int, i1::Int, i2::Int, i3::Int) =
1020-
i0 + dims[1]*((i1-1) + dims[2]*((i2-1) + dims[3]*(i3-1)))
1021-
1022-
function sub2ind(dims, I::Integer...)
1023-
ndims = length(dims)
1024-
index = Int(I[1])
1025-
stride = 1
1026-
for k=2:ndims
1027-
stride = stride * dims[k-1]
1028-
index += (Int(I[k])-1) * stride
1029-
end
1030-
return index
1031-
end
1032-
1033-
function sub2ind{T<:Integer}(dims::Array{T}, sub::Array{T})
1034-
ndims = length(dims)
1035-
ind = sub[1]
1036-
stride = 1
1037-
for k in 2:ndims
1038-
stride = stride * dims[k - 1]
1039-
ind += (sub[k] - 1) * stride
1040-
end
1041-
return ind
1042-
end
1043-
1044-
sub2ind{T<:Integer}(dims, I::AbstractVector{T}...) =
1045-
[ sub2ind(dims, map(X->X[i], I)...)::Int for i=1:length(I[1]) ]
1046-
1047-
function ind2sub(dims::Tuple{Integer,Vararg{Integer}}, ind::Int)
1048-
ndims = length(dims)
1049-
stride = dims[1]
1050-
for i=2:ndims-1
1051-
stride *= dims[i]
1052-
end
1053-
1054-
sub = ()
1055-
for i=(ndims-1):-1:1
1056-
rest = rem(ind-1, stride) + 1
1057-
sub = tuple(div(ind - rest, stride) + 1, sub...)
1058-
ind = rest
1059-
stride = div(stride, dims[i])
1060-
end
1061-
return tuple(ind, sub...)
1062-
end
1010+
sub2ind(dims::Tuple{}) = 1
1011+
sub2ind(dims::Tuple{},I::Integer...) = sum(I) - length(I) + 1
1012+
sub2ind(dims::Tuple{Integer,Vararg{Integer}}, i1::Integer) = i1
1013+
sub2ind(dims::Tuple{Integer,Vararg{Integer}}, i1::Integer, I::Integer...) = i1 + dims[1]*(sub2ind(tail(dims),I...)-1)
10631014

1064-
ind2sub(dims::Tuple{Vararg{Integer}}, ind::Integer) = ind2sub(dims, Int(ind))
10651015
ind2sub(dims::Tuple{}, ind::Integer) = ind==1 ? () : throw(BoundsError())
1066-
ind2sub(dims::Tuple{Integer,}, ind::Int) = (ind,)
1067-
ind2sub(dims::Tuple{Integer,Integer}, ind::Int) =
1068-
(rem(ind-1,dims[1])+1, div(ind-1,dims[1])+1)
1069-
ind2sub(dims::Tuple{Integer,Integer,Integer}, ind::Int) =
1070-
(rem(ind-1,dims[1])+1, div(rem(ind-1,dims[1]*dims[2]), dims[1])+1,
1071-
div(rem(ind-1,dims[1]*dims[2]*dims[3]), dims[1]*dims[2])+1)
1072-
ind2sub(a::AbstractArray, ind::Integer) = ind2sub(size(a), Int(ind))
1073-
1074-
function ind2sub{T<:Integer}(dims::Tuple{Integer,Vararg{Integer}}, ind::AbstractVector{T})
1075-
n = length(dims)
1076-
l = length(ind)
1077-
t = ntuple(n, x->Array(Int, l))
1078-
for i = 1:l
1079-
s = ind2sub(dims, ind[i])
1080-
for j = 1:n
1081-
t[j][i] = s[j]
1016+
ind2sub(dims::Tuple{Integer}, ind::Integer) = (ind,)
1017+
function ind2sub(dims::Tuple{Integer,Vararg{Integer}}, ind::Integer)
1018+
@_inline_meta()
1019+
ind2 = div(ind-1,dims[1])+1
1020+
tuple(ind-dims[1]*(ind2-1), ind2sub(tail(dims),ind2)...)
1021+
end
1022+
1023+
# TODO in v0.5: either deprecate line 1 or add line 2
1024+
ind2sub(a::AbstractArray, ind::Integer) = ind2sub(size(a), ind)
1025+
# sub2ind(a::AbstractArray, I::Integer...) = sub2ind(size(a), I...)
1026+
1027+
function sub2ind{T<:Integer}(dims::Tuple{Vararg{Integer}}, I::AbstractVector{T}...)
1028+
N = length(dims)
1029+
M = length(I[1])
1030+
indices = Array{T}(length(I[1]))
1031+
copy!(indices,I[1])
1032+
1033+
s = dims[1]
1034+
for j=2:length(I)
1035+
Ij = I[j]
1036+
for i=1:M
1037+
indices[i] += s*(Ij[i]-1)
1038+
end
1039+
s*= (j <= N ? dims[j] : 1)
1040+
end
1041+
return indices
1042+
end
1043+
1044+
function ind2sub{T<:Integer}(dims::Tuple{Vararg{Integer}}, ind::AbstractVector{T})
1045+
N = length(dims)
1046+
M = length(ind)
1047+
t = [Array{T}(M) for j=1:N]
1048+
copy!(t[1],ind)
1049+
for j = 1:N-1
1050+
d = dims[j]
1051+
tj = t[j]
1052+
tj2 = t[j+1]
1053+
for i = 1:M
1054+
ind2 = div(tj[i]-1, d)
1055+
tj[i] -= d*ind2
1056+
tj2[i] = ind2+1
10821057
end
10831058
end
1084-
return t
1059+
return tuple(t...)
10851060
end
10861061

1087-
function ind2sub!{T<:Integer}(sub::Array{T}, dims::Array{T}, ind::T)
1062+
function ind2sub!{T<:Integer}(sub::Array{T}, dims::Tuple{Vararg{T}}, ind::T)
10881063
ndims = length(dims)
1089-
stride = dims[1]
1090-
for i in 2:(ndims - 1)
1091-
stride *= dims[i]
1092-
end
1093-
for i in (ndims - 1):-1:1
1094-
rest = rem1(ind, stride)
1095-
sub[i + 1] = div(ind - rest, stride) + 1
1096-
ind = rest
1097-
stride = div(stride, dims[i])
1064+
for i=1:ndims-1
1065+
ind2 = div(ind-1,dims[i])+1
1066+
sub[i] = ind - dims[i]*(ind2-1)
1067+
ind = ind2
10981068
end
1099-
sub[1] = ind
1100-
return
1069+
sub[ndims] = ind
1070+
return sub
11011071
end
11021072

11031073
# Generalized repmat
@@ -1113,26 +1083,18 @@ function repeat{T}(A::Array{T};
11131083
throw(ArgumentError("inner/outer repetitions must be set for all input dimensions"))
11141084
end
11151085

1116-
size_in = Array(Int, ndims_in)
1117-
size_out = Array(Int, ndims_out)
1118-
inner_size_out = Array(Int, ndims_out)
1086+
inner = vcat(inner, ones(Int,ndims_out-length_inner))
1087+
outer = vcat(outer, ones(Int,ndims_out-length_outer))
11191088

1120-
for i in 1:ndims_in
1121-
size_in[i] = size(A, i)
1122-
end
1123-
for i in 1:ndims_out
1124-
t1 = ndims_in < i ? 1 : size_in[i]
1125-
t2 = length_inner < i ? 1 : inner[i]
1126-
t3 = length_outer < i ? 1 : outer[i]
1127-
size_out[i] = t1 * t2 * t3
1128-
inner_size_out[i] = t1 * t2
1129-
end
1089+
size_in = size(A)
1090+
size_out = ntuple(i->inner[i]*size(A,i)*outer[i],ndims_out)::Dims
1091+
inner_size_out = ntuple(i->inner[i]*size(A,i),ndims_out)::Dims
11301092

11311093
indices_in = Array(Int, ndims_in)
11321094
indices_out = Array(Int, ndims_out)
11331095

11341096
length_out = prod(size_out)
1135-
R = Array(T, size_out...)
1097+
R = Array(T, size_out)
11361098

11371099
for index_out in 1:length_out
11381100
ind2sub!(indices_out, size_out, index_out)
@@ -1144,7 +1106,7 @@ function repeat{T}(A::Array{T};
11441106
indices_in[t] = fld1(indices_in[t], inner[t])
11451107
end
11461108
end
1147-
index_in = sub2ind(size_in, indices_in)
1109+
index_in = sub2ind(size_in, indices_in...)
11481110
R[index_out] = A[index_in]
11491111
end
11501112

base/deprecated.jl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,9 @@ end
319319
@deprecate flipud(A::AbstractArray) flipdim(A, 1)
320320
@deprecate fliplr(A::AbstractArray) flipdim(A, 2)
321321

322+
@deprecate sub2ind{T<:Integer}(dims::Array{T}, sub::Array{T}) sub2ind(tuple(dims...), sub...)
323+
@deprecate ind2sub!{T<:Integer}(sub::Array{T}, dims::Array{T}, ind::T) ind2sub!(sub, tuple(dims...), ind)
324+
322325
@deprecate strftime Libc.strftime
323326
@deprecate strptime Libc.strptime
324327
@deprecate flush_cstdio Libc.flush_cstdio

0 commit comments

Comments
 (0)