7

I am using underarrows from amsmath to decorate messages with their direction, as in $\underleftarrow{\mathsf{msg}}$ () and $\underrightarrow{\mathsf{msg}}$ (). I am looking for a better underarrow, in several senses:

  • Smaller depth of entire construction. The underarrows add depth to the message names. I often use these in multiline constructions, such as align*, and the extra depth affects the apparent spacing. For example, compare the following versions that use underarrows and underlines.
    enter image description here
    Using \smash[b] does eliminate the added depth but also, for some reason, shifts the arrow down:
    enter image description here
  • Shorter minimum arrow length. With the standard underarrows, message names that consist of a single letter are overpowered by the arrow. For example, $\underleftarrow{\mathsf{p}}$ produces enter image description here.
  • Smaller arrow head. To my eye, the arrow head looks too large for my use case.

Are there left and right underarrows that better meet these three criteria? Is there a way that I can construct my own underarrows?

Here is a MWE, in case it is useful:

\documentclass{article}
\usepackage{amsmath}
\begin{document}
\begin{equation*}
  \begin{aligned}[t]
    &\mathsf{bit_0} \bullet \underleftarrow{\mathsf{inc}} \\
    &\mathsf{bit_1} \bullet \underleftarrow{\mathsf{p}}
  \end{aligned}\quad
  \begin{aligned}[t]
    &\mathsf{bit_0} \bullet \smash[b]{\underleftarrow{\mathsf{inc}}} \\
    &\mathsf{bit_1} \bullet \smash[b]{\underleftarrow{\mathsf{p}}}
  \end{aligned}
\end{equation*}
\end{document}
  • 1
    clearly the option [b] on the \smash is a bug, and i'm adding it to our list. however, since there are other parts of the line that determine the height, you can use an unadorned \smash just around the \underrightarrow{\mathsf{inc}} and this won't affect the positioning of the arrow. sorry, i have no suggestions just now regarding shorter arrows or smaller arrowheads. – barbara beeton Jul 30 '13 at 18:42
  • Is using TikZ a valid solution? Could you add an MWE? – Qrrbrbirlbel Jul 31 '13 at 1:00
  • @Qrrbrbirlbel Yes, TikZ is a valid solution, I suppose; I hadn't thought of that. Thanks! I guess I have a slight preference for a non-TikZ solution, though, since I will be using this construction pervasively and would like to avoid slowing down compilation too much. – Henry DeYoung Jul 31 '13 at 14:30
3

I don’t know how much amsmath’s \underleftarrow slows the compilation down or how it would with TikZ, but here is a solution that uses PGF and avoids the parsing process of TikZ.

The proposed solution uses only one \pgfpicture which measured the under-arrowed math content after typesetting it in an box using

\edef\pgf@math@fam{\the\fam}%

and later

