0

I have a series of norm macros that I want to expand to \left\| ...\right\| in display math but remain as \| ... \| in inline math. Each norm has a subscript unique to the macro:

\newcommand {\normbrak} [2]                            % display/inline -aware norm brackets
    {\mathchoice{\left\|#1\right\|_{#2}}{\|#1\|_{#2}}{\|#1\|_{#2}}{\|#1\|_{#2}}}
\newcommand {\inorm}    [1] {\normbrak{#1}{1}}         % 1-norm (nuclear norm)
\newcommand {\iinorm}   [1] {\normbrak{#1}{2}}         % 2-norm (operator norm)
\newcommand {\fronorm}  [1] {\normbrak{#1}{\text{F}}}  % Frobenius norm
\newcommand {\infnorm}  [1] {\normbrak{#1}{\infty}}    % infinity norm
\newcommand {\Linorm}   [1] {\normbrak{#1}{L^1}}       % L1 norm
\newcommand {\Liinorm}  [1] {\normbrak{#1}{L^2}}       % L2 norm
\newcommand {\Linfnorm} [1] {\normbrak{#1}{L^\infty}}  % L-infinity norm

In certain places, I wish to write, e.g., \fronorm{\hat H}^{-1} to get a superscript on the norm as well. My problem is that \mathchoice appears to reset the positioning of superscripts and subscripts, yielding

bad norm superscript

instead of the proper

good norm superscript

One possible solution is to rewrite every macro as, e.g.

\newcommand {\normbrak} [3] {%
    \mathchoice
        {\left\|#1\right\|_{#2}\IfNoValueF {#3} {\sp{#3}}}
        {\|#1\|_{#2}\IfNoValueF {#3} {\sp{#3}}}
        {\|#1\|_{#2}\IfNoValueF {#3} {\sp{#3}}}
        {\|#1\|_{#2}\IfNoValueF {#3} {\sp{#3}}}%
}

\NewDocumentCommand {\fronorm} {me{^}} {% \normbrak{#1}{\text{F}}{#2}% }

but this seems messy and redundant.

Is there a way to stop \mathchoice from ratching the bounds of its contents, or a macro other than \mathchoice that would work here?

COTO
  • 371
  • 1
    you could make the superscript an optional argument so \newcommand {\normbrak} [3][] {... then \fronorm[-1]{\hat H} – David Carlisle Jan 06 '22 at 20:41
  • 1
    Btw that image really shows why one shouldn't blindly use left/right. – daleif Jan 06 '22 at 22:33
  • @DavidCarlisle sigh OK. Was hoping to avoid having to change my markup because there are a lot of these scattered throughout the document, but reality is what it is. Thanks. – COTO Jan 07 '22 at 00:55
  • as @daleif indicates your example here would look much better without left/right so an alternative solution would be to simply drop the mathchoice – David Carlisle Jan 07 '22 at 00:57
  • @DavidCarlisle: The problem is that in other contexts where the norm is used, the argument is, e.g., a fraction, and the expanding braces are needed. I know of no way to get LaTeX to use \left\| \right\| when it "looks good" and \| \| when it "looks good" except to choose based on whether display math is being used. If I don't have the choice made by the macro itself, then I have to implement at least two versions of each of the seven macros, which smacks of bad design. So I'm at a loss. – COTO Jan 07 '22 at 01:04

2 Answers2

1

You have to absorb the possible superscript before calling \mathchoice.

Here's a way to do it, with some fixes:

  1. use \lVert and \rVert instead of \| (try \|-x\| to see why);
  2. use \mathrm{F} instead of \text{F} (try in a theorem statement to see why).
\documentclass{article}
\usepackage{amsmath}

\NewDocumentCommand{\normbrak}{mme{^}}{% \mathchoice{\makenormbrak{\left}{\right}{#1}{#2}{#3}} {\makenormbrak{}{}{#1}{#2}{#3}} {\makenormbrak{}{}{#1}{#2}{#3}} {\makenormbrak{}{}{#1}{#2}{#3}}% }

\NewDocumentCommand{\makenormbrak}{mmmmm}{% #1\lVert #3 #2\rVert_{#4}\IfValueT{#5}{^{#5}}% }

\newcommand {\inorm} [1] {\normbrak{#1}{1}} % 1-norm (nuclear norm) \newcommand {\iinorm} [1] {\normbrak{#1}{2}} % 2-norm (operator norm) \newcommand {\fronorm} [1] {\normbrak{#1}{\mathrm{F}}}% Frobenius norm \newcommand {\infnorm} [1] {\normbrak{#1}{\infty}} % infinity norm \newcommand {\Linorm} [1] {\normbrak{#1}{L^1}} % L1 norm \newcommand {\Liinorm} [1] {\normbrak{#1}{L^2}} % L2 norm \newcommand {\Linfnorm} [1] {\normbrak{#1}{L^\infty}} % L-infinity norm

\begin{document}

[ \fronorm{\hat{H}}^{-1} ] \begin{center}% for comparison $\fronorm{\hat{H}}^{-1}$ \end{center}

\end{document}

enter image description here

This image, however, clearly shows why using \left and \right is very dangerous, because it leads to very oversized delimiters.

egreg
  • 1,121,712
0

To assist anyone facing this same issue:

I came up with a workable, if inelegant solution:

\ExplSyntaxOn
\NewDocumentCommand {\norm} {som} {%
    \IfBooleanTF {#1} {\left\|#3\right\|} {\|#3\|}%
    \IfNoValueF {#2} {\sb{%
        \str_case:nnF {#2} {
            {F}    {\text F}
            {inf}  {\infty}
            {L1}   {L^1}
            {L2}   {L^2}
            {Linf} {L^\infty}
        }
        {#2}%
    }}%
}
\ExplSyntaxOff

This allows for, e.g., \norm[F]{\hat H}^{-1} and \norm*[L2]{\sum\limits_k a_k}^2 to both work as expected, with the * manually invoking the \left| right\| version rather than the default \| \| version.

Inelegant, since the choice of brackets should ideally be decided automatically by the height of the contents, but... workable.

Thanks to @DavidCarlisle and @daleif for suggestions.

COTO
  • 371
  • In this case can scan forward for superscript as well, but is highly difficult (as with other TeX programming tasks). I think embellishment does that? – user202729 Jan 07 '22 at 04:16
  • Wait actually... in this case you just need to distinguish inline and display math, right? In that case it's actually possible to distinguish without mathchoice (e.g. use everydisplay https://tex.stackexchange.com/a/389460/250119) – unless you count fraction/superscript as inline https://tex.stackexchange.com/a/583752/250119 – user202729 Jan 07 '22 at 04:20