6

I want to vertical align two matrices by using a combination of \phantom and \llap. But neither \llap nor \clap gives the right spacing.

ps: when I use \makebox[\widthof{$\infty$}][c]{7}, it works. I can't explain the difference between them.

enter image description here

MWE

\documentclass{article}

\usepackage{amsmath}
\usepackage{mathtools}
\usepackage{calc}
%\def\clap#1{\hbox to 0pt{\hss#1\hss}}


\begin{document}

\begin{align*}
D_0 &= \left[\begin{array}{cccc}
    0 & 7 & 1 & 6 \\
    \infty & 0 & 9 & \infty \\
    4   & 4 & 0 & 2 \\
    1 & \infty & \infty & 0 
    \end{array}\right]\\
D_1 &= \left[
\begin{array}{cccc}
    0 & \phantom{\infty}\llap{7}  & 1 & 6 \\
    \infty & 0 & 9 & \infty \\
    4   & 4 & 0 & 2 \\
    1 & 8 & 2 & 0 
\end{array}\right]
\end{align*}

\end{document}
Werner
  • 603,163
sun0727
  • 527
  • You can't explain the difference between using \widthof and combinations of \phantom and \*lap commands? It's not entirely clear what you mean by the PS reference. – Werner Nov 21 '19 at 18:58
  • @Werner I thought, they should have the same result. But in fact only \widthof works. I want to know the reason. Thanks – sun0727 Nov 21 '19 at 19:29
  • See https://tex.stackexchange.com/questions/432061/align-multiple-matrix-equations-and-their-elements – John Kormylo Nov 22 '19 at 01:58

4 Answers4

8

It's best to view the output of certain combinations of \phantoms and \*lapping. Below are all possible overlaps (either \phantom first, followed by \*laps, or \*laps first, followed by \phantom. Column 1 denotes the broad usage, while column 2 shows the actual output. Column 3 shows the \phantom text using a light gray colour, just for clarity. A left rule (in red) is inserted before the construction; a centre rule (green) is inserted in the middle of the construction; a right rule (blue) is inserted after the construction.

enter image description here

\documentclass{article}

\usepackage{xcolor}

\newcommand{\lrule}{\textcolor{red}{\rule[-.3\normalbaselineskip]{.4pt}{1.3\normalbaselineskip}}\hspace*{-.4pt}}
\newcommand{\crule}{\textcolor{green}{\rule[-.3\normalbaselineskip]{.4pt}{1.3\normalbaselineskip}}\hspace*{-.4pt}}
\newcommand{\rrule}{\textcolor{blue}{\rule[-.3\normalbaselineskip]{.4pt}{1.3\normalbaselineskip}}\hspace*{-.4pt}}
\newcommand{\abcd}{\textcolor{black!50}{abcd}}

\begin{document}

\begin{tabular}{ l @{\hspace{4em}} l @{\hspace{4em}} l }
  \verb|\phantom\llap| & \lrule\phantom{abcd}\crule\llap{efgh}\rrule & \lrule \abcd \crule \llap{efgh}\rrule \\
  \verb|\phantom\clap| & \lrule\phantom{abcd}\crule\clap{efgh}\rrule & \lrule \abcd \crule \clap{efgh}\rrule \\
  \verb|\phantom\rlap| & \lrule\phantom{abcd}\crule\rlap{efgh}\rrule & \lrule \abcd \crule \rlap{efgh}\rrule \\
  \verb|\llap\phantom| & \lrule\llap{efgh}\crule\phantom{abcd}\rrule & \lrule \llap{efgh}\crule \abcd \rrule \\
  \verb|\clap\phantom| & \lrule\clap{efgh}\crule\phantom{abcd}\rrule & \lrule \clap{efgh}\crule \abcd \rrule \\
  \verb|\rlap\phantom| & \lrule\rlap{efgh}\crule\phantom{abcd}\rrule & \lrule \rlap{efgh}\crule \abcd \rrule
\end{tabular}

\end{document}

None of the available options show that efgh is set exactly in the middle of abcd. So, there's no way to do what you want using the above methods. You'll have to resort to other box manipulations. Bernard already mentioned eqparbox (which calculates the maximum width of <stuff> automatically for all similar <tag>s within \eqmakebox[<tag>][<align>]{<stuff>}; an optional <align>ment can be specified, with the default being centre).

You can use \makebox[\widthof{<other stuff>}]{<stuff>} which sets <stuff> is a box that matches the width of <other stuff>. Or, you can measure the widths yourself using boxes or the like (for example, \newlength{\inftylen} \settowidth{\inftylen}{$\infty$} and then use \makebox[\inftylen]{<stuff>}).

