Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

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?

share|improve this question
add comment

1 Answer

up vote 15 down vote accepted

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.

share|improve this answer
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
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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