4

Quick summary: \text can be used to ensure proper scaling with respect to the correct math style. When exactly should one use it for that purpose? What need is there for nested invocations of \text for that purpose?


amsmath's \text includes \mathchoice, which people may have encountered in the form of \mathpalette.

When one might want to use \text is explained here. An advanced use case for \text is to make sure that text within some sort of text box embedded within math mode scales correctly. A concrete example is my definition of a 180°-rotated iota (), which one can use to denote a uniqueness selector (here \trnupiota):

\documentclass{article}
\usepackage{upgreek} % for \upiota
\usepackage{rotating} % for \rotatebox
\usepackage{amsmath} % for \text
\usepackage{accsupp} % for the right Unicode codepoint

\newcommand*{\trnupiota}{\mathord{%
  \BeginAccSupp{method=hex,unicode,ActualText=2129}%
    \text{\raisebox{\depth}{\rotatebox{180}{\(\upiota\)}}}% % with \text
  \EndAccSupp{}}}
\newcommand*{\trnupiotaNoText}{\mathord{%
  \BeginAccSupp{method=hex,unicode,ActualText=2129}%
    \raisebox{\depth}{\rotatebox{180}{\(\upiota\)}}}% % without \text
  \EndAccSupp{}}


\begin{document}

\(\trnupiota x \,(x \ge 0 \wedge x^{2} = 2)\)
  % denotes the square root of 2, which is by convention non-negative

\(\trnupiota + a_{\trnupiota + a_{\trnupiota}}\)
  % scales correctly

\(\trnupiotaNoText + a_{\trnupiotaNoText + a_{\trnupiotaNoText}}\)
  % doesn't scale correctly

\end{document}

(One may also use an ordinary iota: ι; conventions differ.) The entire first line denotes "the unique x which is non-negative and equals 2 if squared":

uniqueness selector

As one can see, the \trnupiota scales correctly in the different math styles, while the \text-less \trnupiotaNoText doesn't.

As explained in the comment thread to the answer linked above, \text can be slow, especially when it is nested: the relevant material is typeset 4 times (so the time for that material is quadrupled). The 4-fold increase in compilation time normally affects only tiny formula chunks, but it would be good to know a few rules about when we can safely not use \text.

We also know (this is explained in the same comment thread) that, when amstext or amsmath is loaded, the following text macros already include the mechanics of \text: \textrm, \textsf, \texttt, \textnormal, \textbf, \textmd, \textit, \textsl, \textsc, \textup, \emph. That is, for those we don't need an additional \text around their invocations.

Let's figure out when we truly need \text within math mode. In my example, \rotatebox necessitates \text. The frequent box \raisebox necessitates \text. The text macros in the previous paragraph already include \text; an additional \text would be a waste of computing resources. But what about constructs like the following?

  • \raise0.5ex\hbox{MATERIAL}
  • I have a macro defined as \mathbin{\text{\ooalign{...\raise0.1ex\hbox{\(...\raisebox{...}{\scalebox{...}{\(MATERIAL\)}}...\)}...}}}. (Don't ask why; it's about my use of \ooalign and also consistency in between definitions.) The first use of \(...\) in my macro effectively creates a \textstyle (independent of what the outermost math style in which the macro is called is in; is that right?), and therefore the following \raisebox causes no problems and doesn't necessitate another \text?

How can one characterize the contexts in which such use of \text within math mode is needed? I'm looking for an answer along the lines of "all boxes which are based on the TeX primitives X, Y, Z, if they are within non-\textstyle math mode"? What else is there to know?

  • I don't think it is needed, as it really depends on your use case. And as you mentioned, what is really slow in terms of computational time nowadays? – Werner Apr 20 '14 at 5:02
  • @Werner It depends on whether the text within a math-style-shielding box is intended to depend on the outer math style. But there are a couple of implicit questions in my writeup. Which boxes or other scoping elements block the math style? Does \(...\) always produce a \textstyle? Surely some insightful things can be said. This is also meant to be useful to a true beginner. – Lover of Structure Apr 20 '14 at 5:15
3

