# Is there a test for the different styles inside maths mode?

Is there a test for the different styles within maths mode? What I really want is to be able to save the current style to reinvoke it later on, but a \if along the lines of \ifmmode would work just as well.

In the specific example, I want to measure how big something will be when displayed in maths mode, so I do:

\settoheight{\mathheight}{some bit of maths}


except that it complains because the some bit of maths gets put in a box and measured, and the box doesn't know that it's maths. So instead I put:

\settoheight{\mathheight}{$$some bit of maths$$}


except that then I get the wrong answer if this is used in displayed maths. So ideally, I want:

\ifdisplaystyle
\let\currentstyle\displaystyle
\else
\iftextstyle
\let\currentstyle\textstyle
...
\fi
\fi
\settoheight{\mathheight}{$$\currentstyle some bit of maths$$}


and then I'll be happy.

Is there such a test?

Okay, so \mathchoice is clearly the way to go (thanks Martin!), but its behaviour is a little odd and since I want to use it to define a macro depending on which mode I'm in, this oddity is quite important. Here's the code:

\newcommand{\mathtest}{%
\gdef\name{a}%
\mathchoice{%
\name
\gdef\name{b}%
}{%
\name
\gdef\name{c}%
}{%
\name
\gdef\name{d}%
}{%
\name
\gdef\name{e}%
}%
\name}

$\mathtest$


If \mathchoice behaved like \if, this ought to print ab. But it prints ae. All the options to \mathchoice get processed (which makes me wonder a bit how it works, but that's by-the-by).

So, is there an obvious way to make \mathchoice behave a little more like \if?

-
TeX never knows what is the current math style. This is because of the \over, \atop, etc macros. As you discovered, \mathchoice processes all 4 variants and use the appropriate one once the end of the math list is reached. The mathstyle gets around this limitation by assuming that a LaTeX user will not use \over, \atop, etc in the text. These are used behind the scenes in amsmath, so mathstyle redefines the amsmath macros \frac, \binom, etc. That way, it is able to keep track of the current mathstyle. Of course, this will fail if you use an explicit \over, \atop, etc in your document. –  Aditya Aug 6 '10 at 18:48
Also, normally you can work around the limitation of mathchoice by defining your macros accordingly. For example, definition that you are using can also be written as \def\mathtest {\gdef\name{a} \name \gdef\name{\mathchoice{b}{c}{d}{e}} \name} which gives the correct result. –  Aditya Aug 6 '10 at 18:56
@adityam: thanks for the comments. Unfortunately, the implementation of the mathstyle package doesn't work for $$..$$ making it not work for what I want (which is closer to the first example than the second - that was to show that \mathchoice didn't behave how I wanted). –  Andrew Stacey Aug 6 '10 at 19:04
For the behaviour of \mathchoice, see TeX by Topic: 'The primitive command \mathchoice{D}{T}{S}{SS}lets the user specify four variants of a formula for the four styles. TeX constructs all four and inserts the appropriate one.' –  Joseph Wright Aug 7 '10 at 5:54

Lets call such a macro mathsettoheight. I'll keep things simple and define only mathsettoheight (and not mathsettowidth and mathsettodepth).

IIUC, you want this macro to behave like

\mathsettoheight{\dimen}{content}


First, lets consider a simplified version of \settoheight

