How to convert diagonal matrix to rectangular matrix
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)$
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
diag = Flatten[{#}] & /@ Diagonal[m];
ncols = Length@Flatten[diag];
offsets = Most@Prepend[Accumulate[Length /@ diag], 0];
row[values_, offset_, ncols_] := PadRight[ArrayPad[values, {offset, 0}], ncols]
matrix[diag_, offsets_, ncols_] := MapThread[row[#, #2, ncols] &, {diag, offsets}]
m = {{a, 0, 0}, {0, {b, c, d, e, f}, 0}, {0, 0, {b, c}}}
matrix[diag, offsets, ncols] // MatrixForm