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.
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.
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)
ArrayFlatten but if I remember correctly it uses quite a bit of memory and was somewhat slow for large matrices.
–
Feb 18 '13 at 18:49
ArrayFlatten is best for packed arrays and slower otherwise. I cannot recall it being a memory hog though of course I expect a SparseArray to be much better there.
– Mr.Wizard
Feb 18 '13 at 22:01
ArrayFlatten with SparseArray and that did not work to well memory wise. If I recall correctly, the best was to create an empty SparseArray and then set the respective parts. If you ever come across an example where this is an issue let me know. Thanks any ways.
–
Feb 19 '13 at 10:22
Fold and Unevaluated make me shine at the moment.Can you give a same amazing solution in this topic about the opposite operation of you? :)
– yode
Jul 12 '16 at 12:23
"BoundingBoxes" is great! So thanks for the kind words but you've surely outdone me this time. :-)
– Mr.Wizard
Jul 12 '16 at 22:36
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)
– Mr.Wizard
Apr 17 '17 at 16:26
Hold /@ Table[. . .] should work because first the Table evaluates, then Hold wraps each individual element making Diagonal "see" a simple vector even if elements (now wrapped in Hold) are themselves deeper arrays..
– Mr.Wizard
Apr 17 '17 at 16:28
Update: Just bumped into this: SparseArray`SparseBlockMatrix:
bmF = With[{r = MapIndexed[#2[[1]] {1, 1}-># &, #, 1]}, SparseArray`SparseBlockMatrix[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

diagF = SparseArray[Band[{1, 1}] -> {##}] &
– Mr.Wizard
Feb 18 '13 at 10:21
ClearAll more often.)
– kglr
Feb 18 '13 at 10:31
diagF[{0, 1, 0}, {1, 0, 0}]? Does diagF[{{0, 1, 0}}, {{1, 0, 0}}] give what is expected?
– kglr
Mar 12 '13 at 05:03
diagF[{{0}, {1}, {0}}, {{1}, {0}, {0}}] or diagF[Transpose@{{0, 1, 0}}, Transpose@{{1, 0, 0}}] to get column matrices on the "diagonal".
– kglr
Mar 12 '13 at 06:06
diagF need to be a 2d array (in other words, ArrayDepth[argi] needs to be 2 for each array argi in the argument sequence).
– kglr
Mar 12 '13 at 07:18
kX1, 1Xm and nXp arrays as input the most convenient way I can think of is the current form of diagF: for example, diagF[(* a 3X1 array *){{x}, {y}, {z}},(* a 2X3 array *){{a, b, c}, {d, e, f}},(* and a 1X3 array *){{r, s, t}}].
– kglr
Mar 12 '13 at 08:06
diagColF = diagF @@ (List /@ # & /@ {##}) & and use as diagColF[{0, 1, 0}, {1, 0, 0}]. Similarly, define diagRowF = diagF @@ (List /@ {##}) & for a version that takes rows as input and use as diagRowF[{0, 1, 0}, {1, 0, 0}]. Hope this helps.
– kglr
Mar 12 '13 at 08:11
CirclePlus := SparseArray[Band[{1, 1}] -> {##}] &; a_\[CirclePlus]b_ := CirclePlus[a, b]
– Eden Harder
Jan 07 '14 at 09:12
diagF = SparseArray[Band[{1, 1}] -> Normal /@ {##}] &
– matheorem
Apr 21 '16 at 05:56
a,b,c,d are SparseArrays.
– kglr
Apr 21 '16 at 06:17
SymmetrizedArray type. Check it again : )
– matheorem
Apr 21 '16 at 06:42
a = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
b = {{1, 2}, {3, 4}}; SparseArray[Band[{1, 1}] -> {a, b}] // MatrixForm
ArrayFlatten. – b.gates.you.know.what Feb 18 '13 at 09:17