6

I'd like to define a command that defines a vector based on whether it's in display or inline math mode. I've tried this so far, but it hasn't worked:

\newcommand{\ve}[1]{\ensuremath{%
    \mathchoice{%
        \begin{pmatrix}%
            \StrSubstitute{#1}{,}{\\}%
        \end{pmatrix}%
    }{%
        \left(\begin{smallmatrix}%
            \StrSubstitute{#1}{,}{\\}%
        \end{smallmatrix}\right)%
    }{#1}{#1}%
}}

I'd like to get $$\ve{1,2,x}$$ to expand to

\begin{pmatrix}
    1\\2\\x
\end{pmatrix}

and $\ve{1,2,x}$ to expand to

\left(\begin{smallmatrix}
    1\\2\\x
\end{smallmatrix}\right)
3
  • Are you willing and able to entertain a LuaLaTeX-based solution, or does it have to work with pdfLaTeX? – Mico Jan 19 at 7:22
  • Please also indicate how or where \StrSubstitute is defined. – Mico Jan 19 at 7:23
  • @Mico I'd like to stick to PDFLaTeX. \StrSubstitute is defined in the xstrings package (or something like that). – Raymo111 Jan 19 at 7:26
7

Distinguishing inline and display math is different from distinguishing \displaystyle from \textstyle and can be tricky, since the align-like environments of amsmath use internally $\displaystyle...$. Your definition with \ensuremath will furthermore always use \textstyle if you call the macro outside of math mode. In my (of course questionable) opinion \ensuremath shouldn't be used unless the life of sweet kittens and fluffy bunnies depends on it; and also in that case it shouldn't be used lightly.

Luckily, amsmath provides a boolean \if@display, so we can (ab)use it. I'd load mathtools, an extension to amsmath, which among other things defines already a psmallmatrix environment.

\documentclass{article}

\usepackage{mathtools}% loads amsmath

\makeatletter

\newcommand*{\ve}[1]{%
   \begingroup
   \if@display
      \def\@tempa{{pmatrix}}
   \else
      \def\@tempa{{psmallmatrix}}
   \fi
   \expandafter\begin\@tempa
   \@ve#1,\@@nil,
   \expandafter\end\@tempa
   \endgroup
}
   
\def\@ve#1,{\ifx\@@nil#1\else#1\\\expandafter\@ve\fi}

\makeatother

\begin{document}

\hsize=4cm % for the snapshot

\[
\ve{a}\ve{a,b}\ve{a,b,c}
\]

\begin{align*}
\ve{a}\ve{a,b}\ve{a,b,c}
\end{align*}

$\ve{a}\ve{a,b}\ve{a,b,c}$

\end{document}

enter image description here

EDIT A version which like egreg's answer uses \mathchoice. I've added for completeness also a row vector. This required some more trickery, becase there is no harm in adding \\ at the end of a column vector (like my first coded did) but it goes wrong when you add a & at the end of a row.

\documentclass{article}

\usepackage{mathtools}

\makeatletter

\newcommand*{\cvector}[1]{\cr@vector{\\}{#1}}
\newcommand*{\rvector}[1]{\cr@vector{&}{#1}}

\newcommand*{\cr@vector}[2]{%
   \mathchoice{\cr@@vector{#1}{#2}{}}%
              {\cr@@vector{#1}{#2}{small}}%
              {\cr@@vector{#1}{#2}{small}}%
              {\cr@@vector{#1}{#2}{small}}%
}

\newcommand*{\cr@@vector}[3]{%
   \def\@tempa{\gdef\@tempa{#1}}% first time does nothing, afterwards it's \\ or &
   \def\@tempb##1,{\ifx\@@nil##1\else\@tempa##1\expandafter\@tempb\fi}%
   \begin{p#3matrix}
   \@tempb#2,\@@nil,
   \end{p#3matrix}
}

\makeatother


\begin{document}

\hsize=5cm % for smaller snapshot

Display
\begin{align*}
\rvector{a,b,c} \cvector{a,b,c}
= \frac{\rvector{x,y} \cvector{u,v}}{\rvector{1,2,3}\cvector{4,5,6}}
\end{align*}
and inline $\rvector{a,b,c}$, $\cvector{a,b,c,d,e}$

\end{document}

enter image description here

One could use \mathchoice directly in the definition of \cvector and \rvector and spare one intermediate macro but I find the code would be less readable.

12
  • Thanks @campa! This works perfectly, is extremely readable, and doesn't involve importing extra packages. The \psmallmatrix is genius as well! – Raymo111 Jan 19 at 17:29
  • 1
    @Raymo111 Readability might be one thing, but as far as egreg's answer is concerned consider that (1) xparse is a rather standard package and even for an older distribution where it's not part of the format you might already have it (maybe you don't load it directly but there are many common packages which do) and (2) my solution will give you larger matrices also e.g. in fractions, while egreg's will give you smaller matrices. Not that anybody in their sane mind would type something like that, but keep the difference in mind. – campa Jan 19 at 17:43
  • I get that xparse is standard, but if I'm sharing \ve with friends I don't really want to make them import xparse if they're not on the latest Tex distribution. What do you mean by larger/smaller matrices? – Raymo111 Jan 19 at 18:01
  • @Raymo111 Try using the \ve macro in an argument of \frac. My version will stay large; egreg's will become smaller (which is the sensible behaviour). – campa Jan 19 at 18:03
  • 1
    @Raymo111 LOL, yes, I know what is wrong :-D In the definition of \@ve there is \ifx#1\relax, and in this case this becomes \ifx((a))\relax so the two ( are compared and they are of course equal... I can't test now but quick fix: use \ifx\relax#1 instead. I'll see tomorrow if there are more pitfalls. – campa Feb 4 at 19:23
7

The idea is good. Not so \ensuremath, of course.

\documentclass[twocolumn]{article} % twocolumn is just to get a smaller picture
\usepackage{amsmath}

\ExplSyntaxOn
\NewDocumentCommand{\ve}{m}
 {
  \mathchoice
    {\raymo_ve_display:n {#1}}
    {\raymo_ve_inline:n {#1}}
    {\raymo_ve_inline:n {#1}}
    {\raymo_ve_inline:n {#1}}
 }
\cs_new_protected:Nn \__raymo_ve_make:n
 {
  \seq_set_split:Nnn \l__raymo_ve_body_seq { , } { #1 }
  \seq_use:Nn \l__raymo_ve_body_seq { \\ }
 }
\cs_new_protected:Nn \raymo_ve_display:n
 {
  \begin{pmatrix}
  \__raymo_ve_make:n { #1 }
  \end{pmatrix}
 }
\cs_new_protected:Nn \raymo_ve_inline:n
 {
  \left(\begin{smallmatrix}
  \__raymo_ve_make:n { #1 }
  \end{smallmatrix}\right)
 }
\ExplSyntaxOff

\begin{document}

This is inline $\ve{1,2,x}$ and there is also a display
\[
\ve{1,2,x}
\]

\end{document}

If you're not running the latest LaTeX kernel (2020-10-01), you need \usepackage{xparse}.

I find expl3 much better than xstrings.

enter image description here

“Optimized” code for also supporting row vectors:

\documentclass[twocolumn]{article} % twocolumn is just to get a smaller picture
\usepackage{amsmath,mathtools}

\ExplSyntaxOn
\NewDocumentCommand{\gve}{mm}
 {% #1 = c or r
  \mathchoice
    {\raymo_ve_build:nnn {#1}{#2}{}}
    {\raymo_ve_build:nnn {#1}{#2}{small}}
    {\raymo_ve_build:nnn {#1}{#2}{small}}
    {\raymo_ve_build:nnn {#1}{#2}{small}}
 }
\NewDocumentCommand{\ve}{m}{\gve{c}{#1}}
\NewDocumentCommand{\rve}{m}{\gve{r}{#1}}

\cs_new_protected:Nn \__raymo_ve_make:nn
 {
  \seq_set_split:Nnn \l__raymo_ve_body_seq { , } { #2 }
  \seq_use:Nn \l__raymo_ve_body_seq { \str_case:nn {#1}{{c}{\\}{r}{&}} }
 }
\cs_new_protected:Nn \raymo_ve_build:nnn
 {
  \begin{p#3matrix}
  \__raymo_ve_make:nn { #1 } { #2 }
  \end{p#3matrix}
 }
\ExplSyntaxOff

\begin{document}

This is inline $\ve{1,2,x}\rve{1,2,x}$ and there is also a display
\[
\ve{1,2,x}\rve{1,2,x}
\]

\end{document}

enter image description here

1
  • Thanks for a working answer! Upvoted, though I must accept @campa's answer as it doesn't involve using xparse and is overall shorter and easier to read. – Raymo111 Jan 19 at 17:28

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.