# Is there an easy way to fill with zeros in array concatenation?

For example,

``````julia> [rand(2,2) zeros(2,3)
zeros(3,2) rand(3,3)]
5×5 Matrix{Float64}:
0.717944  0.840054  0.0       0.0       0.0
0.513488  0.62959   0.0       0.0       0.0
0.0       0.0       0.553575  0.129365  0.998488
0.0       0.0       0.493924  0.634678  0.267029
0.0       0.0       0.643076  0.394884  0.650393
``````

In this case I want the off-diagonal blocks to be zero, and would prefer to leave the sizes implicit. Is there a way to use some type such that the sizes are inferred automatically, and the expression may look something like

``````[A ZerosFill()
ZerosFill() B]
``````

where `ZerosFill()` would be replaced by `zeros` of compatible sizes (or perhaps `Zeros` from `FillArrays`).

Had these been square matrices, I could have used the `UniformScaling` `0I` to represent the zeros as

``````julia> [rand(2,2) 0I
0I rand(2,2)]
4×4 Matrix{Float64}:
0.39555   0.0482989  0.0       0.0
0.766527  0.386412   0.0       0.0
0.0       0.0        0.705164  0.436469
0.0       0.0        0.188006  0.566772
``````

however I don’t know of a way to do this for rectangular matrices.

``````A = randn(2,2)
B = randn(3,3)
iA, jA = size(A)
iB, jB = size(B)
C = [A zeros(iA,jB);
zeros(iB,jA) B]
``````

For this specific case you can use the BlockDiagonals package.

2 Likes

That’s true. The actual case that I’m dealing with is not block diagonal, but a block array. I was hoping that a more general solution might exist

I realize that in this case I can read the sizes off the arrays, however this becomes difficult if there are more arrays involved. In any case I was hoping that I may leave the sizes implicit, and have it inferred from the context.

If your final matrix is something like an irregular-sized checker-board with one field per column/row, you still can infer it before assembly (Tuple, for loop).
If there are several filled subarrays per column/row, you need more code, but should be doable.

Based on the code for `I` (`UniformScaling`), it shouldn’t be very hard to do: julia/uniformscaling.jl

When there is only one per row, it should be quite easy, but if there is multiple on one row, we can’t know their widths because the submatrix widths are not required to match with the previous line

meaning this is possible:

``````julia> [fill(9,2) 0I
0I fill(8,2)]
4×3 Matrix{Int64}:
9  0  0
9  0  0
0  0  8
0  0  8

julia> [fill(9,2) 0I 0I
0I fill(8,2) 0I]
4×5 Matrix{Int64}:
9  0  0  0  0
9  0  0  0  0
0  0  8  0  0
0  0  8  0  0
``````

this means there would be ambiguity with `ZerosFill()` or only accept stricter dimensions

In the absence of a smarter `ZeroFill`, there’s GitHub - JuliaArrays/FillArrays.jl: Julia package for lazily representing matrices filled with a single entry which at least allows you to avoid the allocations of zero matrices.

Could you define a function to handle n-matrices?

For example
``````function blockmatrix(A::Vector{Matrix{Int}})
sa = size.(A)
sz = cumsum.((first.(sa), last.(sa)))
R = zeros(eltype(A[1]),last.(sz))
r0, c0 = 1, 1
for i in 1:length(A)
ri, ci = getindex.(sz,i)
R[r0:ri, c0:ci] .= A[i]
r0, c0 = ri + 1, ci + 1
end
return R
end

n = 3  # example with 3 matrices:
A = Vector{Matrix{Int}}(undef,n)
A[1] = rand((1:4), 2,3)
A[2] = rand((-4:-1), 1,2)
A[3] = rand(7:8, 4,5)

julia> blockmatrix(A)
7×10 Matrix{Int64}:
3  4  1   0   0  0  0  0  0  0
1  1  4   0   0  0  0  0  0  0
0  0  0  -3  -2  0  0  0  0  0
0  0  0   0   0  7  8  7  7  8
0  0  0   0   0  7  7  8  7  7
0  0  0   0   0  7  7  8  8  8
0  0  0   0   0  8  7  8  8  7
``````

Nobody has suggested

``````julia> cat(rand(2,2),rand(3,3);dims=(1,2))
5×5 Matrix{Float64}:
0.104583  0.266817  0.0       0.0       0.0
0.915434  0.785553  0.0       0.0       0.0
0.0       0.0       0.89667   0.760755  0.778991
0.0       0.0       0.18982   0.439059  0.489084
0.0       0.0       0.937842  0.298687  0.669757
``````
4 Likes

@Jean_Michel, brilliant , with an array of matrices it even takes splatting: `cat(A...;dims=(1,2))`