# How to form a block-diagonal matrix from a list of matrices?

For example, like this:

I know Join works, but it is a bit troublesome for multiple matrices. I also tried DiagonalMatrix, but it can only form a matrix from a list of elements.

• Have a look at ArrayFlatten. Commented Feb 18, 2013 at 9:17
• @Mr.Wizard, thanks. Commented Nov 12, 2014 at 10:29
• Related: (18224) Commented Jun 11, 2017 at 12:12

## 3 Answers

ybeltukov's blockArray from Speeding up generation of block diagonal matrix blows the methods below out of the water by orders of magnitude, in terms of performance.

a = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};

b = {{1, 2}, {3, 4}};

ArrayFlatten[{{a, 0}, {0, b}}] // MatrixForm


You can Fold this operation over a list of matrices to get a diagonal:

a = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
b = {{1, 2}, {3, 4}};
c = {{1, 2, 3}, {4, 5, 6}};
d = {{1, 2}, {3, 4}, {5, 6}};

Fold[ArrayFlatten[{{#, 0}, {0, #2}}] &, a, {b, c, d}] // MatrixForm


Here is another way to do this, illustrating a forcing of DiagonalMatrix by using an arbitrary head (Hold) on top of List:

DiagonalMatrix[Hold /@ {a, b, c, d}] // ReleaseHold // ArrayFlatten // MatrixForm


(same output)

Or a bit more cleanly using Unevaluated (though this may be harder to apply in a program as opposed to interactive input because the elements of your matrix list will probably not be named):

DiagonalMatrix[Unevaluated @ {a, b, c, d}] // ArrayFlatten // MatrixForm


(same output)

• Mr.Wizard What about a list of Matrices? I only examplified two matrices to form one block-diagonal matrix. Better automatic method. Commented Feb 18, 2013 at 9:31
• @user5463 what do you mean? Commented Feb 18, 2013 at 9:31
• Suppose my matrices are not predefined, but generated in the middle of my program. Commented Feb 18, 2013 at 9:37
• @user5463 see my updated answer; is that what you want? Commented Feb 18, 2013 at 9:43
• @huotuichang Let me see if I can explain in a comment. Diagonal needs to "see" a simple vector (list) of elements (i.e. not matrices themselves) for it to work in the manner I need here. Unevaluated @ {a, b, c, d} works because {a, b, c, d} is expressly a vector of elements, and Unevaluated keeps the evaluator from changing it before Diagonal "sees" it. However Table[. . .] is not expressly a vector and therefore Diagonal doesn't know how to operate on it. This is what I meant by "may be harder to apply in a program." (continued) Commented Apr 17, 2017 at 16:26

Update: Just bumped into this: SparseArraySparseBlockMatrix:

bmF = With[{r = MapIndexed[#2[[1]] {1, 1}-># &, #, 1]}, SparseArraySparseBlockMatrix[r]]&;

a = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
b = {{1, 2}, {3, 4}};
c = {{x, y, z}, {u, v, w}};

bmF[{a, b, c}]  // MatrixForm


Original post:

 diagF = With[{dims = Total@(Dimensions /@ {##})},
SparseArray[Band[{1, 1}, dims] -> {##}, dims]] &;


Edit: Much more elegant form (thanks to Mr.Wizard)

 diagF = SparseArray[Band[{1, 1}] -> {##}] &


Example:

 a = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
b = {{1, 2}, {3, 4}};
c = {{1, 2, 3}, {4, 5, 6}};
d = {{1, 2}, {3, 4}, {5, 6}};
diagF[a, b, d, b, c] // MatrixForm


• I forgot about that. Nice. Commented Feb 18, 2013 at 10:16
• If I am not mistaken this function can be reduced to: diagF = SparseArray[Band[{1, 1}] -> {##}] & Commented Feb 18, 2013 at 10:21
• @Mr.Wizard, you are right! (somehow I did not get that form working when I first tried; need to use ClearAll more often.)
– kglr
Commented Feb 18, 2013 at 10:31
• +1 Great solution. It may be worth pointing out, though, that the example is not a block-diagonal matrix. By definition, a block-diagonal matrix represents an endomorphism of a product of vector spaces in which each component space is mapped to itself; ergo, the blocks must be square. But it is evident that this solution will work correctly when its input matrices are all square; it can be thought of as a generalization of the block-diagonal form in which the matrix represents a Cartesian product of arbitrary linear maps (rather than just endomorphisms). Commented Feb 18, 2013 at 18:10
• @whuber, thanks. Great observation.
– kglr
Commented Feb 18, 2013 at 18:32

a = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};

b = {{1, 2}, {3, 4}}; SparseArray[Band[{1, 1}] -> {a, b}] // MatrixForm