18

I’m struggling with getting \ifmmode to work correctly when used inside an array environment which is inside a displaymath environment.

Here is a minimal example:

\documentclass{article}

\newcommand{\signal}[1]{%
  \ifmmode
    1#1
  \else
    2$#1$
  \fi
}

\begin{document}
\begin{displaymath}
  \begin{array}{cc}
    \signal{a} \signal{b} & \signal{c} \signal{d} \\
  \end{array}
\end{displaymath}
\end{document}

This example generates the following output:

2a 1 _b_ 2c 1 _d_

Why doesn’t all invokations of \signal detect math-mode?

22

At the start of an alignment cell, TeX is looking for an \omit or \noalign, rather than being in math mode. The way to deal with this is to insert a \relax.

\documentclass{article}

\newcommand{\signal}[1]{%
  \relax
  \ifmmode
    1#1
  \else
    2$#1$
  \fi
}

\begin{document}
\begin{displaymath}
  \begin{array}{cc}
    \signal{a} \signal{b} & \signal{c} \signal{d} \\
  \end{array}
\end{displaymath}
\end{document}

Now, the issue with that is that it will mess up kerning if used in other places (it puts a \relax in even when it's not needed). In some LaTeX3 work, we've experimented with an approach to 'pick up' the alignment cell using e-TeX. At one point we had something very elaborate to test for this

\documentclass{article}

\newcommand{\signal}[1]{%
  \ifnum\currentgrouptype = 6 %
    \ifnum\lastnodetype = 0 %
    \else
      \ifnum\lastnodetype = 7 %
      \else
        \relax
      \fi
    \fi
  \fi
  \ifmmode
    1#1
  \else
    2$#1$
  \fi
}

\begin{document}
\begin{displaymath}
  \begin{array}{cc}
    \signal{a} \signal{b} & \signal{c} \signal{d} \\
  \end{array}
\end{displaymath}
\end{document}

This uses the various diagnostics from e-TeX to pick up the start of a cell. However, this is really not a good idea as it pretends to be expandable but does insert \relax: not expandable! A much cleaner approach is to use \protected

\documentclass{article}

\protected\def\signal#1{%
  \ifmmode
    1#1
  \else
    2$#1$
  \fi
}

\begin{document}
\begin{displaymath}
  \begin{array}{cc}
    \signal{a} \signal{b} & \signal{c} \signal{d} \\
  \end{array}
\end{displaymath}
\end{document}

as e-TeX does not expand protected macros here.

  • 1
    Joseph, we're not in math mode: that will be started when TeX inserts the u part for the cell (in the terminology of the TeXbook) and ended with the v part. Saying \omit won't give math mode, for example; LaTeX takes precautions to add again the $ characters when \multicolumn is used in an array. But this is almost splitting hairs, I guess. :) – egreg Sep 5 '11 at 21:41

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.