# Modify eqnarray to match that of amsmath's align

This is a follow-up question to \eqnarray vs \align.

Sadly, some journals (and their accompanying document classes) still require the use of eqnarray to arrange a number of equations in a single block. What would be the easiest (and best) way to modify the eqnarray environment to match the output of align without having to modify the input regime. Something that produces the output of the second set of equations (in align) given the first set (in eqnarray):

\documentclass{article}
\usepackage{amsmath}% http://ctan.org/pkg/amsmath
\begin{document}
\begin{eqnarray}
f(x) & = & ax^2 + bx + c \\
g(x) & = & dx^2 + ex + f
\end{eqnarray}

\setcounter{equation}{0}
\begin{align}
f(x) & = ax^2 + bx + c \\
g(x) & = dx^2 + ex + f
\end{align}
\end{document}


The idea is to provide a very minimal package that could be added to a document when it still uses eqnarray, without having to modify the code used for eqnarray.

My first attempt was to modify the setup within \eqnarray (from latex.ltx). Currently defined as

\def\eqnarray{%
\stepcounter{equation}%
\def\@currentlabel{\p@equation\theequation}%
\global\@eqnswtrue
\m@th
\global\@eqcnt\z@
\tabskip\@centering
\let\\\@eqncr
\everycr{}\halign to\displaywidth\bgroup \hskip\@centering\displaystyle\tabskip\z@skip{##}\@eqnsel &\global\@eqcnt\@ne\hskip \tw@\arraycolsep \hfil{##}\hfil &\global\@eqcnt\tw@ \hskip \tw@\arraycolsep \displaystyle{##}\hfil\tabskip\@centering &\global\@eqcnt\thr@@ \hb@xt@\z@\bgroup\hss##\egroup \tabskip\z@skip \cr }  It's obvious that the three components of an equation are handled separately. Additionally, a horizontal skip of 2\arraycolsep is inserted around the middle component while also making that component equivalent to \mathord (wrapping it within {..}). A possible correction of this is therefore: \documentclass{article} \usepackage{amsmath}% http://ctan.org/pkg/amsmath \makeatletter \def\eqnarray{% \stepcounter{equation}% \def\@currentlabel{\p@equation\theequation}% \global\@eqnswtrue \m@th \global\@eqcnt\z@ \tabskip\@centering \let\\\@eqncr\everycr{}\halign to\displaywidth\bgroup
\hskip\@centering$\displaystyle\tabskip\z@skip{##}$\@eqnsel
&\global\@eqcnt\@ne${}##{}$% Removed horizontal skip + forced mathord
&\global\@eqcnt\tw@% Removed horizontal skip
$\displaystyle{##}$\hfil\tabskip\@centering
&\global\@eqcnt\thr@@ \hb@xt@\z@\bgroup\hss##\egroup
\tabskip\z@skip
\cr
}
\makeatother
\begin{document}
\begin{eqnarray}
f(x) & = & ax^2 + bx + c \\
g(x) & = & dx^2 + ex + f
\end{eqnarray}

\setcounter{equation}{0}
\begin{align}
f(x) & = ax^2 + bx + c \\
g(x) & = dx^2 + ex + f
\end{align}
\end{document}


What else?

-
What else? Automatic offset if the alignment is too near the equation number, for instance. –  egreg Jan 31 '13 at 19:09
implement the code that supports \qedhere. –  barbara beeton Jan 31 '13 at 19:40
@barbarabeeton: \qedhere is something that is not specific to eqnarray to begin with. So users of eqnarray would most likely not use \qedhere. The idea is that code eqnarray input code remains unchanged, while the output is updated to be better (like that of align + friends). –  Werner Jan 31 '13 at 19:46
@Werner -- agreed, but if someone wrote a proof of a theorem that ended with a math display, then the \qedhere facility would be wanted (at least by a careful editor). however, i think that no math journal requires eqnarray via its document class, and physicists and computer scientists don't usually deal in theorems and proofs, so maybe the point is moot. (if you are certain that no math journal is a culprit, then i'll be happy to remove the comment.) –  barbara beeton Jan 31 '13 at 20:00
is loading the amsmath package allowed? –  jfbu Jan 31 '13 at 20:06

This is a robust solution based only on making & active. The code is well commented I hope:

\documentclass{article}
\usepackage{amsmath}% http://ctan.org/pkg/amsmath

\begingroup % we group everything so that our \catcode changes are local, and we use \gdef everywhere
\makeatletter
\gdef\eqna@origamp{&} % & stored
\catcode\&\active % set & active in the scope of these hooks
\gdef\eqna@newamp{%
\ifx\@currenvir\eqna@currenvir % if the inner-most environment is eqnarray
\eqna@onlyfirstamp\let\eqna@onlyfirstamp\@empty % use &, but only once for each line
\else % if there's another environment inside eqnarray
\eqna@origamp % use & as is
\fi
}
\gdef\eqna@hook{% modification of eqnarray
\let\eqna@currenvir\@currenvir % store the current environment, which is eqnarray or eqnarray*
\catcode\&\active % & has to be active
\let&\eqna@newamp % define & expansion
\let\eqna@onlyfirstamp\eqna@origamp % & that is used only once on a line
}
\catcode\*11 % set * letter so that we can redefine eqnarray*
\gdef\eqnarray{\eqna@hook\align} % eqnarray is our hooks and align
\gdef\eqnarray*{\eqna@hook\align*} % eqnarray* is our hooks and align*
\global\let\endeqnarray\endalign
\global\let\endeqnarray*\endalign*
\endgroup

\begin{document}\thispagestyle{empty}

\begin{eqnarray}
f(x) & = & \begin{cases} 1 & x\geq0 \\ 0 & x<0 \end{cases}\\
\begin{pmatrix}1&0\\0&1\end{pmatrix} & = & dx^2 + ex + f \nonumber\\
kkk(x) & = & gx^2 + kx + m
\end{eqnarray}

\begin{align}
f(x) & = \begin{cases} 1 & x\geq0 \\ 0 & x<0 \end{cases}\\
\begin{pmatrix}1&0\\0&1\end{pmatrix} & = dx^2 + ex + f \notag\\
kkk(x) & = gx^2 + kx + m
\end{align}

\end{document}

-
Don't forget about eqnarray*. However this requires amsmath, which probably is not allowed if the journal admits only eqnarray. –  egreg Feb 1 '13 at 12:12
@egreg * done. And you are right that it requires amsmath. However, it at least does the job of converting eqnarray truly into align. –  tohecz Feb 1 '13 at 13:09

Transmutation of eqnarray into align

original enthusiasm: I just didn't believe it when I saw it worked. Well it works in this very minimal case, but will certainly break I guess in real life.

When I proposed the method I had hesitated between a an active & approach (exactly what tochecz's code seems to do very robustly) and a more down-to-earth approach using delimited arguments. I was very surprised that I got the delimited argument method to work quickly so I posted it here and then extended to multi-line situations. I also wasted some time on extending to many-tabs as I didn't know that eqnarray was a strictly three column format with two tabs.

However if one wanted to extend the code to allow \begin{env}...\end{env} that would require quite an effort. Actually possibly recreating the amsmath \collect@body or similar (perhaps one could just coerce it to serve us here). That's my two pence thought at this stage as I was busy with other things in-between and I come back to see that tochecz has implemented the idea of transmutation with the active & technique, obviously the much better choice. So purely by sentimentalism I will leave here some of my initial code.

\documentclass{article}
\usepackage{amsmath}% http://ctan.org/pkg/amsmath

\newtoks\arraytoaligntoks

%% Initial version for two lines
%%\long\def\eqnarray #1&#2&#3\\#4&#5&#6\end{%
%%    \arraytoaligntoks={#1&#2#3\\#4&#5#6}%
%%    \edef\endeqnarray{\noexpand\begin{align}\the\arraytoaligntoks
%%                     \noexpand\end{align}}\end}

%% version for arbitrarily many lines*
%% But this will fail completely if some \begin..\end is not within braces

\def\transmute #1&#2&#3\\{\arraytoaligntoks\expandafter
{\the\arraytoaligntoks #1&#2#3}}

\def\jfbu{\jfbu}

\long\def\eqnarray #1\end{\arraytoaligntoks{}%
\def\\##1\\{\transmute ##1\\%
\def\\####1\\{\ifx\jfbu####1\jfbu\else
\arraytoaligntoks\expandafter{\the\arraytoaligntoks \\}%
\transmute ####1\\\expandafter\\\fi}\\}%
\\#1\\\\%
\edef\endeqnarray{\noexpand\begin{align}\the\arraytoaligntoks
\noexpand\end{align}}\end}

\begin{document}\thispagestyle{empty}

\begin{eqnarray}
f(x) & = & ax^2 + bx + c \\
g(x) & = & dx^2 + ex + f \nonumber\\
k(x) & = & gx^2 + kx + m
\end{eqnarray}

\begin{align}
f(x) & = ax^2 + bx + c \\
g(x) & = dx^2 + ex + f \notag\\
k(x) & = gx^2 + kx + m
\end{align}

\end{document}


-
This is specific to a two-liner eqnarray and "will certainly break I guess in real life". –  Werner Jan 31 '13 at 20:51
The usage is similar to that of align, except for the fact the it requires a dual alignment character & as in my example. You can use it to set a single equation, two, or more, just like align. One would use \nonumber to remove a number in eqnarray, or use eqnarray* to remove all numbers (just like align*). –  Werner Jan 31 '13 at 20:55
In retrospect, I'm glad to see that you may not have grown up with the eqnarray era in the sense that you didn't know if only took a double alignment &..&` (and that's it)! :) –  Werner Jan 31 '13 at 23:08