I agree that the concern for nested \mathchoices is real (I've seen cases that don't involve \text where it is significant, see, for example, Serious problem with \widebar, and the "important note" suffixed to the answer).

But rather than asking the question, "when do I 'need' \text?", I am looking at it as "how can I make \text work for me? In my MWE, the approach I propose is in the preamble, while the code redefinitions below the \hrulefill are purely for diagnostic examinations of the problem.

What I have found useful, when I suspect that \mathchoice nesting is causing a slowdown in compilation, is to develop (at the user end of the macro) a means to locally "fix" the mathstyle, and thus avoid the \mathchoice expansion. The underlying definition (in this case, \trnupiota) must remain general, able to handle any mathstyle. But the instances of its use are, by the end-user, usually known as to what the mathstyle will be for that instance. In those cases, and only when compilation speed is an issue, it can be useful to provide the end user a short-circuit on the \mathchoice.

So, for the case of \text, I introduce \Dtext, \Ttext, \Stext, and \stext to force behavior in display, text, script, or scriptscript styles, through a local redefinition of \mathchoice.

The way I implement that in your \trnupiota definition is to use an optional argument. Left blank, the regular \text is called. But with options of [D], [T], [S], or[s], the optional versions of \text are called upon.


After the \hrulefill in the MWE, I diagnostically redefine \mathchoice to count how many boxes are being made, before downselecting the final box to typeset. As is demonstrated, every time you can fix in advance the mathstyle for a particular invocation of \text (which is often known from the context of the problem), the number of boxes created for that invocation drops from 4 to 1.

\documentclass{article}
\usepackage{upgreek} % for \upiota
\usepackage{rotating} % for \rotatebox
\usepackage{amsmath} % for \text
\usepackage{accsupp} % for the right Unicode codepoint

\newcommand*{\trnupiota}{\mathord{%
  \BeginAccSupp{method=hex,unicode,ActualText=2129}%
    \text{\raisebox{\depth}{\rotatebox{180}{\(\upiota\)}}}% % with \text
  \EndAccSupp{}}}

\def\Dtext#1{{\renewcommand\mathchoice[4]{##1}\text{#1}}}% FORCE \displaystyle
\def\Ttext#1{{\renewcommand\mathchoice[4]{##2}\text{#1}}}% FORCE \textstyle
\def\Stext#1{{\renewcommand\mathchoice[4]{##3}\text{#1}}}% FORCE \scriptstyle
\def\stext#1{{\renewcommand\mathchoice[4]{##4}\text{#1}}}% FORCE \scriptscriptstyle

\begin{document}

\(\trnupiota x \,(x \ge 0 \wedge x^{2} = 2)\)
  % denotes the square root of 2, which is by convention non-negative

\(\trnupiota + a_{\trnupiota + a_{\trnupiota}}\)
  % scales correctly

The following redefinition of the macro \verb|\trnupiota| will allow an 
optional  argument D, T, S, or s to force the mathstyle of \verb|\text|, 
thus saving on the inefficiency of \verb|\mathchoice|.

\renewcommand*{\trnupiota}[1][]{\mathord{%
  \BeginAccSupp{method=hex,unicode,ActualText=2129}%
    \csname#1text\endcsname%
    {\raisebox{\depth}{\rotatebox{180}{\(\upiota\)}}}% % with \text
  \EndAccSupp{}}}

\(\trnupiota[D] + a_{\trnupiota[S] + a_{\trnupiota[s]}}\)
  % scales correctly

\hrulefill

To see how this works, let's have \verb|\mathchoice| count the boxes.

