11

Since I am using 2 x 2 matrices very frequently, I would like to define a command which would work like this: \matr{a, b, c, d} would produce $\begin{pmatrix} a & b \\ c & d \end{pmatrix}$.

Of course, I know how to get this result using something like \matr{a}{b}{c}{d}, but the point is to have a "comma-separated list" of arguments. A solution using \matr{a, b}{c, d} could be interesting as well (especially its generalization to 3 x 3 matrices).

Most of the answers from here, there or there seem to rely on xparse package. But I am highly unused to the LaTeX3 syntax, so I have no clue on how to tackle with my problem.

4
  • Oh, it seems that I cannot use LaTeX? It does not render currently... :-(
    – Watson
    Feb 25, 2021 at 17:58
  • 2
    We deliberately do not have MathJaX on the site: if you need to show TeX output, make an image and upload it
    – Joseph Wright
    Feb 25, 2021 at 18:00
  • This function already exists from within Emacs for matrices of all sizes. As a bonus, you can do all kinds of calculations on the matrices, see my answer for more precision.
    – gigiair
    Mar 11, 2021 at 6:45
  • There is an analogue command in mlist package: mirror.foobar.to/CTAN/macros/latex/contrib/mlist/mlist.pdf.
    – Watson
    Mar 20, 2021 at 17:32

6 Answers 6

8

I am highly unused to the LaTeX3 syntax too, so I give you non-exp3 solution based only on TeX primitives. You need not any LaTeX package (and you basically don't even need LaTeX):

\documentclass[12pt]{article}

\def\addto#1#2{\expandafter\def\expandafter#1\expandafter{#1#2}}
\def\matr#1{\def\matrL{}\matrA#1\end}
\def\matrA#1{\ifx\end#1\pmatrix{\matrL}\else 
   \ifx,#1\addto\matrL{&}\else
   \ifx;#1\addto\matrL{\cr}\else
   \addto\matrL{#1}\fi\fi
   \expandafter\matrA\fi
}

\begin{document}

$$
  \matr{a,b;c,d}\ne\matr{1,2,3;4,5,6;7,8,9;10,11,12}
$$

\end{document}
2
  • 2
    Wonderful! I think that I will accept this answer since it seems to be the only one that works with the (old) TexLive 2018, and also I feel that I would be able to understand this answer (as opposed to the scary LaTeX3 syntax...).
    – Watson
    Feb 26, 2021 at 7:18
  • Some update: the above code doesn't work with \usepackage{amsmath}, which rise the error Package amsmath Error: Old form \pmatrix should be \begin{pmatrix}.. One has simply to use \begin{pmatrix}\matrL\end{pmatrix} instead of \pmatrix{\matrL} in your code. But then there is an issue with babel french option! I asked about it here: tex.stackexchange.com/questions/586677
    – Watson
    Mar 10, 2021 at 15:28
11

The argument is first split at commas in a sequence which is mapped taking into account the positions, so we can add & or \\ as needed.

\documentclass{article}
\usepackage{amsmath}

\ExplSyntaxOn
\NewDocumentCommand{\matr}{m}
 {
  \begin{pmatrix}
  \seq_set_from_clist:Nn \l__watson_matr_seq { #1 }
  \seq_indexed_map_function:NN \l__watson_matr_seq \__watson_matr_entry:nn
  \end{pmatrix}
 }

\seq_new:N \l__watson_matr_seq

\cs_new:Nn \__watson_matr_entry:nn
 {
  #2 % the entry
  \int_case:nn { #1 } { {1}{&} {2}{\\} {3}{&} }
 }
\ExplSyntaxOff

\begin{document}

\[
\matr{a,b,c,d}
\]

\end{document}

enter image description here

Can we generalize it? Yes.

\documentclass{article}
\usepackage{amsmath}

\ExplSyntaxOn
\NewDocumentCommand{\matr}{O{2}m}
 {
  \int_set:Nn \l__watson_matr_size_int { #1 }
  \begin{pmatrix}
  \watson_matr:nn { #1 } { #2 }
  \end{pmatrix}
 }

\seq_new:N \l__watson_matr_seq
\int_new:N \l__watson_matr_size_int

\cs_new_protected:Nn \watson_matr:nn
 {
  \seq_set_from_clist:Nn \l__watson_matr_seq { #2 }
  \seq_indexed_map_function:NN \l__watson_matr_seq \__watson_matr_entry:nn
 }
\cs_new_protected:Nn \__watson_matr_entry:nn
 {
  #2 % the entry
  \int_compare:nTF { \int_mod:nn { #1 } { \l__watson_matr_size_int } = 0 }
   { \\ }
   { & }
 }
\ExplSyntaxOff

\begin{document}

\[
\matr{a,b,c,d}\ne\matr[3]{1,2,3,4,5,6,7,8,9}
\]

\end{document}

enter image description here

If you're willing to accept a slightly different syntax, with semicolons for ending rows, you can easily produce matrices with different shapes and delimiters.

\documentclass{article}
\usepackage{amsmath}

\ExplSyntaxOn
\NewDocumentCommand{\matr}{O{p}m}
 {
  \seq_set_split:Nnn \l__watson_matr_full_seq { ; } { #2 }
  \begin{#1matrix}
  \seq_map_function:NN \l__watson_matr_full_seq \__watson_matr_makerow:n
  \end{#1matrix}
 }

\seq_new:N \l__watson_matr_full_seq
\seq_new:N \l__watson_matr_row_seq

\cs_new_protected:Nn \__watson_matr_makerow:n
 {
  \seq_set_split:Nnn \l__watson_matr_row_seq { , } { #1 }
  \seq_use:Nn \l__watson_matr_row_seq { & }
  \\
 }
\ExplSyntaxOff

\begin{document}

\[
\matr{a,b;c,d}\ne\matr[b]{1,2,3;4,5,6;7,8,9;10,11,12}
\]

\end{document}

enter image description here

3
  • Thank you very much. I think one should include \usepackage{xparse}. Even with it, it does not compile with the TexLive2018 distribution... The log file says "! Undefined control sequence. \matr code ...eq {#1}\seq_indexed_map_function:NN \l__watson_matr_seq __wat... l.26 \matr{a,b,c,d}"
    – Watson
    Feb 25, 2021 at 18:48
  • @Watson Only if you're running an older LaTeX kernel. Update, TL 2018 is really outdated.
    – egreg
    Feb 25, 2021 at 20:57
  • @Watson I added a different method for matrices of arbitrary shape.
    – egreg
    Feb 25, 2021 at 23:17
7

Here I use tokcycle to replace the commas with & separators. WHile I show 2x2 and 3x3, any number of columns are acceptible, as long as the matrices contain 2 or (optionally) 3 rows.

\documentclass{article}
\usepackage{amsmath,tokcycle}
\newcommand\matr[1][2]{\tctestifnum{3=#1}{\matrTHREE}{\matrTWO}}
\newcommand\matrTWO[2]{%
  \tokcyclexpress{#1\\#2}%
  \begin{pmatrix}\the\cytoks\end{pmatrix}}
\newcommand\matrTHREE[3]{%
  \tokcyclexpress{#1\\#2\\#3}%
  \begin{pmatrix}\the\cytoks\end{pmatrix}}
\Characterdirective{\tctestifx{,#1}{\addcytoks{&}}{\addcytoks{#1}}}
\begin{document}
\[
\matr{a, b}{c, d}
\]
\[
\matr[3]{a, b,c}{d, e, f}{g, h, i}
\]
\end{document}

enter image description here

OPTIONAL SINGLE ARGUMENT APPROACH

This allows any combination of rows and columns within a single argument with the syntax \matr{ a, b / c, d} Here, commas are taken a column separators and / tokens are taken as row separators:

\documentclass{article}
\usepackage{amsmath,tokcycle}
\newcommand\matr[1]{\tokcyclexpress{#1}%
  \begin{pmatrix}\the\cytoks\end{pmatrix}}
\Characterdirective{\tctestifx{,#1}{\addcytoks{&}}{%
  \tctestifx{/#1}{\addcytoks{\\}}{\addcytoks{#1}}}}
\begin{document}
\[
\matr{a, b / c, d}
\]
\[
\matr{a, b,c / d, e, f/ g, h, i}
\]
\end{document}
5

A solution without any packages that is based on two fast loops to replace , with & and ; with \\ (so the syntax is the same as in @wipet's answer, but the execution is marginally faster, and it has no problems with braced groups, e.g., \matr{\mathbf{stuff},b;c,d} works as intended). To change to other parsing tokens than , and ; just swap out these two in every definition...

Also, I separated the parsing macro from the pmatrix, so that you could also use other matrix/tabular like enviroments (e.g., \begin{tabular}{cc}\matrinp{a,b;c,d}\end{tabular} would work as well).

\documentclass[]{article}

\usepackage[]{amsmath}

\makeatletter
\newcommand\matr[1]
  {%
    \begin{pmatrix}
      \matrinp{#1}%
    \end{pmatrix}
  }
\newcommand\matrinp[1]
  {%
    \expandafter\@firstofone\expandafter
      {%
        \romannumeral
        \matr@commas
          \matr@nil#1\matr@mark
          \matr@stop\matr@commas
          ,\matr@stop\matr@commas@done
      }%
  }
\long\def\matr@commas#1,#2\matr@stop#3{#3#1&#2\matr@stop#3}
\long\def\matr@commas@done#1\matr@stop#2\matr@commas@done
  {\matr@semicolon#1\matr@stop\matr@semicolon;\matr@stop\matr@done}
\long\def\matr@semicolon#1;#2\matr@stop#3{#3#1\\#2\matr@stop#3}
\long\def\matr@done#1\matr@mark#2\matr@done{\expandafter\z@\@gobble#1}
\makeatother

\begin{document}
\[
  \matr{a,b;c,d}\ne\matr{1,2,3;4,5,6;7,8,9;10,11,12}
\]
\end{document}
2

A little bit late to the party, but for the sake of variety, here's a LuaLaTeX-based solution. Regarding input syntax, I make the assumption that , is used as the separator between cells in a given row, while ; is used as the separator between rows.

enter image description here

\documentclass{article}
\usepackage{amsmath} % for 'pmatrix' environment
\usepackage{luacode} % for '\luaexec' macro

\luaexec{
    function matr ( s ) 
       s = s:gsub ( ";" , "\\\\" )
       s = s:gsub ( "," , "&" )
       tex.sprint ( "\\begin{pmatrix}" .. s .. "\\end{pmatrix}" )
    end
}
\newcommand\matr[1]{\directlua{ matr ( "#1" ) }}

\begin{document}
$\matr{ a, b ; c, d  }$
\end{document}
1

If you are a Emacs user, such a command already exists. You just type (for example)

\[ [[a b][c d]]\]

and when the point is on this formula, call the Calc-embedded command (C-x * e) . Emacs immediately returns:

\[ \begin{pmatrix} a & b \\ c & d \end{pmatrix}\]

As a bonus, Calc allows you to perform many matrix operations.

You have to call again Calc-embedded to return to normal latex-mode.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.