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.

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?

share|improve this question
4  
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
2  
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
add comment

4 Answers

up vote 9 down vote accepted

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

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.

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

Yes, you have \mathchoice

\documentclass{article}

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

\begin{document}
\[
 \mathtest x^{\mathtest^{\mathtest}}
\]

\(
  \mathtest
\)

\end{document}
share|improve this answer
    
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
add comment

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}
share|improve this answer
    
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
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.