[Tex/LaTex] algorithm2e noend option produces wrong label

algorithm2ecross-referencing

I have a problem with the algorithm2e package. I want to reference the end of a block, e.g., a for-loop, in my text. Therefore, I place a label behind the closing bracket of the for statement. When I configure the package to produce an "end" line, the label correctly points to this line. But if I use the option "noend", the label points to the for statement instead of the last line of the for-loop.
Here is an example:

\documentclass[]{scrartcl}
\usepackage[algo2e, noline]{algorithm2e}
\begin{document}
\begin{algorithm2e}  
    \For {...} { a = b\; }\label{x}  
\end{algorithm2e}
Reference: \ref{x}
\end{document}

The output would look somehow like this:

1 for … do

2 a = b

3 end

Reference: 3

When I reference label x in my text, I get a correct reference to line 3.

With the noend option for package algorithm2e, I get the following output:

1 for … do

2 a = b

Reference: 1

Label x now creates a reference to line 1 instead of line 2.

I guess it depends on how latex handles labels. I can fix it by putting the label behind the last line of my for-loop. But then the label would point to line 2 instead of 3 when I want to show "end" lines again.

Is there a possibility that always generates the correct reference independent of the option that I am using?

Best Answer

You most certainly triggered a bug in algorithm2e. While the manual is not very clear on that, I guess the behaviour of the end version is correct, and the label should refer to the last line of the block. The reason for this bug is that \label picks up \@currentlabel, but algorithm2e uses its own counter AlgoLine, and this is not pushed to \@currentlabel in all situations. The funny thing is that algorithm2e has special code for label handling when hyperref is loaded, and then everything works correct. So your recipe is: 1. Inform the maintainer of algorithm2e about this bug. 2a. Use the hyperref package. 2b. If you don't want to use hyperref, the following code defines a new labeling command, \elabel, which works as expected:

\documentclass{article}

\usepackage[lined,linesnumbered,noend]{algorithm2e}
\usepackage{hyperref}

\makeatletter
\@ifpackageloaded{hyperref}{%
  \def\elabel#1{\label{#1}}%
}{%
  \def\elabel#1{\@bsphack \protected@write \@auxout {}{\string \newlabel {#1}{{\theAlgoLine }{\thepage }}}\@esphack}%
}
\makeatother

\begin{document}
\SetAlgoShortEnd%
\begin{algorithm}%
\For {...} { a = b\; }                \label{ya}\elabel{ya2}
\end{algorithm}%
\textbackslash{}label gives \ref{ya}, \textbackslash{}elabel is \ref{ya2}%

\SetAlgoNoEnd%
\begin{algorithm}%
\For {...} { a = b }\label{xa}\elabel{xa2}
\end{algorithm}%
\textbackslash{}label is \ref{xa}, \textbackslash{}elabel is \ref{xa2}%
\end{document}

sample output

Related Question