diff --git a/base/abstractarray.jl b/base/abstractarray.jl index 90e9a5bc05a44..a01a6ec6e8616 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -1045,6 +1045,17 @@ function sub2ind(dims, I::Integer...) 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]) ] @@ -1057,23 +1068,6 @@ ind2sub(dims::(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) -function ind2sub(dims::(Integer,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 - function ind2sub{T<:Integer}(dims::(Integer,Integer...), ind::AbstractVector{T}) n = length(dims) l = length(ind) @@ -1087,6 +1081,22 @@ function ind2sub{T<:Integer}(dims::(Integer,Integer...), ind::AbstractVector{T}) return t end +function ind2sub!{T<:Integer}(sub::Array{T}, dims::Array{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]) + end + sub[1] = ind + return +end + indices(I) = I indices(I::Int) = I indices(I::Real) = convert(Int, I) @@ -1094,40 +1104,43 @@ indices(I::AbstractArray{Bool,1}) = find(I) indices(I::Tuple) = map(indices, I) # Generalized repmat -fld1{T <: Integer}(x::T, y::Integer) = fld(x - one(T), y) + one(T) - function repeat{T}(A::Array{T}; inner::Array{Int} = ones(Int, ndims(A)), outer::Array{Int} = ones(Int, ndims(A))) - size_A = size(A) - ndims_A = ndims(A) - length_inner, length_outer = length(inner), length(outer) - ndims_out = max(ndims_A, length_inner, length_outer) + ndims_in = ndims(A) + length_inner = length(inner) + length_outer = length(outer) + ndims_out = max(ndims_in, length_inner, length_outer) - if length_inner < ndims_A || length_outer < ndims_A - error("Inner/outer repetitions must be set for all input dimensions") + if length_inner < ndims_in || length_outer < ndims_in + msg = "Inner/outer repetitions must be set for all input dimensions" + throw(ArgumentError(msg)) end + size_in = Array(Int, ndims_in) size_out = Array(Int, ndims_out) inner_size_out = Array(Int, ndims_out) + for i in 1:ndims_in + size_in[i] = size(A, i) + end for i in 1:ndims_out - t1 = ndims_A < i ? 1 : size_A[i] + 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 - length_out = prod(size_out) + indices_in = Array(Int, ndims_in) + indices_out = Array(Int, ndims_out) + length_out = prod(size_out) R = Array(T, size_out...) for index_out in 1:length_out - indices_out = ind2sub(tuple(size_out...), index_out) - indices_in = Array(Int, length(indices_out)) - for t in 1:length(indices_out) - indices_in[t] = indices_out[t] + ind2sub!(indices_out, size_out, index_out) + for t in 1:ndims_in # "Project" outer repetitions into inner repetitions indices_in[t] = mod1(indices_out[t], inner_size_out[t]) # Find inner repetitions using flooring division @@ -1135,7 +1148,7 @@ function repeat{T}(A::Array{T}; indices_in[t] = fld1(indices_in[t], inner[t]) end end - index_in = sub2ind(size_A, tuple(indices_in[1:ndims_A]...)...) + index_in = sub2ind(size_in, indices_in) R[index_out] = A[index_in] end diff --git a/base/exports.jl b/base/exports.jl index 9ac36d87245a8..342a52c0172a2 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -327,6 +327,7 @@ export factor, factorial, fld, + fld1, flipsign, float, #float16, @@ -404,6 +405,7 @@ export reim, reinterpret, rem, + rem1, round, sec, secd, diff --git a/base/operators.jl b/base/operators.jl index 0311dc186e297..b37a1c7316794 100644 --- a/base/operators.jl +++ b/base/operators.jl @@ -87,6 +87,8 @@ const % = rem # mod returns in [0,y) whereas mod1 returns in (0,y] mod1{T<:Real}(x::T, y::T) = y-mod(y-x,y) +rem1{T<:Real}(x::T, y::T) = rem(x-1,y)+1 +fld1{T<:Real}(x::T, y::T) = fld(x-1,y)+1 # cmp returns -1, 0, +1 indicating ordering cmp{T<:Real}(x::T, y::T) = int(sign(x-y)) diff --git a/base/promotion.jl b/base/promotion.jl index a2674c9803ec5..a1d1fb43b5912 100644 --- a/base/promotion.jl +++ b/base/promotion.jl @@ -165,6 +165,8 @@ rem(x::Real, y::Real) = rem(promote(x,y)...) mod(x::Real, y::Real) = mod(promote(x,y)...) mod1(x::Real, y::Real) = mod1(promote(x,y)...) +rem1(x::Real, y::Real) = rem1(promote(x,y)...) +fld1(x::Real, y::Real) = fld1(promote(x,y)...) cmp(x::Real, y::Real) = cmp(promote(x,y)...) max(x::Real, y::Real) = max(promote(x,y)...) diff --git a/doc/stdlib/linalg.rst b/doc/stdlib/linalg.rst index d020d2dc2b13c..5bd0d194fd6d0 100644 --- a/doc/stdlib/linalg.rst +++ b/doc/stdlib/linalg.rst @@ -278,6 +278,10 @@ Linear algebra functions in Julia are largely implemented by calling functions f Construct a matrix by repeating the given matrix ``n`` times in dimension 1 and ``m`` times in dimension 2. +.. function:: repeat(A, inner = Int[], outer = Int[]) + + Construct an array by repeating the entries of ``A``. The i-th element of ``inner`` specifies the number of times that the individual entries of the i-th dimension of ``A`` should be repeated. The i-th element of ``outer`` specifies the number of times that a slice along the i-th dimension of ``A` should be repeated. + .. function:: kron(A, B) Kronecker tensor product of two vectors or two matrices.