Is there a nice way to add submatrices to a larger matrix?

So I’ve found two ways of doing this, the obvious for-loop way and the slightly more Julian infix operator way.

First, the for-loop way

``````for (ind,i) in enumerate(indices)
M[i:i+n, i:i+m] .= A[ind]
end
``````

Where `indices` contains the top-left index of each sub matrix in `M`, and `A` is an `n`x`m` matrix smaller than `M`.

And the infix operator way

``````⊕(x,y) = (x .= y)
[@view(M[i:i+n, i:i+m]) for i in indices] .⊕ A
``````

I’ve been trying to figure out a way of doing the second way without the awkward double broadcasting trick since just using `.=` doesn’t work.

Is there a generally prettier way of doing this?

A loop seems a heck of a lot clearer (and doesn’t temporary arrays like your second approach). Nothing wrong with loops in Julia.

Another possibility would be to use a different data structure. e.g. make `M` into a matrix of matrices (or `SMatrix` from StaticArrays.jl, if they are small and fixed-size). But that depends on what you want to do with `M` afterwards.

3 Likes

The GitHub - JuliaArrays/BlockDiagonals.jl: Functionality for working efficiently with block diagonal matrices. package might be the efficiency trick you are looking for. By using it, it might be possible to avoid the matrix copies in the first place. And as the proverb says, the most efficient work is the work NOT done.

1 Like

Unless your matrix is sparse, I would also suggest simple concatenation via `[ ]` (aka `hvcat`). I find

``````[A B
C D]
``````

to be quite a bit more readable. Although if you still need to access these submatrices after construction, then your `[@view ...]` solution seems appropriate.

You might also take a look at BlockArrays.jl.

That also works for sparse matrices.

3 Likes