# Expanding a matrix by duplicating its elements

Hi!

I am trying to create a “higher resolution” matrix by duplicating, in both dimensions by a factor `n`, the elements of a “lower resolution” matrix. A naive implementation looks like this:

``````function lr2hr(
inarray::AbstractMatrix,
factor::Integer
)

# Determine the type and size of the input argument `inarray`, and define the output array `outarray`:
in_type = typeof(inarray)
in_size = size(inarray)
outarray = Matrix{in_type}(undef, factor * in_size[1], factor * in_size[2])

for i = 1:in_size[1]
for j = 1:in_size[2]
for k = 1 + (i - 1) * factor:(i * factor)
for l = 1 + (j - 1) * factor:(j * factor)
outarray[k, l] = inarray[i, j]
end
end
end
end

return outarray

end
``````

This function generates an error message complaining about “Cannot `convert` an object of type Int64 to an object of type Matrix{Int64}”, although it seems to me that `outarray[k, l]` and `inarray[i, j]` are both integers (though each is a matrix element):

``````julia> inarray = [1 2; 3 4]
2×2 Matrix{Int64}:
1  2
3  4

julia> outarray = lr2hr(inarray, 2)
ERROR: MethodError: Cannot `convert` an object of type Int64 to an object of type Matrix{Int64}
Closest candidates are:
convert(::Type{T}, ::LinearAlgebra.Factorization) where T<:AbstractArray at ~/.julia/juliaup/julia-1.8.5+0.x64.apple.darwin14/share/julia/stdlib/v1.8/LinearAlgebra/src/factorization.jl:58
convert(::Type{Array{T, N}}, ::StaticArraysCore.SizedArray{S, T, N, N, Array{T, N}}) where {S, T, N} at ~/.julia/packages/StaticArrays/J9itA/src/SizedArray.jl:88
convert(::Type{Array{T, N}}, ::StaticArraysCore.SizedArray{S, T, N, M, TData} where {M, TData<:AbstractArray{T, M}}) where {T, S, N} at ~/.julia/packages/StaticArrays/J9itA/src/SizedArray.jl:82
...
Stacktrace:
[1] setindex!
@ ./array.jl:968 [inlined]
[2] lr2hr(inarray::Matrix{Int64}, factor::Int64)
@ JMTools ~/Projects/MISR/MISR_Tools/JMTools/src/lr2hr.jl:81
[3] top-level scope
@ REPL[14]:1
``````

where line 81 points to the statement `outarray[k, l] = inarray[i, j]`. The matrix `outarray` should look like this:

``````1 1 2 2
1 1 2 2
3 3 4 4
3 3 4 4
``````

Questions:

1. How should I assign the elements of the small matrix to the larger one?
2. Is there a more efficient way to construct the larger matrix?

``````in_type = typeof(inarray)
outarray = Matrix{in_type}(undef, factor * in_size[1], factor * in_size[2])
``````

the type of `inarray` is `Matrix`, you probably meant `eltype` here (i.e. the type of the elements of `inarray`, not of the array itself).

1 Like

As for efficiency, you probably don’t want to construct this matrix at all, consider expressing it as a Kronecker product with LazyArrays

2 Likes

Thanks a lot, @nilshg. That’s right, and it works well. I did not know about the command `eltype`.

Regarding the efficiency question, my application is this: the process that generates `inarray` actually creates a geophysical field, for instance of 512 by 128 pixels. The goal is to create a map of that field at a size more convenient for visualization or printing. In that case, `factor` would be `4`, for instance, to generate a reasonable image on the screen.

I’ll look into the link to `Kronecker product with LazyArrays`. Thanks again for your help.

By the way, you can use `Base.repeat` for this:

``````julia> inarray = [1 2; 3 4]
2×2 Matrix{Int64}:
1  2
3  4

julia> repeat(inarray, inner=(2,2))
4×4 Matrix{Int64}:
1  1  2  2
1  1  2  2
3  3  4  4
3  3  4  4
``````
4 Likes

Even better! Thanks @Jollywatt for this elegant solution.