Vertical Alignment of Matrices with spalign Package

This is not supported by spalign.

Here's a different implementation.

\documentclass[12pt]{report}
\usepackage{xparse}
\usepackage{amsmath}
\usepackage{delarray}

\ExplSyntaxOn
\NewDocumentCommand{\extraalign}{O{}m}
 {
  \group_begin:
  \keys_set:nn { extraalign } { #1 }
  \extraalign_make:n { #2 }
  \group_end:
 }

\NewDocumentCommand{\extraalignset}{m}
 {
  \keys_set:nn { extraalign } { #1 }
 }

\tl_new:N \l__extraalign_cols_tl
\tl_new:N \l__extraalign_row_tl
\seq_new:N \l__extraalign_rows_in_seq
\seq_new:N \l__extraalign_rows_out_seq
\seq_new:N \l__extraalign_row_seq
\int_new:N \l__extraalign_cols_int

\keys_define:nn { extraalign }
 {
  h .code:n = \tl_set:Nn \l__extraalign_cols_tl { *{\l__extraalign_cols_int}{#1} },
  h .initial:n = c,
  v .tl_set:N = \l__extraalign_vertical_tl,
  v .initial:n = c,
  p .code:n = \tl_set:Nn \l__extraalign_cols_tl { #1 },
  l .tl_set:N = \l__extraalign_left_tl,
  l .initial:n = (,
  r .tl_set:N = \l__extraalign_right_tl,
  r .initial:n = ),
 }

\cs_new_protected:Nn \extraalign_make:n
 {
  \__extraalign_body:n { #1 }
  \__extraalign_preamble:VVVV
   \l__extraalign_vertical_tl % vertical alignment
   \l__extraalign_left_tl     % left delimiter
   \l__extraalign_right_tl    % right delimiter
   \l__extraalign_cols_tl     % column spec
  % deliver the matrix
  \seq_use:Nn \l__extraalign_rows_out_seq { \\ }
  \end{array}
 }

\cs_new_protected:Nn \__extraalign_preamble:nnnn
 {
  \begin{array}[#1]#2{@{}#4@{}}#3
 }
\cs_generate_variant:Nn \__extraalign_preamble:nnnn { VVVV }

\cs_new_protected:Nn \__extraalign_body:n
 {
  \seq_set_split:Nnn \l__extraalign_rows_in_seq { ; } { #1 }
  \seq_clear:N \l__extraalign_rows_out_seq
  \seq_map_variable:NNn \l__extraalign_rows_in_seq \l__extraalign_row_tl
   {
    \__extraalign_makerow:V \l__extraalign_row_tl
   }
 }

\cs_new_protected:Nn \__extraalign_makerow:n
 {
  \seq_set_split:Nnn \__extraalign_row_seq { ~ } { #1 }
  \int_compare:nT { \l__extraalign_cols_int = 0 }
   {
    \int_set:Nn \l__extraalign_cols_int { \seq_count:N \__extraalign_row_seq }
   }
  \seq_put_right:Nx \l__extraalign_rows_out_seq
   { \seq_use:Nn \__extraalign_row_seq { & } }
 }
\cs_generate_variant:Nn \__extraalign_makerow:n { V }

\ExplSyntaxOff


\begin{document}

\begin{gather*}
  A=\begin{pmatrix}1 & 2 & 3 \\ 4 & 5 & 6 \\ 7 & 8 & 9\end{pmatrix}
\quad
  A=\extraalign{1 2 3;4 5 6;7 8 9}
\\
  A=\extraalign[v=t]{1 2 3;4 5 6;7 8 9}
\quad
  A=\extraalign[p=rcl,v=t]{-1 2 3;4 5 66;700 8 9000}
\\
  A=\extraalign[l=\{,r=.,h=l]{aaaa ; bbb ; c}
\end{gather*}

\end{document}

The optional argument to \extraalign contains a key-value list of options

  • h for the general format of columns (default c), with as many columns as required
  • p for a special preamble, specifying all columns
  • v for the vertical alignment, t, c or b (default c)
  • l for the left delimiter (default (); use . for no delimiter
  • r for the right delimiter (default )); use . for no delimiter

Should you want to change the default values, use \extraalignset with the values you want. For instance, if you do

\extraalignset{ l = [, r = ] }

all matrices (in the current scope or globally if done in the preamble) will use brackets unless locally countermanded.

enter image description here

Just for completeness, here's how you can do augmented matrices.

\extraalignset{l=[,r=]}

\begin{gather*}
  A=\extraalign[p=cccc|cc]{1 2 3 4 5 6;4 5 6 7 8 9;7 8 9 1 2 3}
  \quad
  A=\extraalign[p=cccc|cc,v=t]{1 2 3 4 5 6;4 5 6 7 8 9;7 8 9 1 2 3}
\\
  A=\extraalign[p=ccc|ccc]{1 2 3 4 5 6;4 5 6 7 8 9;7 8 9 1 2 3}
  \quad
  A=\extraalign[p=ccc|ccc,v=t]{1 2 3 4 5 6;4 5 6 7 8 9;7 8 9 1 2 3}
\end{gather*}

enter image description here


\documentclass{article}
\usepackage{tabstackengine,scalerel}
\TABstackMath
\setstacktabbedgap{1ex}
\strutlongstacks{T}
\begin{document}
\[
A = \tabbedLongunderstack{1&2&3\\4&5&6\\7&8&9}
\]
\[
A = \scaleleftright[1.5ex]{\Biggl(}
   {\tabbedLongunderstack{1&2&3\\4&5&6\\7&8&9}}{\Biggr)}
\]
\[
\savestack\mysystem{\setstacktabbedgap{0pt}%
  \tabbedCenterstack[r]{2x +& 3y =& 1\\x -& y =& 10}}
\renewcommand\stackalignment{r}
\stackunder[10pt]
{$A = \tabbedLongunderstack{1&2&3\\4&5&6\\7&8&9}$}
{A system using tabstackengine: $\biggl\{\mysystem$}
\]
\end{document}

enter image description here


I appreciate the other answers. This was bothering me for a while, and as it sat unanswered for so long (I think it is too specific, no one but me apparently needed to be able to do this) I had found a way to do it by patching the spalign commands. Just in case anyone else ever wonders how to do this, I'll post my answer here.

I had to dig into the existing spalign code a bit. The matrices are built using arrays as expected, so I initially thought to just replace \begin{align} by \begin{align}[t]. However, this creates a problem where the delimiters are also centered on the top line:

align top

To solve that problem, I used delarray as suggested in this answer (and as suggested again by egreg's answer this question).

However, this required a much more complicated find-and-replace in the existing code of spalign, since the macros in that package put the delimiters outside of the array environment (as is usual when not using delarray. At any rate, I became a little obsessed with solving this problem and managed it with xpatch and some trial-and-error. I think it's a bit of a mess (partly because of the way *s are handled in spalign), but the following code creates duplicates of several of the spalign environments, aligned with their top rows, with all optional arguments and starred versions intact:

\documentclass[12pt]{report}
\usepackage{amsmath}
\usepackage[delims={[}{]},sysdelims={.}{.}]{spalign} %set to square brackets on matrices and no delimiters on systems
\usepackage{letltxmacro}
\usepackage{delarray}
\usepackage{xpatch}

\makeatletter

\let\tmat=\spalignmat
\let\tmatx=\spalignmat@x
\LetLtxMacro\tmatstar\spalignmat@star
\xpatchcmd{\tmat}{\spalignmat@x}{\tmatx}{}{}
\xpatchcmd{\tmatx}{\spalignmat@star}{\tmatstar}{}{}
\xpatchcmd{\tmatstar}{\spalign@maybedelim}{\spalignenv}{}{}
\xpatchcmd{\tmatstar}{\begin{array}{\spalign@repeated}}%
    {\begin{array}[t]\ifspalign@star\else\spalign@leftdelim\fi%
    {@{\spalignmatdelimskip}\spalign@repeated @{\spalignmatdelimskip}}%
    \ifspalign@star\else\spalign@rightdelim\fi}{}{}
\xpatchcmd{\tmatstar}{{\hskip-\arraycolsep\spalignmatdelimskip}}{}{}{}
\providecommand{\dtmat}[2][r]{{\detm \tmat[#1]{#2}}}

\let\tamatn=\spalignaugmatn
\let\tamatnx=\spalignaugmatn@x
\LetLtxMacro\tamatnstar\spalignaugmatn@star
\xpatchcmd{\tamatn}{\spalignaugmatn@x}{\tamatnx}{}{}
\xpatchcmd{\tamatnx}{\spalignaugmatn@star}{\tamatnstar}{}{}
\xpatchcmd{\tamatnstar}{\spalign@maybedelim}{\spalignenv}{}{}
\xpatchcmd{\tamatnstar}{\begin{array}{\spalign@repeated@one|\spalign@repeated@two}}%
    {\begin{array}[t]\ifspalign@star\else\spalign@leftdelim\fi%
    {@{\spalignmatdelimskip}\spalign@repeated@one|\spalign@repeated@two @{\spalignmatdelimskip}}\ifspalign@star\else\spalign@rightdelim\fi}{}{}
\xpatchcmd{\tamatnstar}{{\hskip-\arraycolsep\spalignmatdelimskip}}{}{}{}

\providecommand{\tamat}[1][r]{%
    \tamatn[#1]{1}%
    }%

\let\tamath=\spalignaugmathalf
\let\tamathx=\spalignaugmathalf@x
\LetLtxMacro\tamathstar\spalignaugmathalf@star
\xpatchcmd{\tamath}{\spalignaugmathalf@x}{\tamathx}{}{}
\xpatchcmd{\tamathx}{\spalignaugmathalf@star}{\tamathstar}{}{}
\xpatchcmd{\tamathstar}{\spalign@maybedelim}{\spalignenv}{}{}
\xpatchcmd{\tamathstar}{\begin{array}{\spalign@repeated@one|\spalign@repeated@two}}%
    {\begin{array}[t]\ifspalign@star\else\spalign@leftdelim\fi%
    {@{\spalignmatdelimskip}\spalign@repeated@one|\spalign@repeated@two @{\spalignmatdelimskip}}\ifspalign@star\else\spalign@rightdelim\fi}{}{}
\xpatchcmd{\tamathstar}{{\hskip-\arraycolsep\spalignmatdelimskip}}{}{}{}

\let\tsys=\spalignsys
\let\tsysx=\spalignsys@x
\let\tsysstar=\spalignsys@star
\xpatchcmd{\tsys}{\spalignsys@x}{\tsysx}{}{}
\xpatchcmd{\tsysx}{\spalignsys@star}{\tsysstar}{}{}
\xpatchcmd{\tsysstar}{\vcenter}{\vtop}{}{}

\makeatother

\begin{document}

\[
    A=\spalignmat{1 2 3;4 5 6;7 8 9}. \quad A=\tmat{1 2 3;4 5 6;7 8 9}.
\]

\[
    A=\spalignaugmat{1 2 3;4 5 6;7 8 9}. \quad A=\tamat{1 2 3;4 5 6;7 8 9}.
\]

\[
    A=\spalignaugmatn{2}{1 2 3 4 5 6;4 5 6 7 8 9;7 8 9 1 2 3}. \quad A=\tamatn{2}{1 2 3 4 5 6;4 5 6 7 8 9;7 8 9 1 2 3}.
\]

\[
    A=\spalignaugmathalf{1 2 3 4 5 6;4 5 6 7 8 9;7 8 9 1 2 3}. \quad A=\tamath{1 2 3 4 5 6;4 5 6 7 8 9;7 8 9 1 2 3}.
\]

System of equations:
$\spalignsys{2x + 3y = 1;x - y = 10}$.\quad
Top aligned:
$\tsys{2x + 3y = 1;x - y = 10}$.

\end{document}

Which produces: top aligned spalign

Those were all I needed, so they're all I patched. Others could be done similarly.

The *ed versions omit the delimiters, and the matrices take optional arguments to specify column alignments. Both of these features still work as in the original spalign.

It would perhaps be easier to just define anew the macros I want instead of using \xpatchcmd, but I found it instructive to do it this way. I had never used xpatch before and learned a lot in this first attempt.

I was not able to get the delimiters top-aligned for a system of equations because spalign uses halign for that instead of the array environment. For me, this was not a problem, since the book I am teaching from doesn't use delimiters on systems anyway, and I wanted to use consistent notation.