[Tex/LaTex] Serious problem with \widebar

amsmathsymbols

I met across a serious problem using the widebar math command defined by Hendrik Vogt as an answer to question 16337. It worked fine until I used \(wide)hat in its argument. Here is a M(non)WE:

\documentclass[12pt, a4paper]{article}
\usepackage{amsmath}%

\makeatletter
\newcommand*\if@single[3]{%
  \setbox0\hbox{${\mathaccent"0362{#1}}^H$}%
  \setbox2\hbox{${\mathaccent"0362{\kern0pt#1}}^H$}%
  \ifdim\ht0=\ht2 #3\else #2\fi
  }
%The bar will be moved to the right by a half of \macc@kerna, which is computed by amsmath:
\newcommand*\rel@kern[1]{\kern#1\dimexpr\macc@kerna}
%If there's a superscript following the bar, then no negative kern may follow the bar;
%an additional {} makes sure that the superscript is high enough in this case:
\newcommand*\widebar[1]{\@ifnextchar^{{\wide@bar{#1}{0}}}{\wide@bar{#1}{1}}}
%Use a separate algorithm for single symbols:
\newcommand*\wide@bar[2]{\if@single{#1}{\wide@bar@{#1}{#2}{1}}{\wide@bar@{#1}{#2}{2}}}
\newcommand*\wide@bar@[3]{%
  \begingroup
  \def\mathaccent##1##2{%
%If there's more than a single symbol, use the first character instead (see below):
    \if#32 \let\macc@nucleus\first@char \fi
%Determine the italic correction:
    \setbox\z@\hbox{$\macc@style{\macc@nucleus}_{}$}%
    \setbox\tw@\hbox{$\macc@style{\macc@nucleus}{}_{}$}%
    \dimen@\wd\tw@
    \advance\dimen@-\wd\z@
%Now \dimen@ is the italic correction of the symbol.
    \divide\dimen@ 3
    \@tempdima\wd\tw@
    \advance\@tempdima-\scriptspace
%Now \@tempdima is the width of the symbol.
    \divide\@tempdima 10
    \advance\dimen@-\@tempdima
%Now \dimen@ = (italic correction / 3) - (Breite / 10)
    \ifdim\dimen@>\z@ \dimen@0pt\fi
%The bar will be shortened in the case \dimen@<0 !
    \rel@kern{0.6}\kern-\dimen@
    \if#31
      \overline{\rel@kern{-0.6}\kern\dimen@\macc@nucleus\rel@kern{0.4}\kern\dimen@}%
      \advance\dimen@0.4\dimexpr\macc@kerna
%Place the combined final kern (-\dimen@) if it is >0 or if a superscript follows:
      \let\final@kern#2%
      \ifdim\dimen@<\z@ \let\final@kern1\fi
      \if\final@kern1 \kern-\dimen@\fi
    \else
      \overline{\rel@kern{-0.6}\kern\dimen@#1}%
    \fi
  }%
  \macc@depth\@ne
  \let\math@bgroup\@empty \let\math@egroup\macc@set@skewchar
  \mathsurround\z@ \frozen@everymath{\mathgroup\macc@group\relax}%
  \macc@set@skewchar\relax
  \let\mathaccentV\macc@nested@a
%The following initialises \macc@kerna and calls \mathaccent:
  \if#31
    \macc@nested@a\relax111{#1}%
  \else
%If the argument consists of more than one symbol, and if the first token is
%a letter, use that letter for the computations:
    \def\gobble@till@marker##1\endmarker{}%
    \futurelet\first@char\gobble@till@marker#1\endmarker
    \ifcat\noexpand\first@char A\else
      \def\first@char{}%
    \fi
    \macc@nested@a\relax111{\first@char}%
  \fi
  \endgroup
}
\makeatother

\begin{document}

$  \widebar{f \circ \widehat{x}}  $

\end{document}

The .log file delivers this:

! TeX capacity exceeded, sorry [grouping levels=255].
<to be read again> 
                   \macc@style 
l.195 ...i(f)^*} = \widebar{f \circ \widehat{x}} =
                                                   \widebar f \circ \widehat...
If you really absolutely need more capacity, …

Without the \widehat command, it's perfect:

enter image description here
Can anyone help?

Best Answer

REVISED to add important note at end:

Based on my answer at Big tilde in math mode, I adapted similar approaches for a wide hat and bar. After showing them in various math styles, I show composites of them, including the function of interest to you.

\documentclass{article}
\usepackage{scalerel}[2014/03/10]
\usepackage{stackengine}

\newcommand\reallywidetilde[1]{\ThisStyle{%
  \setbox0=\hbox{$\SavedStyle#1$}%
  \stackengine{1pt-\LMpt}{$\SavedStyle#1$}{%
    \stretchto{\scaleto{\SavedStyle\mkern.2mu\sim}{.5467\wd0}}{.5\ht0}%
%    .2mu is the kern imbalance when clipping white space
%    .5467++++ is \ht/[kerned \wd] aspect ratio for \sim glyph
  }{O}{c}{F}{T}{S}%
}}

\newcommand\reallywidehat[1]{\ThisStyle{%
  \setbox0=\hbox{$\SavedStyle#1$}%
  \stackengine{-1.0\ht0+.5pt}{$\SavedStyle#1$}{%
    \stretchto{\scaleto{\SavedStyle\mkern.15mu\char'136}{2.6\wd0}}{1.4\ht0}%
  }{O}{c}{F}{T}{S}%
}}

\newcommand\reallywidebar[1]{\ThisStyle{%
  \setbox0=\hbox{$\SavedStyle#1$}%
  \stackengine{.5pt+\LMpt}{$\SavedStyle#1$}{%
    \rule{\wd0}{\dimexpr.3\LMpt+.3pt}%
  }{O}{c}{F}{T}{S}%
}}

\def\test#1{$%
  \reallywidetilde{#1}\,
  \scriptstyle\reallywidetilde{#1}\,
  \scriptscriptstyle\reallywidetilde{#1}$~$
  \reallywidehat{#1}\,
  \scriptstyle\reallywidehat{#1}\,
  \scriptscriptstyle\reallywidehat{#1}$~$
  \reallywidebar{#1}\,
  \scriptstyle\reallywidebar{#1}\,
  \scriptscriptstyle\reallywidebar{#1}
$\par}

\parskip 1ex
\begin{document}

Normal math (different styles):

\test{abcde}
\test{abc}
\test{a}

Composites:

$\reallywidebar{D + \reallywidehat{C +\reallywidetilde{ag}}}$

$\reallywidebar{f \circ \reallywidehat{x}}$

\end{document}

enter image description here


IMPORTANT NOTE: (further revised based on better understanding)

I would make one interesting observation. The way TeX handles different mathstyles automatically is with \mathchoice, in which four boxes are constructed, and only one of them used, depending on the local mathstyle. The \ThisStyle{...\SavedStyle...} construct of the scalerel package used in this MWE is a glorified version of \mathchoice that helps save on typing.

But regardless of whether \mathchoice or \ThisStyle is used to achieve the result, the nesting of \mathchoices can become very computationally inefficient.

For cases like this, it might make sense to override the \mathchoice and tell it which of the boxes to use. One can achieve that by defining these macros:

\def\fixDS#1{{\renewcommand\mathchoice[4]{##1}#1}}% FORCE \displaystyle
\def\fixTS#1{{\renewcommand\mathchoice[4]{##2}#1}}% FORCE \textstyle
\def\fixSS#1{{\renewcommand\mathchoice[4]{##3}#1}}% FORCE \scriptstyle
\def\fixsS#1{{\renewcommand\mathchoice[4]{##4}#1}}% FORCE \scriptscriptstyle

In the case of my 2nd to last example, because all \mathchoice symbols occur in \displaystyle, one could save a lot of compilation time by invoking the call as

$\fixDS{\reallywidebar{D + \reallywidehat{C +\reallywidetilde{ag}}}}$

A similar approach can be used if the \mathchoices occur in different mathstyles. For example, The first of the following forms constructs many boxes before choosing one, while the second form bypasses the \mathchoice branching.

$\reallywidebar{A_{\reallywidebar{A_{\reallywidebar{A}}}}}$

$\fixDS{\reallywidebar{A_{\fixSS{\reallywidebar{A_\fixsS{\reallywidebar{A}}}}}}}$

This hardwiring approach need only to be considered if the computational cost of \mathchoice nesting presents a notable slowdown in compilation.


SUPPLEMENT

After having been informed that the above approach for \reallywidehat did not look so pretty for newtxmath, I reworked a version for that font. Also tweaked \reallywidetilde to match the font characteristics:

\documentclass{article}
\usepackage{scalerel}[2014/03/10]
\usepackage{stackengine}
\usepackage{newtxtext,newtxmath}

\newcommand\reallywidetilde[1]{\ThisStyle{%
  \setbox0=\hbox{$\SavedStyle#1$}%
  \stackengine{1pt-\LMpt}{$\SavedStyle#1$}{%
    \stretchto{\scaleto{\SavedStyle\mkern.2mu\sim}{.65\wd0}}{.5\ht0}%
%    .2mu is the kern imbalance when clipping white space
%    .5467++++ is \ht/[kerned \wd] aspect ratio for \sim glyph
  }{O}{c}{F}{T}{S}%
}}

\newcommand\reallywidehat[1]{\ThisStyle{%
  \setbox0=\hbox{$\SavedStyle#1$}%
  \stackengine{-1.0\ht0+1.8pt}{$\SavedStyle#1$}{%
    \stretchto{\scaleto{\SavedStyle\mkern.15mu\mathchar"0362}{1.3\wd0}}{1.15\ht0}%
  }{O}{c}{F}{T}{S}%
}}

\newcommand\reallywidebar[1]{\ThisStyle{%
  \setbox0=\hbox{$\SavedStyle#1$}%
  \stackengine{.5pt+\LMpt}{$\SavedStyle#1$}{%
    \rule{\wd0}{\dimexpr.3\LMpt+.3pt}%
  }{O}{c}{F}{T}{S}%
}}

\def\test#1{$%
  \reallywidetilde{#1}\,
  \scriptstyle\reallywidetilde{#1}\,
  \scriptscriptstyle\reallywidetilde{#1}$~$
  \reallywidehat{#1}\,
  \scriptstyle\reallywidehat{#1}\,
  \scriptscriptstyle\reallywidehat{#1}$~$
  \reallywidebar{#1}\,
  \scriptstyle\reallywidebar{#1}\,
  \scriptscriptstyle\reallywidebar{#1}
$\par}

\parskip 1ex
\begin{document}

Normal math (different styles):

\test{abcde}
\test{abc}
\test{a}

Composites:

$\reallywidebar{D + \reallywidehat{C +\reallywidetilde{ag}}}$

$\reallywidebar{f \circ \reallywidehat{x}}$

\end{document}

enter image description here

Related Question