# How to use Array[] to evaluate block-diagonal matrix at different values

I would like to construct a diagonal matrix that is defined as a function and put it multiple times in a block-diagonal matrix each block evaluated at a consecutive integer.

Let's say my matrix looks like this:

$$\mathtt{mat}[x\_]=\begin{pmatrix} x & 1 \\ 1 & x^2 \end{pmatrix}$$

and I would like to stack it up such that it looks something like this:

$$\mathtt{matnew}[x\_]=\begin{pmatrix} x|_1 & 1 & 0& 0&0\\ 1 & x^2|_1 & 0& 0&0\\ 0& 0&x|_2 & 1 &0\\ 0& 0&1 & x^2|_2 &0\\ 0& 0&0 & 0&\ddots\\ \end{pmatrix}$$

where each block in this block-diagonal matrix is evaluated at a different consecutive number. An interesting approach came up here. Particularly, the function

mats[p_, n_] := ArrayFlatten[DiagonalMatrix[Array[1 &, n]] /. {1 -> p, 0 -> 0 p}];


seems to be very helpful, but unfortunately each block will not be evaluated at different x. How should I change the function Array[] in this definition to get the above matrix matnew[x_] with x = 1, x = 2, ...?

mat[x_] := {{x, 1}, {1, x^2}}

matnew[n_] := Block[{f},
ArrayFlatten@(DiagonalMatrix[Array[f, n]] /. Table[f[i] -> mat[i], {i, n}])]

matnew

(* {{1, 1, 0, 0, 0, 0}, {1, 1, 0, 0, 0, 0}, {0, 0, 2, 1, 0, 0},
{0, 0, 1, 4, 0, 0}, {0, 0, 0, 0, 3, 1}, {0, 0, 0, 0, 1, 9}} *)

% // TeXForm


$$\left( \begin{array}{cccccc} 1 & 1 & 0 & 0 & 0 & 0 \\ 1 & 1 & 0 & 0 & 0 & 0 \\ 0 & 0 & 2 & 1 & 0 & 0 \\ 0 & 0 & 1 & 4 & 0 & 0 \\ 0 & 0 & 0 & 0 & 3 & 1 \\ 0 & 0 & 0 & 0 & 1 & 9 \\ \end{array} \right)$$

Here is a more general version that allows fractional numbers

matnew2[imin_, imax_, di_] :=
Block[{f},
ArrayFlatten@(DiagonalMatrix[Table[f[i], {i, imin, imax, di}]] /.
Table[f[i] -> mat[i], {i, imin, imax, di}])]


matnew2[1, 3, 1] gives the same result as before:

$$\left( \begin{array}{cccccc} 1 & 1 & 0 & 0 & 0 & 0 \\ 1 & 1 & 0 & 0 & 0 & 0 \\ 0 & 0 & 2 & 1 & 0 & 0 \\ 0 & 0 & 1 & 4 & 0 & 0 \\ 0 & 0 & 0 & 0 & 3 & 1 \\ 0 & 0 & 0 & 0 & 1 & 9 \\ \end{array} \right)$$

And, for example, with intervals of 1/2 instead of 1:

matnew2[1, 3, 1/2]

$$\left( \begin{array}{cccccccccc} 1 & 1 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ 1 & 1 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & \frac{3}{2} & 1 & 0 & 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 1 & \frac{9}{4} & 0 & 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 2 & 1 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 1 & 4 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 & 0 & \frac{5}{2} & 1 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 & 0 & 1 & \frac{25}{4} & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 3 & 1 \\ 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 1 & 9 \\ \end{array} \right)$$

• This answer worked perfectly. How would I have to change it if I wanted fractions numbers instead of integers? More precisely, the Array[f, n] above should include a range like Array[f, n, {min,max}]. – xabdax Aug 3 '19 at 23:12
• @xabdax I updated the function so it takes three values: min, max, and interval. Let me know if that's not what you meant. – MelaGo Aug 5 '19 at 0:06
• This is exactly what I meant. Thanks!! – xabdax Aug 5 '19 at 22:40
mat = Array[x^(# Boole[# == #2]) &, {2, 2}];

n = 3;

mats = mat /. {x -> #} & /@ Range[n];

sa  = SparseArray[{Band[{1, 1}] -> mats}]

TeXForm @ MatrixForm @ sa


$$\left( \begin{array}{cccccc} 1 & 1 & 0 & 0 & 0 & 0 \\ 1 & 1 & 0 & 0 & 0 & 0 \\ 0 & 0 & 2 & 1 & 0 & 0 \\ 0 & 0 & 1 & 4 & 0 & 0 \\ 0 & 0 & 0 & 0 & 3 & 1 \\ 0 & 0 & 0 & 0 & 1 & 9 \\ \end{array} \right)$$

Also

ControlBlockDiagonalMatrix @@ mats // MatrixForm // TeXForm


same picture

Module[{i = 1}, ArrayFlatten[IdentityMatrix[n] /. {1 :> mats[[i++]]}]] //
MatrixForm // TeXForm


same picture

• How would this look like if 𝑚𝑎𝑡[𝑥_] was an arbitrary function/matrix? I wrote x and x^2 to make the question look simpler but in reality my initial matrix is more complicated (and also bigger) than that. – xabdax Jul 31 '19 at 4:52
• will each block be evaluated at different integers? I updated the question to make this a little clearer. Basically I do not only need them to be on the diagonal but also each block should be evaluated at a different number. – xabdax Jul 31 '19 at 5:02
• @xabdax, please see the new version. – kglr Jul 31 '19 at 5:22

Using an undocumented function:

With[{n = 3}, SparseArraySparseBlockMatrix[Table[{x, x} -> {{x, 1}, {1, x^2}}, {x, 1, n}]]]


generates a block diagonal matrix as a SparseArray[]; use Normal[] if you wish to have an actual list instead.

In general, SparseArraySparseBlockMatrix[] takes a list of rules corresponding to the positions of a specified block; e.g. {1, 1} -> {{1, 1}, {1, 1}} corresponds to block $$(1,1)$$ of the block matrix.

As another example, here is how to construct a block triangular matrix:

SparseArraySparseBlockMatrix[{{1, 1} -> HilbertMatrix, {1, 2} -> IdentityMatrix,
{2, 2} -> Array[Min, {2, 2}]}] // Normal
{{1, 1/2, 1, 0}, {1/2, 1/3, 0, 1}, {0, 0, 1, 1}, {0, 0, 1, 2}}