# amsmath align* tampering with a counter of mine

\documentclass[a4paper]{report}
\usepackage{amsmath,mathtools}
\makeatletter
\newcount\mw@shortcnt
\mw@shortcnt=0
\newcommand{\short}[1]{%
\expandafter\def\csname temp\the\mw@shortcnt\endcsname{#1}
}
\newcount\mw@unshortcnt
\mw@unshortcnt=0
\newcommand{\unshort}{%
\csname temp\the\mw@unshortcnt\endcsname
}
\newcommand{\undershort}[1]{\underset{\unshort}{#1}}
\newcommand{\overshort}[1]{\overset{\unshort}{#1}}
\newcommand{\abbr}[2]{\expandafter\gdef\csname#1\endcsname{#2}}
\newcommand{\setshortcnt}[1]{\mw@shortcnt=#1}
\newcommand{\setunshortcnt}[1]{\mw@unshortcnt=#1}
\newcommand{\showshort}{\the\mw@shortcnt}
\newcommand{\showunshort}{\the\mw@unshortcnt}
\newcommand{\showboth}{\showshort\showunshort}
\makeatother
\newcommand{\ang}[1]{\left\langle #1\right\rangle}

\begin{document}
\showboth \\
\short{\mathclap{\substack{\text{posso portarmi da un membro all'altro la proiezione e $p_1$ idempotente.} \\ |}}}
\short{\mathclap{\substack{| \\ \text{commutano per ipotesi e $p_2$ porto a destra nel primo}}}}
\showboth \\
\begin{align*}
\showboth \\
\setunshortcnt{0}
\ang{x-p_1(p_2(x)\!),p_1(p_2(y)\!)}={}\text{\textit{\showboth}}&\text{\textit{\showboth}}\ang{x,p_1(p_2(y)\!)}-\ang{p_1p_2(x),p_1p_2(y)}\undershort{=}{} \\
{}={}&\ang{p_1(x),p_2(y)}-\ang{p_1(p_2(x)\!),p_2(y)}\undershort{=}\ang{p_2(p_1(x)\!),y}-\ang{p_1(x),p_2(y)}=0.
\end{align*}
\end{document}


The command \short is defined for when I have an \underset or \overset with \mathclap, \substack and \text combined in the under or over argument, as in the example, to keep the complications of that argument outside the equation and make the equation's code more readable. The command \unshort (and its abbreviation in combination with \underset and \overset) is the twin of \short to place the argument in place. They rely each on a counter, with the counters named \mw@shortcnt and \mw@unshortcnt, defining macros with a standard start followed by the counter's value (previously incremented globally to avoid conflict in sequences of \shorts) to expand to the argument that is to be later recovered, and recovering the argument placed in the \short when \mw@shortcnt was at a certain value (\mw@unshortcnt, previously globally incremented by 1). The example compiles to:

Both counters start at 0 as set. Then the shortcnt becomes 2 because of the two \shorts. And that's all right. Then I open the align* and the unshortcnt magically becomes 2! I set it back to 0 manually, and the following 20 shows the command is executed, but the & somehow undoes that! What is happening here? WHat does this align* environment do to my counters and why? After all it's prefixed with mw@, the counter name I mean, so how can amsmath know anything about it to tamper with it? Update: It looks like setting the unshortcnt right manually the first time is enough to solve this… why does the first & mess with the counter while the second one doesn't?

Edit: The idea of this is the following. If I write the above code with e.g.:

\overset{\mathclap{\substack{\text{posso portarmi da un membro all'altro la proiezione e $p_1$ idempotente.} \\ |}{=}


It is next to unreadable. So I wanted to store the messy unreadable argument somewhere outside the equation, making things more readable in the equation. I started doing things like:

\def\temp{\mathclap{\substack{\text{posso portarmi da un membro all'altro la proiezione e $p_1$ idempotente.} \\ |}


To then recall the \temp macro inside the equation. Since it was a shortening and unshortening of the arguments, it seemed logical to have a macro to take care of the macro definition and recalling, and to create the name. Here came \short and \unshort. Since the most frequent use of this was in \underset, I combined \unshort with it, yielding \undershort. So the sole purpose of these macros was to make equation code more readable.

• align passes over the material twice. – egreg Dec 10 '14 at 21:55
• But there is nothing acting on the counters at the start, and yet the unshortcnt is modified. Also, if align* "passes over the material twice", then why is the second \global\advance\mw@unshortcnt+1 not done twice? Setting it right once gets the second \undershort dealt with, yet if everything is executed twice in an align*, the second \undershort and the \advance inside it should be done twice, resulting in a +2, but only a +1 happens. Maybe I misunderstood what you said @egreg. – MickG Dec 10 '14 at 22:01
• also you really, really really don't want the % in +1% – David Carlisle Dec 10 '14 at 22:08
• @MickG because without the % it increments the counter by 1, with the % it may or may not increment by 1 depending on the expansion of \csname temp\the\mw@unshortcnt\endcsname if its expansion began with 2 then the counter would increment by 12 – David Carlisle Dec 10 '14 at 22:21
• @MickG \advance needs a <number> and tex expands to find the number it expands until it finds a non-digit such as a space that terminates the number so adding % forces the \csname to be expanded before the \advance without the % it expands after the \advance. – David Carlisle Dec 10 '14 at 22:37

The amsmath alignment environments pass over the material twice. In the measurement pass, the conditional \ifmeasuring@ is set to true, otherwise it's false.

I have made some amendments to the code. For instance you have two wrong % after +1; also your settings of the counters were sometimes local sometimes global, which is wrong. There are \@namedef and \@nameuse for avoiding \expandafter\def\csname...\endcsname and \csname...\endcsname.

Finally, I used \romannumeral in the \@namedef, because control sequences ending with digits are best avoided. See How to implement (low-level) arrays in TeX and in particular Bruno Le Floch's answer.

\documentclass[a4paper]{report}
\usepackage{amsmath,mathtools}

\makeatletter
\newcount\mw@shortcnt
\newcommand{\short}[1]{%
\ifmeasuring@\else
\@namedef{mickgtemp\romannumeral\mw@shortcnt}{#1}
\fi
}
\newcount\mw@unshortcnt
\newcommand{\unshort}{%
\ifmeasuring@\else
\@nameuse{mickgtemp\romannumeral\mw@unshortcnt}%
\fi
}
\newcommand{\undershort}[1]{\underset{\unshort}{#1}}
\newcommand{\overshort}[1]{\overset{\unshort}{#1}}
\newcommand{\abbr}[2]{\global\@namedef{#1}{#2}}
\newcommand{\setshortcnt}[1]{\global\mw@shortcnt=#1\relax}
\newcommand{\setunshortcnt}[1]{\global\mw@unshortcnt=#1\relax}
\newcommand{\showshort}{\the\mw@shortcnt}
\newcommand{\showunshort}{\the\mw@unshortcnt}
\newcommand{\showboth}{\showshort\showunshort}
\makeatother

\newcommand{\ang}[1]{\left\langle #1\right\rangle}

\begin{document}
\showboth \\
\short{\mathclap{\substack{\text{posso portarmi da un membro all'altro la proiezione e $p_1$ idempotente.} \\ |}}}
\short{\mathclap{\substack{| \\ \text{commutano per ipotesi e $p_2$ porto a destra nel primo}}}}
\showboth \\
\begin{align*}
\showboth \\
\setunshortcnt{0}
\ang{x-p_1(p_2(x)\!),p_1(p_2(y)\!)}={}\text{\textit{\showboth}}&\text{\textit{\showboth}}\ang{x,p_1(p_2(y)\!)}-\ang{p_1p_2(x),p_1p_2(y)}\undershort{=}{} \\
{}={}&\ang{p_1(x),p_2(y)}-\ang{p_1(p_2(x)\!),p_2(y)}\undershort{=}\ang{p_2(p_1(x)\!),y}-\ang{p_1(x),p_2(y)}=0.
\end{align*}
\end{document}


It might go without saying that the typography is terrible.

• But once I remove the \showboths and use an \overshort in the first case, and split the text of both the implicit \unshorts into at least two lines, it improves greatly, doesn't it :)? Anyway I take it the main culprit is the use of digits in the csnames, as explained (in a way that is a bit out of my reach) by the linked question, right? I'll bear the rest of your advice in mind @egreg. Thanks. – MickG Dec 10 '14 at 22:26
• OK, scratch the "main culprit" bit out :). I was thinking in single bits, but the whole content of the environment is read once, and so the advances are done once, but then all is read once again, thus getting the counter messed up with in the first case. But still, if I set it manually at the start of the environment, why does it change again around the &? I mean, read everything once, so set the counter right, advance it by two while reading the rest. Then read everything again, set the counter right again, and then the &` causes trouble? Maybe this has to do with the hashes? – MickG Dec 10 '14 at 22:40
• @MickG Sorry, but the code is very hard to read and, above all, it's quite difficult to understand what you're aiming to achieve. The problem with collisions of control sequences has nothing to do with the specific issue; it's a general issue about efficiency. – egreg Dec 10 '14 at 22:48
• does the edit clarify what I want to achieve? – MickG Dec 11 '14 at 6:33