\let\svmathchoice\mathchoice
\newcounter{bxcnt}
\renewcommand\mathchoice[4]{\svmathchoice%
  {\stepcounter{bxcnt}#1}%
  {\stepcounter{bxcnt}#2}%
  {\stepcounter{bxcnt}#3}%
  {\stepcounter{bxcnt}#4}%
}
\def\Dtext#1{{\renewcommand\mathchoice[4]{\stepcounter{bxcnt}##1}\text{#1}}}
\def\Ttext#1{{\renewcommand\mathchoice[4]{\stepcounter{bxcnt}##2}\text{#1}}}
\def\Stext#1{{\renewcommand\mathchoice[4]{\stepcounter{bxcnt}##3}\text{#1}}}
\def\stext#1{{\renewcommand\mathchoice[4]{\stepcounter{bxcnt}##4}\text{#1}}} 
\newcommand\boxcount{\par\thebxcnt\ mathchoice boxes made\setcounter{bxcnt}{0}}


\(\trnupiota + a_{\trnupiota + a_{\trnupiota}}\)
  % scales correctly
\boxcount

\(\trnupiota + a_{\trnupiota + a_{\trnupiota[s]}}\)
\boxcount

\(\trnupiota + a_{\trnupiota[S] + a_{\trnupiota[s]}}\)
\boxcount

\(\trnupiota[D] + a_{\trnupiota[S] + a_{\trnupiota[s]}}\)
\boxcount
\end{document}

enter image description here

In the first example after the \hrulefill, each of the three \trnupiota instances are boxed four times each resulting in 4+4+4=12 boxes. When one of the instances is hardwired in the 2nd example, the number of boxes is 4+4+1=9 boxes; For the 3rd example, it is 4+1+1=6 boxes; and in the last example, it is 1+1+1=3 boxes made.

1

As the name of the command implies, \text is intended for natural language text that needs to adapt to the current math context. using it as suggested here as a purely math context is misusing the command which makes it rather inefficient and not guaranteed to produce the correct font size.

If you use \text{hello $x+y$} in the context of a superscript then you get the setting that latex would use for \scriptsize hello $x+y$ this means that (the first time it is used) LaTeX has the cost of setting up all the math fonts for that text size, but more importantly $x+y$ will be set at the math \textfont size for the text size \scriptsize. Both the size of \scriptsize, and the size of the math fonts declared for that text font size are arbitrary sizes set by the class in use and may not be the same same size as \scriptfont in the current text size.

In a case where you need to set hello with text formatting at a size determined by the outer math expression then \text is a good option.

If however you just want to use a box containing math set at the current \scriptfont size it is better to use \mathchoice, passing in the current style, so\scriptstyle` in superscripts.

The macro \mathpalette in latex, inherited from plain, is designed fro exactly this use. It calls the \mathcoice primitive, to a supplied macro that is passed the current style as first argument. The second argument is normally the user-supplied argument such as the argument of \phantom or \root but here the command being defined takes no argument, so I pass in {}

enter image description here

\documentclass{article}
\usepackage{upgreek} % for \upiota
\usepackage{rotating} % for \rotatebox
\usepackage{amsmath} % for \text
\usepackage{accsupp} % for the right Unicode codepoint

\newcommand*{\trnupiota}{\mathord{%
  \BeginAccSupp{method=hex,unicode,ActualText=2129}%
    \text{\raisebox{\depth}{\rotatebox{180}{\(\upiota\)}}}% % with \text
  \EndAccSupp{}}}
\newcommand*{\trnupiotaNoText}{\mathord{%
  \BeginAccSupp{method=hex,unicode,ActualText=2129}%
    \raisebox{\depth}{\rotatebox{180}{\(\upiota\)}}}% % without \text
  \EndAccSupp{}}
\newcommand*{\trnupiotamp}{\mathord{%
  \BeginAccSupp{method=hex,unicode,ActualText=2129}%
    \mathpalette\trnupiotampx{}%
  \EndAccSupp{}}}

\newcommand*\trnupiotampx[1]{\raisebox{\depth}{\rotatebox{180}{\(#1\upiota\)}}}% % with \text
\begin{document}

\(\trnupiota x \,(x \ge 0 \wedge x^{2} = 2)\)
  % denotes the square root of 2, which is by convention non-negative

\(\trnupiota + a_{\trnupiota + a_{\trnupiota}}\)
  % scales correctly

\(\trnupiotaNoText + a_{\trnupiotaNoText + a_{\trnupiotaNoText}}\)
  % doesn't scale correctly

\(\trnupiotamp + a_{\trnupiota + a_{\trnupiota}}\)
  % scales even more correctly

\end{document}

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.