# How to convert diagonal matrix to rectangular matrix

Suppose you have the following diagonal matrix:

$$\left( \begin{array}{cc} a & 0 \\ 0 & \{b,c\} \end{array} \right)$$

How can the above matrix be converted to the following rectangular one?

$$\left( \begin{array}{ccc} a & 0 & 0 \\ 0 & b & c \end{array} \right)$$

Or a more complex example:

$$\left( \begin{array}{ccc} \{\{b,c,d,e,f\}\} & 0 & 0 \\ 0 & \{a\} & 0 \\ 0 & 0 & \{\{b,c\},\{x,y\}\} \end{array} \right)$$

to

$$\left( \begin{array}{cccccccc} b & c & d & e & f & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 & a & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 & 0 & b & c \\ 0 & 0 & 0 & 0 & 0 & 0 & x & y \end{array} \right)$$

Using a combination of SparseArray and Band after some processing of the diagonal of the input matrix:

ClearAll[toRectangularMatrix]
toRectangularMatrix = Module[{blocks = Replace[Diagonal[#],
{x_?(ArrayDepth @ # == 0 &) :> {{x}},  x_?(ArrayDepth @ # == 1 &) :> {x}}, 1]},
SparseArray[Band[{1, 1}] -> blocks]] &;


Examples:

toRectangularMatrix @ {{a, 0}, {0, {b, c}}} // MatrixForm // TeXForm


$$\left( \begin{array}{ccc} a & 0 & 0 \\ 0 & b & c \\ \end{array} \right)$$

 toRectangularMatrix @ {{{b, c}, 0}, {0, a}} // MatrixForm // TeXForm


$$\left( \begin{array}{ccc} b & c & 0 \\ 0 & 0 & a \\ \end{array} \right)$$

toRectangularMatrix @ {{a, 0}, {0, {{b, c}, {d, e}}}} // MatrixForm  // TeXForm


$$\left( \begin{array}{ccc} a & 0 & 0 \\ 0 & b & c \\ 0 & d & e \\ \end{array} \right)$$

toRectangularMatrix @ {{{a, d, e}, 0}, {0, {b, c}}} // MatrixForm // TeXForm


$$\left( \begin{array}{ccccc} a & d & e & 0 & 0 \\ 0 & 0 & 0 & b & c \\ \end{array} \right)$$

toRectangularMatrix @ {{a, 0, 0}, {0, {b, c, d, e, f}, 0}, {0, 0, {{b, c}, {x, y}}}} //
MatrixForm // TeXForm


$$\left( \begin{array}{cccccccc} a & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ 0 & b & c & d & e & f & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 & 0 & b & c \\ 0 & 0 & 0 & 0 & 0 & 0 & x & y \\ \end{array} \right)$$

• Yes, in a situation where the diagonal matrix is as per the below example, then this approach should not be applied: {{a,b},0},{0,c}} Jul 7, 2019 at 6:11
• @aleksander_si, please see the updated version.
– kglr
Jul 7, 2019 at 6:52
• It seems that your updated solution also correctly handles more complex cases, for example, nested matrix, single row matrix as well as the order/length is now not important anymore. I have tested this as well and it seems this is the best solution now. Jul 7, 2019 at 7:29

Here is a solution using ArrayFlatten:

toRectangularMatrix2[m_] := ArrayFlatten@Replace[m, l_List /; ! MatrixQ@l :> {l}, {2}]

toRectangularMatrix2@{{a, 0, 0}, {0, {b, c, d, e, f}, 0}, {0, 0, {{b, c}, {x, y}}}} // MatrixForm


$$\left( \begin{array}{cccccccc} a & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ 0 & b & c & d & e & f & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 & 0 & b & c \\ 0 & 0 & 0 & 0 & 0 & 0 & x & y \\ \end{array} \right)$$

The Replace[…] part is only needed to convert the list-type entries to matrices, e.g. {b,c,d,e,f} to {{b,c,d,e,f}}. So if you can change the input format to be more uniform, ArrayFlatten on its own would be enough:

{{a, 0, 0}, {0, {{b, c, d, e, f}}, 0}, {0, 0, {{b, c}, {x, y}}}} // ArrayFlatten // MatrixForm

• I have to test your solution first to decide if this should be labeled as the answer. The approach by kglr uses sparse array, not sure if this may be useful by anyone? @kglr, why have you used sparse array approach? But yes, we should use the ArrayFlatten function as much as possible. Jul 8, 2019 at 9:45
diag = Flatten[{#}] & /@ Diagonal[m];
ncols = Length@Flatten[diag];
offsets = Most@Prepend[Accumulate[Length /@ diag], 0];

• @C.E. replaced PadRight with an alternative method.