@Section
@Title { An equation formatting package }
@Tag { eq }
@Begin
@PP
In this section we describe the design and implementation of the Eq
eq. @Index { Eq equation formatting package }
equation formatting package. Equation formatting makes a natural first
example, partly because its requirements have strongly influenced the
design of Lout, and partly because no cross references or galleys are
required.
@PP
To the author's knowledge, Eq is the first equation formatter to be
implemented as a collection of high-level definitions. This approach
has significant advantages: the basics of language and layout are
trivial, so the implementor can concentrate on fine-tuning; and the
definitions, being readily available, can be improved, extended, or even
replaced.
@PP
As described in the User's Guide @Cite { $kingston1995lout.user }, an
equation is entered in a format based on the one introduced by the eqn
language of Kernighan and Cherry @Cite { $kernighan1975eqn }:
kernighan.b @Index { Kernighan, B. }
cherry.l @Index { Cherry, L. }
@ID @Code {
"@Eq { { x sup 2 + y sup 2 } over 2 }"
}
The result is
@ID @Eq { { x sup 2 + y sup 2 } over 2 }
In outline, the definition of the @Code "@Eq" symbol is
eq.example @Index { @Code "@Eq" example }
@ID @Code {
"export sup over \"+\" \"2\" \"<=\""
"def @Eq"
" body @Body"
"{"
" def sup precedence 60 left x right y { ... }"
" def over precedence 54 left x right y { ... }"
" def \"2\" { Base @Font \"2\" }"
" def \"+\" { {Symbol Base} @Font \"+\" }"
" def \"<=\" { {Symbol Base} @Font \"\\243\" }"
" ..."
""
" Slope @Font 1.2f @Break 0c @Space @Body"
"}"
}
A body parameter is used to restrict the visibility of the equation
formatting symbols (there are hundreds of them). The equation as a whole
is set in Slope (i.e. Italic) font, and symbols such as @Code "\"2\"" and
@Code "\"+\"" are defined when other fonts are needed. Precedences are
used to resolve ambiguities such as {@Code "a sup b over c"}. Eq takes
all spacing decisions on itself, so to prevent white space
typed by the user from interfering, the equation is enclosed in
{@Code "0c @Space"}. We will discuss the {@Code "1.2f @Break"} later.
@PP
Thus have we disposed of the language design part of the equation
formatting problem; it remains now to define the twenty or so symbols
with parameters, and get the layout right.
@PP
Every equation has an {@I axis}: an imaginary horizontal line through
the centre of variables, through the bar of built-up fractions, and so
on. We can satisfy this requirement by ensuring that the result of each
symbol has a single row mark, on the axis. For example, the
superscripting symbol is defined as follows:
sup.example @Index { @Code "sup" example }
@ID @Code {
"def sup"
" precedence 60"
" associativity left"
" left x"
" named gap { @SupGap }"
" right y"
"{"
" @HContract @VContract {"
" | @Smaller y"
" ^/gap x"
" }"
"}"
}
The @Code "@VContract" and @Code "^/" symbols together ensure that the axis
of the result is the axis of the left parameter. A @Code "gap"
parameter has been provided for varying the height of the superscript,
with default value @Code "@SupGap" defined elsewhere as
{@Code "0.40fk"}. It is important that such gaps be expressed in units
that vary with the font size, so that they remain correct when the size
changes. Collecting the default values into symbols like @Code
"@SupGap" ensures consistency and assists when tuning the values. Here
is another characteristic definition:
over.example @Index { @Code "over" example }
@ID @Code {
"def over"
" precedence 54"
" associativity left"
" left x"
" named gap { 0.2f }"
" right y"
"{"
" @HContract @VContract {"
" |0.5rt @OneCol x"
" ^//gap @HLine"
" //gap |0.5rt @OneCol y"
" }"
"}"
}
Both parameters are centred, since we do not know which will be the
wider; we use @@OneCol to make sure that the entire parameter is
centred, not just its first column, and @@HContract ensures that the
fraction will never expand to fill all the available space, as Lout objects
have a natural tendency to do (Section {@NumberOf size}). @Code "@HLine"
is a horizontal line of the width of the column:
hline.example @Index { @Code "@Hline" example }
@ID @Code {
"def @HLine"
" named line { \"0.05 ft setlinewidth\" }"
"{ "
" { \"0 0 moveto xsize 0 lineto\" line \"stroke\" } @Graphic {}"
"}"
}
Here we are relying on the expanding tendency just mentioned.
@PP
The remaining symbols are quite similar to these ones. We conclude with
a few fine points of mathematical typesetting mentioned by a leading
authority, D. E. Knuth @Cite { $knuth1984tex }.
knuth.d @Index { Knuth, D. }
@PP
Some symbols, such as @Eq {lessequal} and @Eq { notequal }, should have a
thick space on each side; others, such as @Eq {plus} and @Eq {minus},
have a medium space; others have a thin space on the right only. This
would be easy to do except that these spaces are not wanted in
superscripts and subscripts:
@ID @Eq { r sup n+1 - 1 }
In effect, the definition of such symbols changes depending on the
context; but Lout does not permit such a change. Luckily, the so-called
`style' information set by the @@Font, @@Break, and @@Space symbols can
change in this way. Accordingly, Eq uses the @Code y unit, which is
part of style, for these spaces:
@ID @Code {
"def @MedGap { 0.20y }"
""
"def \"+\" { &@MedGap plus &@MedGap }"
""
"def @HSqueeze right x { 0.2f @YUnit x }"
}
In the equation as a whole, the y unit is initially set to
{@Code 1f}, and so @Code "@MedGap" ordinarily supplies 20% of this
amount. But superscripts and subscripts are enclosed in the
@Code "@HSqueeze" symbol, which, by changing the y unit, ensures that
any @Code "@MedGap" within them is much smaller than usual.
@End @Section