\sbox\pgfutil@tempboxa{$\fam\pgf@math@fam#1#2$}%

where the saved font setting is set again, combined with \mathpalette which forwards the current math style to \@pgfunderleftarrow.

The box’s width is stored in \pgfutil@tempdimb which is then used in drawing the line (where we have used \wd\pgfutil@tempboxa directly, too).

This makes it possible to let TeX typeset the math content as it is but also measure it as precise as possible. As I realized later, even the original \underleftarrow doesn’t kepp the math family font settings (like \mathsf) so maybe you want to change this again.

This \the\fam trick was provided by egreg in a chat message from 2013-07-31:

For a single symbl it should work.

It seems also to work for more than one symbol.


The original definition of the to arrow is

\pgfarrowsdeclare{to}{to}
{ … }{
  \pgfutil@tempdima=0.28pt%
  \advance\pgfutil@tempdima by.3\pgflinewidth%
  \pgfsetlinewidth{0.8\pgflinewidth}
  \pgfsetdash{}{+0pt}
  \pgfsetroundcap
  \pgfsetroundjoin
  \pgfpathmoveto{\pgfqpoint{-3\pgfutil@tempdima}{4\pgfutil@tempdima}}
  …
}

The important part is the setup of \pgfutil@tempdima as the y value of the \pgfpathmoveto coordinate is 4\pgfutil@tempdima which makes up the vertical height of the arrow. \pgfutil@tempdima in the definition of \@pgfunderleftarrow is used to calculate this height (we cannot extract it from some macro like the left and right extend).

To let the arrow arc touch the bottom of the math content we would use:

\pgfutil@tempdima=0.28pt%
\advance\pgfutil@tempdima by.3\pgflinewidth%
\pgfutil@tempdima-4\pgfutil@tempdima
\advance\pgfutil@tempdima-.4\pgflinewidth

The last line adds half the line width of the arrow line (which is set to 0.8\pgflinewidth).

So why did I do something differently, namely \pgfutil@tempdima=0.28pt% \advance\pgfutil@tempdima by.8\pgflinewidth% \pgfutil@tempdima-4\pgfutil@tempdima

Because I haven’t done it right (.5 instead of .4 of the line width added and before the multiplication of the factor 4), but it looks right.

Of course, you can change the factors and addition if you think it looks better.

The unstarred version of \pgfunderleftarrow doesn’t add any depth to the line (other than the depth of the math content itself). If this depth is needed (take a look at a \fraction), the starred version \pgfunderleftarrow* can be used.

Code

\documentclass{article}
\usepackage{amsmath}
\usepackage{pgf}
\makeatletter
\newcommand*{\pgfunderleftarrow}{%
  \@ifstar
    {\let\ifpgf@depth\iftrue\mathpalette\@pgfunderleftarrow}
    {\let\ifpgf@depth\iffalse\mathpalette\@pgfunderleftarrow}%
}
\newcommand*{\@pgfunderleftarrow}[2]{%
  #2%
  \edef\pgf@math@fam{\the\fam}%
  \pgfpicture
    \pgfsetbaseline{0pt}%                 % "baseline = 0pt"
    \pgf@relevantforpicturesizefalse      % "overlay"
    \pgfsetroundcap                       % "line cap = round"
    \pgfsetarrowsend{to}%                 % "arrows = -to"
    \pgfutil@tempdima=0.28pt%
    \advance\pgfutil@tempdima by.8\pgflinewidth%
    \pgfutil@tempdima-4\pgfutil@tempdima
    \sbox\pgfutil@tempboxa{$\m@th\fam\pgf@math@fam#1#2$}%
    \advance\pgfutil@tempdima-\dp\pgfutil@tempboxa
    \pgfutil@tempdimb\wd\pgfutil@tempboxa
    \pgfpathmoveto{\pgfqpoint{0pt}{\pgfutil@tempdima}}%
    \pgfpathlineto{\pgfqpoint{-\pgfutil@tempdimb}{\pgfutil@tempdima}}%
    \pgfusepath{stroke}%                  % "draw"
    \ifpgf@depth
      \pgf@relevantforpicturesizetrue
      \pgfpathmoveto{\pgfqpoint{0pt}{-\pgfutil@tempdimb}}%
      \pgfusepath{use as bounding box}%
    \fi
  \endpgfpicture
}
\makeatother
\begin{document}
\begin{gather*}
  \mathsf{bit_0} \bullet \underleftarrow{\mathsf{inc}} \\
  \mathsf{bit_1} \bullet \underleftarrow{\mathsf{p}}  \\
  \mathsf{bit_2} \bullet \underleftarrow{\mathsf{f}} \\
  \mathsf{bit_2} \bullet \mathsf{\underleftarrow{f}} \rlap{$\to$ \texttt{\char`\\mathsf} lost?}
\end{gather*}
\begin{gather*}
  \mathsf{bit_0} \bullet \pgfunderleftarrow{\mathsf{inc}} \bullet \mathsf{\pgfunderleftarrow{inc}}\\
  \mathsf{bit_1} \bullet \pgfunderleftarrow{\mathsf{p}} \bullet \mathsf{\pgfunderleftarrow{p}}\\
  \mathsf{bit_2} \bullet \pgfunderleftarrow{\mathsf{f}} \bullet \mathsf{\pgfunderleftarrow{f}}
\end{gather*}
\begin{equation*}
  \frac{\pgfunderleftarrow*{f}}{f} \neq \frac{\pgfunderleftarrow{f}}{f} \neq \frac{\underleftarrow{f}}{f}
\end{equation*}
\end{document}

Output

Original \underleftarrow (last line uses \mathsf{\pgfunderleftarrow{f}})

enter image description here

PGF version

enter image description here

  • Thanks, this works great! I'm trying to understand how the code works now. Can you explain the purpose of \pgfutil@tempdima=0.28pt\advance\pgfutil@tempdima by.8\pgflinewidth\pgfutil@tempdima-4\pgfutil@tempdima\pgfutil@tempdimb\pgfutil@tempdima? What are the values of \pgfutil@tempdima and \pgfutil@tempdimb when this code fragment finishes? Also, are these just magic constants that you determined empirically, or is there a special reason for this choice? Thanks again for your help! – Henry DeYoung Aug 18 '13 at 15:38
  • @HenryDeYoung The last \pgfutil@tempdimb\pgfutil@tempdima doesn’t do anything because \pgfutil@tempdimb is overwritten anyway. The calculation of \pgfutil@tempdima was taken from the definition of the to arrow but a little adjusted (not correctly but it looks good). I have updated my answer with some explanation. You can adjust the values, of course. – Qrrbrbirlbel Aug 19 '13 at 0:20
5

With this solution, I leave you a number of parameters to play with:

\arrowscale a multiplier on arrow-head size

\FPmul scalefactor on the arrow-shaft length scale (probably should stay =1)

\FPsub parameter is how much arrow-shaft length (non-dimensional) to subtract off, to leave room for arrow-head

\stackunder optional parameter is the gap between the text and the arrow.

I did not use a \mathrel around it, but that could be inserted into the definition, if you so wanted. You can place the argument in \scriptstyle and the arrow-shaft length will adjust. However, the arrowhead size will not shrink. Is that OK?

[EDITED code to condense it.]

\documentclass{article} 
\usepackage{stackengine}
\def\useanchorwidth{T}
\usepackage{scalerel}
\usepackage{fp}
\def\arrowscale{.5}% <---CAN PLAY WITH THIS VALUE
\def\clipeq{\scalebox{\arrowscale}{$\kern-1pt\mathrm{-}\kern-1pt$}}
\def\Lla{\scalebox{\arrowscale}{$\kern-1pt\leftarrow\kern-1pt$}}
\def\Lra{\scalebox{\arrowscale}{$\kern-1pt\rightarrow\kern-1pt$}}
\newcount\argwidth
\newcount\clipeqwidth
\savestack\tempstack{\clipeq}%
\clipeqwidth=\wd\tempstackcontent\relax
\newcommand\xarrow[2]{%
  \savestack\tempstack{$#1$}%
  \argwidth=\wd\tempstackcontent\relax%
  \FPdiv\scalefactor{\the\argwidth}{\the\clipeqwidth}%
  \FPmul\scalefactor{\scalefactor}{1}% <---CAN PLAY WITH THIS VALUE
  \FPsub\scalefactor{\scalefactor}{1.8}% <---CAN PLAY WITH THIS VALUE
  \FPmax\scalefactor{\scalefactor}{.05}%
  \stackunder[0.7pt]{$#1$}{$#2$}%
% CAN PLAY WITH ^
}
\newcommand\xrightarrow[1]{\xarrow{#1}{\hstretch{\scalefactor}{\clipeq}\Lra}}
\newcommand\xleftarrow[1]{\xarrow{#1}{\Lla\hstretch{\scalefactor}{\clipeq}}}
\parskip 1ex
\begin{document} 
$\xrightarrow{a}~~
\xleftarrow{a}$

$\xrightarrow{ab}~~
\xleftarrow{ab}$

$\xrightarrow{abc}~~
\xleftarrow{abc}$

$\xrightarrow{abcd}~~
\xleftarrow{abcd}$

$\xrightarrow{abcde}~~
\xleftarrow{abcde}$
\end{document}

enter image description here

Here are some results with \arrowscale set to 0.4, the \stackunder optional argument set to 0.4pt, and the \FPsub parameter set to 1.7:

enter image description here

2

This question was bumped up to the home page because it was edited as part of the site’s “\\ bug” cleanup, and I couldn’t refrain from remarking that the halloweenmath package (it’s not a joke, it does exists, and I am its author!) features, among several other mathematical symbols linked to the traditional Halloween-related iconography, also a “script” version of the over- and under-arrows provided by the amsmath package. The relevant commands are named \overscriptleftarrow, \overscriptrightarrow, \overscriptleftrightarrow, \underscriptleftarrow, \underscriptrightarrow, and \underscriptleftrightarrow. They are implemented by exactly the same mechanism as their larger counterparts, and therefore require nothing more than the original TeX by Knuth.

This is a simple code sample:

% My standard header for TeX.SX answers:
\documentclass[a4paper]{article} % To avoid confusion, let us explicitly 
                                 % declare the paper format.

\usepackage[T1]{fontenc}         % Not always necessary, but recommended.
% End of standard header.  What follows pertains to the problem at hand.

%   If you want to pass options to the "amsmath" package,
%   uncomment the following line:
% \usepackage[<your_options>]{amsmath}
\usepackage{halloweenmath} % automatically loads "amsmath"

\usepackage{lipsum} % just for this example, it generates the "Lorem ipsum..." 
                    % dummy text



\begin{document}

This is the usual underarrow: \( \underleftarrow{\mathsf{inc}} \); this, one the
other hand, is the smaller underarrow provided by the \textsf{halloweenmath}
package: \( \underscriptleftarrow{\mathsf{inc}} \).  Note the different impact 
on line spacing.  \lipsum*[4]

The following example is drawn directly from the question:
\begin{equation*}
  \begin{aligned}[t]
    &\mathsf{bit_0} \bullet \underleftarrow{\mathsf{inc}} \\
    &\mathsf{bit_1} \bullet \underleftarrow{\mathsf{p}}
  \end{aligned}\quad
  \begin{aligned}[t]
    &\mathsf{bit_0} \bullet \underscriptleftarrow{\mathsf{inc}} \\
    &\mathsf{bit_1} \bullet \underscriptleftarrow{\mathsf{p}}
  \end{aligned}
\end{equation*}
Each user should judge by hersefl\slash himself whether the result fulfill
her\slash his needs.

\end{document}

The output is

Output from the above code

and, I repeat, you should judge by yourself whether it does what you expected.

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.