You could also just set the \infty in a zero-width box (make a thin \infty, or \thinfty command):

enter image description here

\documentclass{article}

\usepackage{mathtools}

\newcommand{\thinfty}{\makebox[0pt]{$\infty$}}

\begin{document}

\begin{align*}
  D_0 &= \left[
    \begin{array}{ *{4}{c} }
          0    &     7    &     1    &     6    \\
      \thinfty &     0    &     9    & \thinfty \\
          4    &     4    &     0    &     2    \\
          1    & \thinfty & \thinfty &     0 
    \end{array}
  \right] \\
  D_1 &= \left[
    \begin{array}{ *{4}{c} }
          0    &     7    &     1    &     6    \\
      \thinfty &     0    &     9    & \thinfty \\
          4    &     4    &     0    &     2    \\
          1    &     8    &     2    &     0 
    \end{array}
  \right]
\end{align*}

\end{document}
Werner
  • 603,163
5

The \fixTABwidth feature of tabstackengine forces all columns to an equal width. While this will not necessarily match matrices generated from another (align* or array) technique, by doing them both in tabstackengine, perfect alignment can be achieved, in this case, without the mess of \phantoms and \llaps.

\documentclass{article}
\usepackage{amsmath}
\usepackage{mathtools}
\usepackage{calc}
\usepackage{tabstackengine}
\fixTABwidth{T}
\setstacktabbedgap{2ex}
\begin{document}
\[
D_0 = 
\bracketMatrixstack{
    0 & 7 & 1 & 6 \\
    \infty & 0 & 9 & \infty \\
    4   & 4 & 0 & 2 \\
    1 & \infty & \infty & 0 
}
\]
\[
D_1 = 
\bracketMatrixstack{
    0 & 7  & 1 & 6 \\
    \infty & 0 & 9 & \infty \\
    4   & 4 & 0 & 2 \\
    1 & 8 & 2 & 0 
}
\]
\end{document}

enter image description here

3

A simple solution with eqparbox. Two observations, the bmatrix environment already defines matrices with extensible brackets, and you don't have to load amsmath when you load mathtools: the latter does it for you, and furthermore, it defines \clap and \mathclap commands.

\documentclass{article}

\usepackage{mathtools}
\usepackage{calc}
\usepackage{eqparbox, booktabs}
\newcommand*{\eqmathbox}[2][2]{\eqmakebox[#1]{$\displaystyle#2$}}

\begin{document}

\begin{align*}
D_0 &=\begin{bmatrix}
    0 & 7 & 1 & 6 \\
    \infty & 0 & 9 & \infty \\
    4 & 4 & 0 & 2 \\
    1 & \eqmathbox{\infty} & \infty & 0
    \end{bmatrix}\\
\addlinespace
D_1 &=
\begin{bmatrix}
    0 & \phantom{\infty}\llap{7} & 1 & 6 \\
    \infty & 0 & 9 & \infty \\
    4 & 4 & 0 & 2 \\
    1 & \eqmathbox{8} & \eqmathbox{2} & 0
\end{bmatrix}
\end{align*}

\end{document} 

enter image description here

Werner
  • 603,163
Bernard
  • 271,350
3

You can define a new column type which reserves the exact space for the infinity symbol.

\documentclass{article}

\usepackage{amsmath}
\usepackage{mathtools}
\usepackage{calc}
\usepackage{array}

\newcolumntype{i}{>{$}w{c}{\widthof{$\infty$}}<{$}}

\begin{document}

\begin{align*}
D_0 &=
\left[\begin{array}{@{}iiii@{}}
  0 & 7 & 1 & 6 \\
  \infty & 0 & 9 & \infty \\
  4   & 4 & 0 & 2 \\
  1 & \infty & \infty & 0 
\end{array}\right]\\
D_1 &= \left[
\begin{array}{@{}iiii@{}}
  0 & 7 & 1 & 6 \\
  \infty & 0 & 9 & \infty \\
  4   & 4 & 0 & 2 \\
  1 & 8 & 2 & 0 
\end{array}\right]
\end{align*}

\end{document}

enter image description here

To answer your question about how to center something in a space at least as wide as another object?

You can use \ooalign, of course:

\documentclass{article}

\makeatletter
\newcommand{\cenover}[2]{%
  \mathord{% force usage in math mode
    \vphantom{#2}%
    \ooalign{\hphantom{$\m@th#2$}$\cr\hfil$\m@th#1$\hfil\cr}%
  }%
}
\makeatother

\begin{document}

$2\infty2$

$2\cenover{7}{\infty}2$

\end{document}

enter image description here

egreg
  • 1,121,712