Matrix decomposition dimensions diagram
Here I do it with stacks, setting the indices below the boxes. The primary macro is
\matbox{rows}{columns}{row index}{column index}{matrix name}
.
A helper macro is \raiserows
, which is like a \raisebox
, except that the "length" is specified in rows, not actual length. Note that in the MWE, because X
has 7 rows, while P^T
only has 2 rows, P^T
must be lifted (7-2)/2 = 2.5 rows.
I introduce the factor \matscale
to scale your box sizes. By default, each row and column of the box size will occupy a square of size \baselineskip
on a side. The factor \matscale
(which defaults to 1) will scale that value.
EDITED to set array indices in \scriptstyle
\documentclass{article}
\usepackage{stackengine}
\stackMath
\newlength\matfield
\newlength\tmplength
\def\matscale{1.}
\newcommand\dimbox[3]{%
\setlength\matfield{\matscale\baselineskip}%
\setbox0=\hbox{\vphantom{X}\smash{#3}}%
\setlength{\tmplength}{#1\matfield-\ht0-\dp0}%
\fboxrule=1pt\fboxsep=-\fboxrule\relax%
\fbox{\makebox[#2\matfield]{\addstackgap[.5\tmplength]{\box0}}}%
}
\newcommand\raiserows[2]{%
\setlength\matfield{\matscale\baselineskip}%
\raisebox{#1\matfield}{#2}%
}
\newcommand\matbox[5]{
\stackunder{\dimbox{#1}{#2}{$\mathbf{#5}$}}{\scriptstyle(#3\times #4)}%
}
\parskip 1em
\begin{document}
$\renewcommand\matscale{.6}
\matbox{7}{4}{I}{J}{X} =
\matbox{7}{2}{I}{R}{T} \raiserows{2.5}{\matbox{2}{4}{R}{J}{P^T}} +
\matbox{7}{4}{I}{J}{E}$
\end{document}
Just to clarify, in case it wasn't clear. One can use actual (very large) matrix dimensions, as long as one scales suitably small. For example, the following works::
$\renewcommand\matscale{.05}
\matbox{300}{75}{I}{J}{X} =
\matbox{300}{25}{I}{R}{T} \raiserows{137.5}{\matbox{25}{75}{R}{J}{P^T}} +
\matbox{300}{75}{I}{J}{E}$
Here is a way to do it "manually."
\documentclass{article}
\usepackage{amsbsy}
\newcommand*{\clap}[1]{\hbox to 0pt{\hss#1\hss}}
\newcommand*{\mat}[1]{\boldsymbol{\mathrm{#1}}}
\newcommand*{\subdims}[3]{\clap{\raisebox{#1}[0pt][0pt]{$\scriptstyle(#2 \times #3)$}}}
\fboxrule=1pt
\begin{document}
\Huge
\[
\framebox[2.5cm]{\clap{\raisebox{0pt}[1.5cm][1.5cm]{$\mat X$}}\subdims{-2.5cm} I J} =
\framebox[1.5cm]{\clap{\raisebox{0pt}[1.5cm][1.5cm]{$\mat T$}}\subdims{-2.5cm} I R} \
\framebox[2.5cm]{\clap{\raisebox{5mm}[1.5cm]{$\mat P^T$}} \subdims{-1cm} R J} +
\framebox[2.5cm]{\clap{\raisebox{0pt}[1.5cm][1.5cm]{$\mat E$}}\subdims{-2.5cm} I J}
\]
\end{document}
Result:
Obviously this doesn't compare to Mr. Segletes's powerful and general answer! It does use more basic commands, however, which could have the benefits that it's quicker to compile on a slow machine, and it will work even with a smaller installation that's lacking in packages. Or perhaps you just like getting your hands dirty. The drawback, of course, is that you have to determine all the widths, heights, and depths yourself.
Note: if you use mathtools
or any other package that provides a \clap
command, it will conflict with the definition. In this case, just omit this definition and use the \clap
provided.
This is one possible solution via amsmath
package.
Code
\documentclass[12pt]{article}
\usepackage[margin=1cm,paper size={20cm,5cm}]{geometry}
\usepackage{amsmath,amssymb}
\thispagestyle{empty}
\begin{document}
\[
{\begin{pmatrix}
& & \\
& X &\\
& &
\end{pmatrix}
\mkern-10mu}_{I \times J}=
{\begin{pmatrix}
\phantom{T}\\
\makebox[20pt][c]{$T$}\\
\phantom{T}
\end{pmatrix}
\mkern-10mu}_{I \times R}
{\begin{pmatrix}
& & \\
& \raisebox{10pt}{$P^T$} &\\
\end{pmatrix}\mkern-10mu}_{R \times J}+
{\begin{pmatrix}
& & \\
& E &\\
& &
\end{pmatrix}
\mkern-10mu}_{I \times J}
\]
\end{document}