↑↑ Home ↑ TeX tricks

Macros for displayed equations

Why invent a new macro for displayed equations when LaTeX already offers several? The equation and eqnarray environments already offer displayed equations with equation numbers, so what remains to be asked for? Several things, in fact. For a start, they are awfully long to type. This is aggravated by the fact that if you want to reference an equation, one has to set a label with \label, and otherwise, one usually omits the number with \nonumber.

There are also some drawbacks to do with appearance of the text, mainly in the eqnarray environment. For equations with many integrals and/or fractions, the distances between lines are a bit small. This can of course be fixed by making the line distance larger within the eqnarray or by inserting vertical spacers after the end of the line. But it is a lot of work to type "\nonumber\\\noalign{\vskip 2mm}" at the end of each line.

Then there is the spacing to both sides of the equals sign which fills the middle column of the alignment table which is the heart of an equation array. TeX is very sophisticated in determining the right spacing between components of a formula; an equals sign is recognised as a relational operator and thererfore gets rather large spaces to both sides. But the space to the sides of an equals sign in a LaTeX equation array is huge, much larger than usual. This looks especially silly when there is than one equals sign in a line because then they will be spaced differently. The spacing of the aligned equals sign can be adjusted with the variable \arraycolsep, but setting it to the right distance requires fine-tuning. Setting \arraycolsep to zero makes the spacing too small.

So why doesn't TeX automatically chooses the right spacing for an equals sign here? The answer is that it stands quite alone in the middle entry of what is in effect a table and therefore is not recognised as a relation. (This is why one should always type "{}+..." when continuing a sum on the next line, not just "+...". In the latter case the plus symbol will be taken for a sign and put closer to what follows.)

When I have to use LaTeX, I set \arraycolsep to 0pt and define \def\eq{{}={}}, which I then use instead of the equals sign. But for home use I have a different macro for aligned equations that 1) has a shorter name than eqnarray, 2) allows the user to temporarily augment line spacings without much typing work, 3) gets spaces right so that the position of the alignment characters ("&") remains hidden to the reader, and 4) allows equation numbers, also without superfluous typing work. It is based on the TeX macro for tables, \halign. For the equation numbers, LaTeX is used.