\def\settoheight#1#2%
{\setbox\@tempboxa\hbox{{#2}}%
#1=\ht\@temboxa
\setbox\@temboxa\box\voidb@x}


The only change that we need to do in \mathsettoheight is to set the box correctly. Instead of

\hbox{#2}


use

\hbox{$\mathpalette{}{#2}$}


\mathpalette is a shortcut used for convenience and is usually defined by all macro packages (plain TeX, LaTeX, ConTeXt) as

\def\mathpalette#1#2{%
\mathchoice
{#1\displaystyle{#2}}%
{#1\textstyle{#2}}%
{#1\scriptstyle{#2}}%
{#1\scriptscriptstyle{#2}}}


A minor improvement is to use

\hbox{$\m@th\mathpalette{}{#2}$}


where \m@th sets the math surround to zero (useful if you are interested in the width of the content).

And thats it. The complete definition with you example is

\documentclass{amsart}

\makeatletter

\def\mathsettoheight#1#2%
{\setbox\@tempboxa\hbox{{#2}}%
#1=\ht\@temboxa
\setbox\@temboxa\box\voidb@x}

\def\mathsettoheight#1#2%
{\setbox\@tempboxa\hbox{$\m@th\mathpalette{}{#2}$}%
#1=\ht\@tempboxa
\setbox\@tempboxa\box\voidb@x}

\makeatother

% Test case

\newlength\mathheight
\newcommand*\intheight{%
\mathsettoheight{\mathheight}{\int}
\the\mathheight
}

\begin{document}

$\intheight$

\begin{align}
\text{displaystyle}&={\displaystyle\text{\intheight}}\\
\text{textstyle}&={\textstyle\text{\intheight}} \\
\text{scriptstyle}&={\scriptstyle\text{\intheight}} \\
\text{scriptscriptstyle}&={\scriptscriptstyle\text{\intheight}}
\end{align}

{\obeylines
\text{displaystyle}= $\displaystyle\text{\intheight}$\\
\text{textstyle}=$\textstyle\text{\intheight}$ \\
\text{scriptstyle}=$\scriptstyle\text{\intheight}$ \\
\text{scriptscriptstyle}=$\scriptscriptstyle\text{\intheight}$
\endgraf}

\end{document}

-

This answer will only apply to LuaTeX and LuaLaTeX, but your question was quite general, so ...

The luatex engine defines a primitive that allows you to query the current math style.

This primitive is called \mathstyle, and when the value is queried (after \ifnum, for example) it returns a number between -1 (not in math mode), 0 (display style), and 7 (cramped scriptscript style).

Luatex also defines four new primitives with \cramped.. prefix: \crampeddisplaystyle, \crampedtextstyle, \crampedscriptstyle, \crampedscriptscriptstyle. These are like their non-prefixed cousins (\displaystyle ... \scriptscriptstyle) except that they explicitly switch to one of the 'cramped' math styles.

Finally, there is the new primitive \Ustack, that is to be used as a prefix for \over.. and \atop.. constructs (which is what commands like \frac and \binom eventually expand into), like so

\Ustack {a \over b}


If you do not do this, \mathstyle will return the wrong value in the initial part of {... \over ...}, as explained by Aditya.

All combined together, these primitives allow code like this:

\ifnum\mathstyle=\textstyle
\message{normal text style}
\else \ifnum\mathstyle=\crampedtextstyle
\message{cramped text style}
\fi \fi


and this:

\def\cramped#1% switch the argument to a cramped math style
{{\ifcase\mathstyle
\crampeddisplaystyle      \or \or % 0 -> 1
\crampedtextstyle         \or \or % 2 -> 3
\crampedscriptstyle       \or \or % 4 -> 5
\crampedscriptscriptstyle \fi     % 6 -> 7
#1}}


and even allow you to define a version of \mathchoice that does not typeset everything four times:

\def\mathchoice#1#2#3#4%
{{\ifcase\mathstyle
#1\or #1\or
#2\or #2\or
#3\or #2\or
#4\or #4\else #2\fi}}


All this can currently only be used if your underlying engine is luatex, but it is hoped that this extension will eventually become supported by xetex as well.

-
Thanks. I did not know the \UStack macro. I believe that \genfrac in ConTeXt MkIV needs to be adapted to use it. –  Aditya Aug 7 '10 at 13:32

Yes, you have \mathchoice

\documentclass{article}

\newcommand\mathtest{%
\mathchoice
{displaystyle}
{text style}
{scriptstyle}
{scriptscriptstyle}
}

\begin{document}
$\mathtest x^{\mathtest^{\mathtest}}$

$$\mathtest$$

\end{document}

-
Clearly that's part of the answer, but it doesn't work quite how I expected! I've edited my question to focus on this (since describing the behaviour is a little long for a comment). –  Andrew Stacey Aug 6 '10 at 15:12

Try using package mathstyle http://ctan.org/pkg/mathstyle. This solution is more along the lines of the original question.

\documentclass{article}
\usepackage{mathtools}
\usepackage{mathstyle}
\usepackage{calc}

\newlength\mathheight
\newcommand*\intheight{%
\settototalheight{\mathheight}{$\currentmathstyle\int$}
\the\mathheight
}

\begin{document}

\begin{align}
\text{displaystyle}&={\displaystyle\text{\intheight}}\\
\text{textstyle}&={\textstyle\text{\intheight}} \\
\text{scriptstyle}&={\scriptstyle\text{\intheight}} \\
\text{scriptscriptstyle}&={\scriptscriptstyle\text{\intheight}}
\end{align}

\end{document}

-
So close! And yet so far. Looking at the style file, mathstyle works by hooking in to \displaystyle etc. But that means that if they don't get called, then it defaults to \displaystyle. Fine for displayed maths, but it does mean that $$\text{\intheight}$$ gives the wrong height. –  Andrew Stacey Aug 6 '10 at 18:51
You are right, but I don't have a fix right now. –  Martin Heller Aug 7 '10 at 0:50