6

I'm in the process to try to give an expl3 flavor of my answer of my question: Add a marginal note when a page break occurs in the middle of a multi-line equation.

During this process, I noticed a difference in the result of some treatment applied in parallel to LaTeX3's integers and LaTeX2e's counters: the minimized example below shows that, despite the parallelism of the treatment, the labels affected to each line of the align environment:

  • start from 0 for the labels build with a LaTeX2 counter,
  • start from n for the labels build with a LaTeX3 integer (n being the number of labeled lines of the align environment),

the .aux file containing:

\relax 
\newlabel{LaTeX2-counter-line-1}{{}{1}}
\newlabel{LaTeX3-integer-line-4}{{}{1}}
\newlabel{LaTeX2-counter-line-2}{{}{1}}
\newlabel{LaTeX3-integer-line-5}{{}{1}}
\newlabel{LaTeX2-counter-line-3}{{}{1}}
\newlabel{LaTeX3-integer-line-6}{{}{1}}

Do you see what's going on?

\documentclass{article}
\usepackage{amsmath}
\usepackage{xparse,environ}

\ExplSyntaxOn
\makeatletter

% Each line of the `align' environment will have a unique number.
\newcounter{line@of@align}
\int_new:N \g_line_of_align_int

% Save the original `align' environment.
\cs_set_eq:cc {db_align_start:} {align}
\cs_set_eq:cc {db_align_end:} {endalign}
\NewDocumentEnvironment{amsmathalign}{}
{\db_align_start:}
{\db_align_end:}

% Redefine it.
\RenewEnviron{align}
{
  \db_patch:nV {align} \BODY
}

\seq_new:N \l_db_patch_seq
\cs_new_protected:Nn \db_patch:nn
 {
  %
   \seq_set_split:Nnn \l_db_patch_seq { \\ } { #2 }
   \begin{amsmathalign}
     \seq_use:Nnnn \l_db_patch_seq { \db@patch } { \db@patch } { \db@patch } \hfill
   \end{amsmathalign}
 }
\cs_generate_variant:Nn \db_patch:nn { nV }

\NewDocumentCommand{\db@patch}{so}{%
  \IfValueTF{#2}{%
    \IfBooleanTF{#1}{\\*[#2]}{\\[#2]}%
  }{%
    \IfBooleanTF{#1}{\\*}{\\}
  }%
  % We increment the number of the current line.
  \stepcounter{line@of@align}%
  \int_gincr:N \g_line_of_align_int
  % We set the labels of the current line.
  \ltx@label{ LaTeX2-counter-line-\theline@of@align }%
  \ltx@label{ LaTeX3-integer-line-\int_use:N \g_line_of_align_int }%
}

\makeatother
\ExplSyntaxOff

\begin{document}
\begin{align}
  1 + 1 & = 2 \\
  2 + 1 & = 3 \\
  3 + 1 & = 4 \\
  4 + 1 & = 5
\end{align}
\end{document}
0

1 Answer 1

13

AMS alignments are set twice, once in a "measuring" pass and then again to typeset. It knows about all LaTeX2e counters (using the infrastructure that LaTeX uses to reset counters for \include so all counters are restored after the measuring, but it does not know about expl3 allocation so those counters all get incremented on both passes. You would see a similar thing with tabularx and some other environments.


Perhaps the simplest fix is to use a hybrid allocation of the count register

%\int_new:N \g_line_of_align_int
\newcounter{g_line_of_align_int}
\cs_set_eq:NN\g_line_of_align_int\c@g_line_of_align_int

produces

\relax 
\newlabel{LaTeX2-counter-line-1}{{}{1}}
\newlabel{LaTeX3-integer-line-1}{{}{1}}
\newlabel{LaTeX2-counter-line-2}{{}{1}}
\newlabel{LaTeX3-integer-line-2}{{}{1}}
\newlabel{LaTeX2-counter-line-3}{{}{1}}
\newlabel{LaTeX3-integer-line-3}{{}{1}}

The dual allocation is one general approach to the problem but for the specific case of AMS alignments rather than making sure the counter gets reset it would be better to only increment it once so

  \ifmeasuring@\else % do nothing on first pass
  \stepcounter{line@of@align}%
  \int_gincr:N \g_line_of_align_int
  % We set the labels of the current line.
  \ltx@label{ LaTeX2-counter-line-\theline@of@align }%
  \ltx@label{ LaTeX3-integer-line-\int_use:N \g_line_of_align_int
  \fi
1
  • I think it isn't really recommended to use c@ internal in LaTeX3. tex.stackexchange.com/questions/167094/… -- Perhaps \int_set:Nn\g_line_...int{\arabic{g_line..._int}} is better? (also you have an unmatched ( in the answer)
    – user202729
    Commented Sep 11, 2021 at 2:18

Not the answer you're looking for? Browse other questions tagged .