% standard "display math" macro, with optional number+label:
\def\dmath#1#2{
$$\lineskiplimit=1000pt \advance\lineskip by #1\jot 
\mathsurround=0pt \tabskip=0pt plus 1000pt
\everycr{\noalign{\penalty\interdisplaylinepenalty}}
\halign to \displaywidth{
\hfil$\displaystyle{##}$\tabskip=0pt&%
\hfil $\displaystyle{{}##{}}$\hfil &%
$\displaystyle{##}$\hfil \tabskip=0pt plus 1000pt minus 1000pt&%
\refstepcounter{equation}\label{##}\llap{(\theequation)}\tabskip=0pt\cr
\noalign{\ifdim \prevdepth>-1000pt \vskip -#1\jot\fi}
#2\crcr}$$}
The macro has two parameters, the additional line spacing and the body of the alignment table, denoted by #1 and #2. The placeholder for the table cells is ## instead of # inside \definitions so it can't be confused with one of the parameters. First a word on the template for the table's rows. The middle column contains "{{}##{}}", that is there is an empty block to the left and the right of whatever is inthis column. This makes TeX recognise an equals sign as a relational operator. Besides, there is an additional \displaystyle command there. This makes it possible to centre displayed formulas under each other by using only the middle column. Without \displaystyle, formulas in this column would be written smaller, as text formulas.

The left and right column are as in LaTeX, but here there is an additional fourth column containing the equation number. It makes use of the fact that TeX omits the commands of the template for a table cell when a line is ended prematurely. Therefore in lines containing only the three regular columns, the code incrementing the equation number and setting the label will not be processed. For getting a number and a label, one only has to type an additional & and the label name, which is probably the world-wide minimum extra effort. One has to take a little care with the label names; there must be no spaces and no line feed between the label name and the \cr ending the line, just as there mustn't be in the braces after \label. Alternatively, one can put a % (immediately) after the name, which will declare the rest of the source line including the line feed a comment, and write the \cr in the next line. Apropos \cr: In the body of the \dmath macro, table rows are concluded with \cr, which is the TeX command for that purpose.

\tabskip is a "glue", a stretchable and shrinkable spacer. The length after "plus" is the distance it can be stretched, the one after "minus" the amount it can shrink. Setting the \tabskip to a stretchable spacer before the first column and a totally elastic one after the third serves to centre the equation and to align the equation number with the right end of the equation display. The commands in braces after \everycr are very important. They insert a penalty, ie an item discouraging page breaks, between formula lines. The undesirablility of a page break between formula lines is traditionally stored in the adequately if verbosely named variable \interdisplaylinepenalty. It can be changed by the user but is usually set to 100 (a largish value).

At the beginning of the macro, the extra space "#1\jot" is added to the line spacing \lineskip. \jot is the unit in which additional spacing between formula lines is traditionally expressed; is it usually equal to 3 pt, about 1 mm. \lineskiplimit is set to a huge value to ensure that the space between lines will be determined solely by \lineskip and the height of the boxes containing the formula lines. Otherwise another measure (the distance between base lines rather than the boundaries of adjacent boxes) may be used, which can lead to funny effects when inserting something between lines (see below).

The \ifdim construct after the preamble deletes the extra line space which would otherwise be inserted before the displayed equation; the extra spacing is to apply only to lines between equations. Then comes the table body, the second parameter. To save the user typing the final \cr, there is a \crcr after that. (\crcr executes a \cr unless there is one immediately preceding it.)

For using \dmath without extra spacing, one can type \dmath0{...}. In TeX digits cannot be part of control sequence names, so the 0 is recognised as the first argument. One can do without the braces around the first argument whenever the spacing is an integer in units of \jot. Here is one "non-trivial" example:

\dmath2{
(-2b+t)(\mbf\rho_1,\mbf\rho_3)&=&
\frac1{(2\pi)^3}\bigg(
-2\,(2\pi)\Delta_1[\ln2+\psi(1)-\ln m-\ln|\mbf\rho_{13}|]\,
\Delta_3\,\Phi_2(\mbf\rho_1,\mbf\rho_3)
\crd&&\qquad\quad\quad
{}+2\,(2\pi)\,[\ln2+\psi(1)-\ln m]\,
\Delta_1\,\Delta_3\,\Phi_2(\mbf\rho_1,\mbf\rho_3)
\crd&&\qquad\quad\quad
{}-2\int d^2\mbf\rho_0
\frac{\theta(|\mbf\rho_{10}|-\epsilon)}{|\mbf\rho_{10}|^2}
\Delta_0\,\Delta_3\,\Phi_2(\mbf\rho_0,\mbf\rho_3)\bigg)
\cr
&=&\frac2{(2\pi)^3}\bigg(
2\pi\,\Delta_1\ln|\mbf\rho_{13}|\,\Delta_3\,\Phi_2(\mbf\rho_1,\mbf\rho_3)
-\int d^2\mbf\rho_0\frac{\theta(|\mbf\rho_{10}|-\epsilon)}{|\mbf\rho_{10}|^2}
\Delta_0\,\Delta_3\,\Phi_2(\mbf\rho_0,\mbf\rho_3)\bigg)
\cr
&=&\frac2{(2\pi)^3}\bigg(
\left[(2\pi)^2\delta^2(\mbf\rho_{13})\,\Delta_3
+4\pi\frac{\mbf\rho_{13}\cdot\mbf\nabla_1}{|\mbf\rho_{13}|^2}\,\Delta_3
+2\pi\ln|\mbf\rho_{13}|\,\Delta_1\Delta_3
\right]\Phi_2(\mbf\rho_1,\mbf\rho_3)
\crd&&\qquad\quad\quad
-\int d^2\mbf\rho_0\frac{\theta(|\mbf\rho_{10}|-\epsilon)}{|\mbf\rho_{10}|^2}
\Delta_0\,\Delta_3\,\Phi_2(\mbf\rho_0,\mbf\rho_3)\bigg)
&eq:-2b+t}
Here is what it represents. The last line has an equation number with the label "eq:-2b+t". The example has one control sequence in it which I haven't defined yet (leaving \mbf aside, which just makes the rho's bold face). It is \crd. There are three equals signs in this calculation, and several of the terms take up multiple lines. \crd was used between lines that belong to the same expression. It is defined in the following way:
% CR with double penalty:
\def\crd{\crcr\noalign{\unpenalty
\multiply\interdisplaylinepenalty by 2 \penalty \interdisplaylinepenalty}}
It doubles the penalty for page breaks. Used as above, it inhibits page breaks between lines that do not have an equals sign between them. It is unavoidable to turn pages in long calculations, but it helps readibility if single stages in the calculation do not straddle pages.

The first item in the definition is the end-of-table-row command \crcr. (That I didn't use \cr here is just a detail. I found out that using a label before \crd didn't work, probably due to LaTeX's processing of labels. With this definition of \crd, one can use \cr\crd after a label without introducing a double row spacing.) The rest of the macro is a \noalign control sequence. This is necessary because page-break penalties may only be inserted in TeX's "vertical mode". The first control sequence inside the braces, \unpenalty, removes the penalty inserted by \dmath. Then the display-line penalty is doubled and inserted. Its value doesn't need to be restored since commands inside \noalign form a group, and changes to variables are undone automatically at the end of that group. (Technical detail: Removing the smaller penalty was necessary since TeX picks the smaller one if it finds two penalties in a row.)

One more useful feature: A macro that writes an equation label between two lines, centred vertically. It can be used for centring a label for an even number of lines or moving a label overlapping with a long line out of the way.

% label between lines:
\def\crl#1{\crcr\noalign{\unpenalty\penalty 10000
\nointerlineskip \vbox to 0pt {
\dimen0=\lineskip \vskip \dimen0 minus 1000pt \hbox to \displaywidth{%
\hfil \refstepcounter{equation}\label{#1}(\theequation)}
\vskip 0pt minus 1000pt} \penalty 10000}}
The macro has as its only parameter the name of the label. Its first command is a \crcr. (So if \crl is used as the first command in a \dmath body, it does not insert an empty line together with the \cr in \dmath.) The rest is vertical mode material inside a \noalign block. In that block, first comes the removing of the previous penalty and a penalty so large it strictly forbids a page break (to prevent a page break between these two equations with the number dangling below the bottom of the page). The \nointerlineskip prohibits the insertion of inter-line spacing. (The following \vbox would normally be surrounded by such space, which would lead to a double line spacing for the formulas.)

Now comes the heart of the matter: the \vbox to 0pt, a box in vertical mode with the (forced) height zero points. It does not change the vertical position of the formula lines because it is computed on the basis of boxes' boundaries. (That's why \lineskiplimit was set to a large value above.) The box contains a vertical glue whose natural height is the height of the line spacing to come. (The line spacing has to be assigned to a dimension-type variable to get rid of its own stretch and shrink components.) It has a large capability to shrink, as has the glue after the \hbox containing the number. These two shrink components have the effect of centring the equation number on the following line spacing. Imagine a thin wooden ledge of the height of the line distance whose top is glued to the wall. From its bottom there goes a rubber strap to the top of a sign with an equation number on it, and from the bottom of the sign an identical strap goes back to the top of the ledge (since the vbox has height zero). That's how the centring works.


TOS / Impressum