X-Git-Url: https://git.distorted.org.uk/~mdw/mdwtools/blobdiff_plain/baa9f3563a25ec9040d59b44a86d62f4d9786258..9cb5c64cc696cd59cf723021386b254ab8de5b13:/mdwmath.dtx

diff --git a/mdwmath.dtx b/mdwmath.dtx
index 01be386..5635a0d 100644
--- a/mdwmath.dtx
+++ b/mdwmath.dtx
@@ -1,44 +1,33 @@
-% \begin{meta-comment}
-%
-% $Id: mdwmath.dtx,v 1.2 2003/09/05 16:14:36 mdw Exp $
-%
-% Various nicer mathematical things
-%
-% (c) 2003 Mark Wooding
-%
-% \end{meta-comment}
-%
 % \begin{meta-comment} <general public licence>
 %%
 %% mdwmath package -- various nicer mathematical things
-%% Copyright (c) 2003 Mark Wooding
+%% Copyright (c) 2003, 2020 Mark Wooding
+%%
+%% This file is part of the `mdwtools' LaTeX package collection.
 %%
-%% This program is free software; you can redistribute it and/or modify
-%% it under the terms of the GNU General Public License as published by
-%% the Free Software Foundation; either version 2 of the License, or
-%% (at your option) any later version.
+%% `mdwtools' is free software: you can redistribute it and/or modify it
+%% under the terms of the GNU General Public License as published by the
+%% Free Software Foundation; either version 2 of the License, or (at your
+%% option) any later version.
 %%
-%% This program is distributed in the hope that it will be useful,
-%% but WITHOUT ANY WARRANTY; without even the implied warranty of
-%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-%% GNU General Public License for more details.
+%% `mdwtools' is distributed in the hope that it will be useful, but
+%% WITHOUT ANY WARRANTY; without even the implied warranty of
+%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+%% General Public License for more details.
 %%
 %% You should have received a copy of the GNU General Public License
-%% along with this program; if not, write to the Free Software
-%% Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+%% along with `mdwtools'.  If not, write to the Free Software Foundation,
+%% Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 %%
 % \end{meta-comment}
 %
 % \begin{meta-comment} <Package preamble>
 %<+package>\NeedsTeXFormat{LaTeX2e}
 %<+package>\ProvidesPackage{mdwmath}
-%<+package>                [2003/08/25 1.3 Nice mathematical things]
-%<+oldeqnarray>\NeedsTeXFormat{LaTeX2e}
-%<+oldeqnarray>\ProvidesPackage{eqnarray}
-%<+oldeqnarray>                [1996/04/11 1.1 Old enhanced eqnarray]
+%<+package>                [2020/09/06 1.14.0 Nice mathematical things]
 % \end{meta-comment}
 %
-% \CheckSum{729}
+% \CheckSum{980}
 %% \CharacterTable
 %%  {Upper-case    \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
 %%   Lower-case    \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
@@ -63,9 +52,6 @@
 \let\opmod\pmod
 \usepackage{amssymb}
 \describespackage{mdwmath}
-%\describespackage{eqnarray}
-\ignoreenv{old-eqnarray}
-%\unignoreenv{old-eqnarray}
 \mdwdoc
 %</driver>
 %
@@ -119,8 +105,8 @@
 % Having just tried to do some simple things, I've found that there are maths
 % symbols missing.  Here they are, in all their glory:
 % \begin{center} \unverb\| \begin{tabular}{cl|cl|cl}
-% $\&$ & "\&"		& $\bitor$ & "\bitor"	& $\dbland$ & "\dbland" \\
-% $\bitand$ & "\bitand"	& $\dblor$ & "\dblor"	& 
+% $\&$ & "\&"           & $\bitor$ & "\bitor"   & $\dbland$ & "\dbland" \\
+% $\bitand$ & "\bitand" & $\dblor$ & "\dblor"   &
 % \end{tabular} \end{center}
 %
 % \DescribeMacro\xor
@@ -219,9 +205,9 @@
 % \DescribeMacro\negl
 % A few esoteric new operator names are supplied.
 % \begin{center} \unverb\| \begin{tabular}{cl|cl|cl}
-% $\keys$ & "\keys"	& $\dom$ & "\dom"	& $\ran$ & "\ran" \\
-% $\supp$ & "\supp"	& $\lcm$ & "\lcm"       & $\ord$ & "\ord" \\
-% $\poly$ & "\poly"	& $\negl$ & "\negl"
+% $\keys$ & "\keys"     & $\dom$ & "\dom"       & $\ran$ & "\ran" \\
+% $\supp$ & "\supp"     & $\lcm$ & "\lcm"       & $\ord$ & "\ord" \\
+% $\poly$ & "\poly"     & $\negl$ & "\negl"
 % \end{tabular} \end{center}
 % I think |\lcm| ought to be self-explanatory.  The |\dom| and |\ran|
 % operators pick out the domain and range of a function, respectively; thus,
@@ -236,6 +222,13 @@
 % $p(\cdot)$, there is an integer $N$ such that $\nu(n) < 1/p(n)$ for all $n
 % > N$; $\negl(n)$ is some negligible function of $n$.
 %
+% \DescribeMacro\defop
+% New operators can be defined using |\defop|:
+% \begin{quote} \syntax{"\\defop"["*"]"{"<command>"}{"<text>"}"} \end{quote}
+% defines \<command> to be an operator which typesets \<text>.  By default,
+% limits will be placed above and below the operator in display style; with
+% |*|, limits are always written as super- and subscripts.
+%
 % \subsection{Standard set names}
 %
 % \DescribeMacro\Z
@@ -276,144 +269,125 @@
 %
 % The old |\big| commands have been redefined in terms of |\bbigg|.
 %
-% \subsection{The `QED' symbol}
-%
-% \DescribeMacro\qed
-% \DescribeMacro\qedrule
-% For use in proofs of theorems, we provide a `QED' symbol which behaves well
-% under bizarre line-splitting conditions.  To use it, just say |\qed|.  The
-% little `\qedrule' symbol is available on its own, by saying |\qedrule|.
-% This also sets |\qedsymbol| if it's not set already.
-% \qed
-%
-% \begin{ignore}
-% There used to be an eqnarray here, but that's migrated its way into the
-% \package{mdwtab} package.  Maybe the original version, without dependency
-% on \package{mdwtab} ought to be releasable separately.  I'll keep it around
-% just in case.
-%
-% The following is the documentation for the original version.  There's an
-% updated edition in \package{mdwtab}.
-% \end{ignore}
-%
-% \begin{old-eqnarray}
-%
-% \subsection{A new \env{eqnarray} environment}
-%
-% \LaTeX's built-in \env{eqnarray} is horrible -- it puts far too much space
-% between the items in the array.  This environment is rather nearer to the
-% \env{amsmath} \env{align} environments, although rather less capable.
-%
-% \bigskip
-% \DescribeEnv{eqnarray}
-% {\synshorts
-% \setbox0\hbox{"\\begin{eqnarray}["<preamble>"]" \dots "\\end{eqnarray}"}
-% \leavevmode \hskip-\parindent \fbox{\box0}
-% }
-% \smallskip
-%
-% The new version of \env{eqnarray} tries to do everything which you really
-% want it to.  The \synt{preamble} string allows you to define the column
-% types in a vaguely similar way to the wonderful \env{tabular} environment.
-% The types provided (and it's easy-ish to add more) are:
-%
-% \def\ch{\char`}
-% \begin{description} \def\makelabel{\hskip\labelsep\normalfont\ttfamily}
-% \item [r] Right aligned equation
-% \item [c] Centre-aligned equation
-% \item [l] Left aligned equation
-% \item [\textrm{\texttt{Tr}, \texttt{Tc} and \texttt{Tl}}] Right, centre and
-%       left aligned text (not maths)
-% \item [L] Left aligned zero-width equation
-% \item [x] Centred entire equation
-% \item [:] Big gap separating sets of equations
-% \item [q] Quad space
-% \item [>\ch\{\synt{text}\ch\}] Insert text before column
-% \item [<\ch\{\synt{text}\ch\}] Insert text after column
-% \end{description}
-%
-% Some others are also defined: don't use them because they do complicated
-% things which are hard to explain and they aren't much use anyway.
-%
-% The default preamble, if you don't supply one of your own, is \lit{rcl}.
-% Most of the time, \lit{rl} is sufficient, although compatibility is more
-% important to me.
-%
-% By default, there is no space between columns, which makes formul\ae\ in an
-% \env{eqnarray} environment look just like formul\ae\ typeset on their own,
-% except that things get aligned in columns.  This is where the default
-% \env{eqnarray} falls down: it leaves |\arraycolsep| space between each
-% column making the thing look horrible.
-%
-% An example would be good here, I think.  This one's from exercise 22.9 of
-% the \textit{\TeX book}.
-%
-% \begin{demo}[w]{Simultaneous equations}
-%\begin{eqnarray}[rcrcrcrl]
-%  10w & + &  3x & + & 3y & + & 18z & = 1 \\
-%   6w & - & 17x &   &    & - &  5z & = 2
-%\end{eqnarray}
-% \end{demo}
-%
-% Choosing a more up-to-date example, here's one demonstrating the \lit{:}
-% column specifier from the \textit{\LaTeX\ Companion}.
+% \subsection{Defining bracketty notations}
+%
+% \DescribeMacro\defbrk
+% Many mathematical notations involve wrapping brackets of various kinds
+% around expressions.  \LaTeX\ doesn't provide much help in defining commands
+% for these notations, which is a shame because it's a good idea to keep the
+% markup semantic rather than visual.  I hereby present the |\defbrk|
+% command:
+% \begin{quote}
+% \syntax{"\\defbrk{"<command>"}["<louter>"]{"<lbrk>"}["<linner>"]"^^A
+%                              "["<rinner>"]{"<rbrk>"}["<router>"]"}
+% \end{quote}
+% The syntax looks intimidating, but it's quite easy really.  The \<command>
+% should be a command name, with a leading |\|.  The \<lbrk> and \<rbrk>
+% arguments, which are the only other mandatory arguments, are the brackets;
+% they should be something that can appear after |\left| and |\right|.  The
+% optional arguments are just extra stuff, commonly spacing, which can appear
+% around the brackets.
+%
+% The main command |\|\<foo> is invoked as
+% \syntax{"\\"<foo>"["<left>"]["<right>"]{"<filling>"}"}.  Slightly
+% unusually, the optional \<left> and \<right> arguments must be either both
+% missing or both provided.  They're the sizes to be applied to the brackets,
+% so they can be something like |\biggl| and |\biggr|, or |\left| and
+% |\right|; they default to empty, so you get the ordinary text-sized
+% brackets if you don't do anything special.  The \<filling> is just the
+% stuff to go in-between the brackets.
+%
+% You also get a number of extra commands:
+% \begin{itemize}
+% \item |\auto|\<foo> uses automatically-resizing brackets, as if you'd asked
+%   for |\left| and |\right|;
+% \item |\big|\<foo>, |\Big|\<foo>, |\bigg|\<foo>, and |\Bigg|\<foo> use the
+%   corresponding standard sizes of brackets; and
+% \item \syntax{"\\bbigg"<foo>"["$a$"]{"$n$"}"} uses the `bbigg' machinery
+%   described above for custom bracket sizes.
+% \end{itemize}
 %
-% \begin{demo}[w]{Lots of equations}
-%\begin{eqnarray}[rl:rl:l]
-% V_i &= v_i - q_i v_j,	& X_i &= x_i - q_i x_j,	&
-%       U_i = u_i, \qquad \mbox{for $i \ne j$}  \label{eq:A} \\
-% V_j &= v_j,           & X_j &= x_j            &
-%       U_j u_j + \sum_{i \ne j} q_i u_i.
-%\end{eqnarray}
-% \end{demo}
+% \begin{figure}
+% \begin{demo}{Custom bracket notation}
+%\defbrk\set{\{}{\}}
+%\defbrk\floor{\lfloor}{\rfloor}
 %
-% We can make things more interesting by adding a plain text column.  Here we
-% go:
+%Let $S = \set{1, 2, 3}$.
 %
-% \begin{demo}[w]{Plain text column}
-%\begin{eqnarray}[rlqqTl]
-%     x  &= y           & by (\ref{eq:A}) \\
-%     x' &= y'          & by definition \\
-% x + x' &= y + y'      & by Axiom~1
-%\end{eqnarray}
+%Let
+%\[ \mu = \biggfloor{\frac{B^{2n}}{m}}
+%   \mpunct. \]
+%Show that $\bigfloor{\floor{a/b}/c} =
+%\floor{a/b c}$.
 % \end{demo}
+% \end{figure}
 %
-% The new features also mean that you don't need to mess about with
-% |\lefteqn| any more.  This is handled by the \lit{L} column type:
+% But wait!  There's more!  Some notation comes in two pieces with a
+% separator in the middle.  For these, there's an even more complicated |*|
+% version of |\defbrk|:
+% \begin{quote}
+% \syntax{"\\defbrk*{"<command>"}["<louter>"]{"<lbrk>"}["<linner>"]"^^A
+%                               "["<mbefore>"]{"<mid>"}["<mafter>"]"^^A
+%                               "["<rinner>"]{"<rbrk>"}["<router>"]"}
+% \end{quote}
+% This defines \<command> as before, but now it takes two arguments, to be
+% surrounded by the \<lbrk> and \<rbrk> brackets and separated by \<mid>.
 %
-% \begin{demo}{Splitting example}
-%\begin{eqnarray*}[Ll]
-%   w+x+y+z = \\
-%    & a+b+c+d+e+{} \\
-%    & f+g+h+i+j
-%\end{eqnarray*}
-% \end{demo}
+% \begin{figure}
+% \begin{demo}{More custom bracket notation}
+%\defbrk*\setcomp{\{}[\,]\vert[][\,]{\}}
 %
-% Finally, just to prove that the spacing's right at last, here's another one
-% from the \textit{Companion}.
-%
-% \begin{demo}{Spacing demonstration}
-%\begin{equation}
-%  x^2 + y^2 = z^2
-%\end{equation}
-%\begin{eqnarray}[rl]
-%  x^2 + y^2 &= z^2 \\
-%        y^2 &< z^2
-%\end{eqnarray}
+%Consider the coset $x + H =
+%\setcomp{x + h}{h \in H}$.
 % \end{demo}
+% \end{figure}
 %
-% Well, that was easy enough.  Now on to numbering.  As you've noticed, the
-% equations above are numbered.  You can use the \env{eqnarray$*$}
-% environment to turn off the numbering in the whole environment, or say
-% |\nonumber| on a line to suppress numbering of that one in particular.
-% More excitingly, you can say \syntax{"\\nonumber["<text>"]"} to choose
-% what text to display.
+% \subsection{The `QED' symbol}
 %
-% A note for cheats: you can use the sparkly new \env{eqnarray} for simple
-% equations simply by specifying \lit{x} as the column description.  Who
-% needs \AmSTeX? |;-)|
+% \DescribeMacro\qed
+% \DescribeMacro\qedrule
+% For use in proofs of theorems, we provide a `QED' symbol which behaves well
+% under bizarre line-splitting conditions.  To use it, just say |\qed|.  The
+% little `\qedrule' symbol is available on its own, by saying |\qedrule|.
+% This also sets |\qedsymbol| if it's not set already.
+% \qed
 %
-% \end{old-eqnarray}
+% \subsection{Punctuation in displays}
+%
+% It's conventional to follow displayed equations with the necessary
+% punctuation for them to fit into the surrounding prose.  This isn't
+% universal: Ian Stewart says in the preface to the third edition of his
+% \emph{Galois Theory}:\footnote{^^A
+%   Chapman \& Hall/CRC Mathematics, 2004; ISBN 1-58488-393-6.} ^^A
+% \begin{quote}
+%   Along the way I made once change that may raise a few eyebrows.  I have
+%   spent much of my career telling students that written mathematics should
+%   have punctuation as well as symbols.  If a symbol or a formula would be
+%   followed by a comma if it were replaced by a word or phrase, then it
+%   should be followed by a comma; however strange the formula then looks.
+%
+%   I still think that punctuation is essential for formulas in the main body
+%   of the text.  If the formula is $t^2 + 1$, say, then it should have its
+%   terminating comma.  But I have come to the conclusion that eliminating
+%   visual junk from the printed page is more important than punctuatory
+%   pedantry, so that when the same formula is \emph{displayed}, for example
+%   \[ t^2 + 1 \]
+%   then it looks silly if the comma is included, like this,
+%   \[ t^2 + 1 \mpunct{,} \]
+%   and everything is much cleaner and less ambiguous without punctuation.
+%
+%   Purists will hate this, though many of them would not have noticed had I
+%   not pointed it out here.  Until recently, I would have agreed.  But I
+%   think it is time we accepted that the act of displaying a formula equips
+%   it with \emph{implicit} (invisible) punctuation.  This is the 21st
+%   century, and typography has moved on.
+% \end{quote}%
+%
+% \DescribeMacro\mpunct
+% I tended to agree with Prof.\ Stewart, even before I read his preface; but
+% now I'm not so sure, and it's clear that we're in the minority.  Therefore,
+% the command |\mpunct| sets its argument as text, a little distance from
+% the preceding mathematics.
 %
 % \implementation
 %
@@ -506,7 +480,7 @@
 %
 % Now we need to do some more calculating (don't you hate it?).  As far as
 % Appendix~G is concerned, $\theta=h(y)=0$, because we want no rule over the
-% top.  
+% top.
 %
 %    \begin{macrocode}
   \@tempdima\ht\tw@%
@@ -717,6 +691,14 @@
 % \end{macro}
 % \end{macro}
 %
+% \begin{macro}{\defop}
+% Defining new operator names.
+%    \begin{macrocode}
+\def\defop{\@ifstar{\defop@\nolimits}{\defop@\limits}}
+\def\defop@#1#2#3{\def#2{\mathop{\operator@font #3}#1}}
+%    \end{macrocode}
+% \end{macro}
+%
 % \begin{macro}{\keys}
 % \begin{macro}{\dom}
 % \begin{macro}{\ran}
@@ -729,14 +711,14 @@
 % And the new operator names.
 %
 %    \begin{macrocode}
-\def\keys{\mathop{\operator@font keys}\nolimits}
-\def\dom{\mathop{\operator@font dom}\nolimits}
-\def\ran{\mathop{\operator@font ran}\nolimits}
-\def\supp{\mathop{\operator@font supp}\nolimits}
-\def\lcm{\mathop{\operator@font lcm}\nolimits}
-\def\poly{\mathop{\operator@font poly}\nolimits}
-\def\negl{\mathop{\operator@font negl}\nolimits}
-\def\ord{\mathop{\operator@font ord}\nolimits}
+\defop*\keys{keys}
+\defop*\dom{dom}
+\defop*\ran{ran}
+\defop*\supp{supp}
+\defop*\lcm{lcm}
+\defop*\poly{poly}
+\defop*\negl{negl}
+\defop*\ord{ord}
 %    \end{macrocode}
 %
 % \end{macro}
@@ -963,8 +945,8 @@
 % macro |\bbigg@|.
 %
 %    \begin{macrocode}
-\def\@bbigg#1{\@ifnextchar[{\@bigg@i{#1}}{\@bigg@i{#1}[\z@]}}
-\def\@bigg@i#1[#2]#3#4{#1{\bbigg@{#2}{#3}{#4}}}
+\def\@bbigg#1{\@testopt{\@bbigg@i{#1}}\z@}
+\def\@bbigg@i#1[#2]{#1{\bbigg@{#2}}}
 %    \end{macrocode}
 %
 % \end{macro}
@@ -1016,6 +998,207 @@
 % \end{macro}
 % \end{macro}
 %
+% \subsection{Bracketty notation}
+%
+% This is mostly an exercise in keeping track of data structures.  Which is a
+% problem, because \TeX\ isn't really very good at data structures.  Our main
+% trick is Church-encoded tuples; i.e., we represent a collection of things
+% as a higher-order function which applies a given projection to the tuple.
+%
+% \begin{macro}{\brk@delim}
+% \begin{macro}{\brk@plain}
+% \begin{macro}{\brk@size}
+% A delimiter keeps track of a before-string, a plain-text delimiter, a sized
+% delimiter, and an after-string.  Rather than just projecting components, we
+% we want to typeset the things, so we provide two macros for doing this: one
+% typesets the plain version (possibly with a prefix), and the other applies
+% a size to the sized delimiter.
+%    \begin{macrocode}
+\def\brk@delim#1#2#3#4#5{#5{#1}{#2}{#3}{#4}}
+\def\brk@plain#1#2#3#4#5{#2#1#3#5}
+\def\brk@size#1#2#3#4#5{#2#1#4#5}
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\brk@bbigg}
+% Before we get really stuck in, here's a quick macro to collect a |\bbigg|
+% argument and pass it to its continuation.
+%    \begin{macrocode}
+\def\brk@bbigg#1{\@testopt{\brk@bbigg@{#1}}\z@}
+\def\brk@bbigg@#1[#2]#3{#1{#2}}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\brk@lefttwo}
+% \begin{macro}{\brk@righttwo}
+% We now begin the two-delimiter machinery proper.  The macro |\defbrk| will
+% package up the delimiters in a macro.  The following two projections pick
+% out the left and right delimiters and apply them to their argument.
+%    \begin{macrocode}
+\def\brk@lefttwo#1#2#3{#2{#1}}
+\def\brk@righttwo#1#2#3{#3{#1}}
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\brk@plaintwo}
+% \begin{macro}{\brk@sizetwo}
+% The next stage is to typeset a full delimited expression, which is what we
+% do here.
+%    \begin{macrocode}
+\def\brk@plaintwo#1#2%
+  {#1{\brk@lefttwo{\brk@plain{}}}#2#1{\brk@righttwo{\brk@plain{}}}}
+\def\brk@sizetwo#1#2#3#4%
+  {#3{\brk@lefttwo{\brk@size{#1}}}#4#3{\brk@righttwo{\brk@size{#2}}}}
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\brk@maintwo}
+% \begin{macro}{\brk@bigtwo}
+% \begin{macro}{\brk@Bigtwo}
+% \begin{macro}{\brk@biggtwo}
+% \begin{macro}{\brk@Biggtwo}
+% \begin{macro}{\brk@bbiggtwo}
+% \begin{macro}{\brk@auto}
+% And finally, the top-level handlers for two-delimiter bracket-notation
+% macros.
+%    \begin{macrocode}
+\def\brk@maintwo#1{\@ifnextchar[{\brk@maintwo@size#1}{\brk@plaintwo#1}}
+\def\brk@maintwo@size#1[#2][#3]{\brk@sizetwo{#2}{#3}#1}
+\def\brk@bigtwo{\brk@sizetwo\bigl\bigr}
+\def\brk@Bigtwo{\brk@sizetwo\Bigl\Bigr}
+\def\brk@biggtwo{\brk@sizetwo\biggl\biggr}
+\def\brk@Biggtwo{\brk@sizetwo\Biggl\Biggr}
+\def\brk@bbiggtwo#1{\brk@bbigg{\brk@bbiggtwo@#1}}
+\def\brk@bbiggtwo@#1#2{\brk@sizetwo{\bbiggl#1{#2}}{\bbiggr#1{#2}}}
+\def\brk@auto{\brk@sizetwo\left\right}
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\brk@leftthree}
+% \begin{macro}{\brk@midthree}
+% \begin{macro}{\brk@rightthree}
+% \begin{macro}{\brk@plainthree}
+% \begin{macro}{\brk@sizethree}
+% Next, the three-delimiter projections.
+%    \begin{macrocode}
+\def\brk@leftthree#1#2#3#4{#2{#1}}
+\def\brk@midthree#1#2#3#4{#3{#1}}
+\def\brk@rightthree#1#2#3#4{#4{#1}}
+\def\brk@plainthree#1#2#3{%
+  #1{\brk@leftthree{\brk@plain{}}}#2%
+  #1{\brk@midthree{\brk@plain\mathrel}}#3%
+  #1{\brk@rightthree{\brk@plain{}}}%
+}
+\def\brk@sizethree#1#2#3#4#5#6{%
+  #4{\brk@leftthree{\brk@size{#1}}}#5%
+  #4{\brk@midthree{\brk@size{#2}}}#6%
+  #4{\brk@rightthree{\brk@size{#3}}}%
+}
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\brk@mainthree}
+% \begin{macro}{\brk@bigthree}
+% \begin{macro}{\brk@Bigthree}
+% \begin{macro}{\brk@biggthree}
+% \begin{macro}{\brk@Biggthree}
+% \begin{macro}{\brk@bbiggthree}
+% And finally, the top-level handlers for three-delimiter bracket-notation
+% macros.
+%    \begin{macrocode}
+\def\brk@mainthree#1{\@ifnextchar[{\brk@mainthree@size#1}{\brk@plainthree#1}}
+\def\brk@mainthree@size#1[#2][#3][#4]{\brk@sizethree{#2}{#3}{#4}#1}
+\def\brk@bigthree{\brk@sizethree\bigl\bigm\bigr}
+\def\brk@Bigthree{\brk@sizethree\Bigl\Bigm\Bigr}
+\def\brk@biggthree{\brk@sizethree\biggl\biggm\biggr}
+\def\brk@Biggthree{\brk@sizethree\Biggl\Biggm\Biggr}
+\def\brk@bbiggthree#1{\brk@bbigg{\brk@bbiggtree@#1}}
+\def\brk@bbiggthree@#1#2%
+  {\brk@sizethree{\bbiggl#1{#2}}{\bbiggm#1{#2}}{\bbiggr#1{#2}}}
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@csname}
+% A brief change of pace: \syntax{"\\@csname{"<cont>"}{"<command>"}"} calls
+% \<cont> with the name of the control sequence \<command>, suitable for
+% inlcuding as part of |\csname|\ldots|\endcsname|.  I use |\string|, and
+% then there's a dance to remove the backslash from the beginning and the
+% space from the end.
+%    \begin{macrocode}
+\def\@csname#1#2{\expandafter\@csname@\string#2 \relax#1}
+\begingroup \lccode`\|=`\\
+  \lowercase{\endgroup \def\@csname@|#1 \relax#2{#2{#1}}}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\defbrk}
+% There's nothing to do now but to define |\defbrk| itself.  This is mostly a
+% tedious exercise in collecting the arguments.
+%    \begin{macrocode}
+\def\defbrk@delim#1{\@testopt{\defbrk@delim@i{#1}}{}}
+\def\defbrk@delim@i#1[#2]#3{%
+  \def\@tempa{#3}%
+  \ifx\@tempa\@empty \expandafter\@firstoftwo
+  \else \expandafter\@secondoftwo \fi
+    {\@testopt{\defbrk@delim@ii{#1}{#2}{}{.}}{}}%
+    {\@testopt{\defbrk@delim@ii{#1}{#2}{#3}{#3}}{}}%
+}
+\def\defbrk@delim@ii#1#2#3#4[#5]{#1{\brk@delim{#2}{#3}{#4}{#5}}}
+\def\defbrk{\@ifstar\defbrk@three\defbrk@two}
+\def\defbrk@two#1{\defbrk@delim{\defbrk@two@i{#1}}}
+\def\defbrk@two@i#1#2{\defbrk@delim{\defbrk@two@ii{#1}{#2}}}
+\def\defbrk@two@ii{\@csname\defbrk@two@iii}
+\def\defbrk@two@iii#1#2#3{%
+  \@namedef{(#1)}##1{##1{#2}{#3}}%
+  \expandafter\defbrk@two@iv\csname(#1)\endcsname{#1}%
+}
+\def\defbrk@two@iv#1#2{%
+  \@namedef{#2}{\brk@maintwo#1}%
+  \@namedef{big#2}{\brk@bigtwo#1}%
+  \@namedef{Big#2}{\brk@Bigtwo#1}%
+  \@namedef{bigg#2}{\brk@biggtwo#1}%
+  \@namedef{Bigg#2}{\brk@Biggtwo#1}%
+  \@namedef{bbigg#2}{\brk@bbiggtwo#1}%
+  \@namedef{auto#2}{\brk@auto#1}%
+}
+\def\defbrk@three#1{\defbrk@delim{\defbrk@three@i{#1}}}
+\def\defbrk@three@i#1#2{\defbrk@delim{\defbrk@three@ii{#1}{#2}}}
+\def\defbrk@three@ii#1#2#3{\defbrk@delim{\defbrk@three@iii{#1}{#2}{#3}}}
+\def\defbrk@three@iii{\@csname\defbrk@three@iv}
+\def\defbrk@three@iv#1#2#3#4{%
+  \@namedef{(#1)}##1{##1{#2}{#3}{#4}}%
+  \expandafter\defbrk@three@v\csname(#1)\endcsname{#1}%
+}
+\def\defbrk@three@v#1#2{%
+  \@namedef{#2}{\brk@mainthree#1}%
+  \@namedef{big#2}{\brk@bigthree#1}%
+  \@namedef{Big#2}{\brk@Bigthree#1}%
+  \@namedef{bigg#2}{\brk@biggthree#1}%
+  \@namedef{Bigg#2}{\brk@Biggthree#1}%
+  \@namedef{bbigg#2}{\brk@bbiggthree#1}%
+}
+%    \end{macrocode}
+% \end{macro}
+%
 % \subsection{The `QED' symbol}
 %
 % \begin{macro}{\qed}
@@ -1035,7 +1218,7 @@
 % \item |\hfill| glue to push the little rule to the end of the line.
 % \item A little square rule `\qedrule', with some small kerns around it.
 % \item A glue item to counter the effect of glue added at the paragraph
-%   boundary. 
+%   boundary.
 % \end{itemize}
 %
 % The vertical mode case is simpler, but less universal.  It copes with
@@ -1081,365 +1264,25 @@
 % \end{macro}
 % \end{macro}
 %
-% \begin{ignore}
-% The following is the original definition of the enhanced eqnarray
-% environment.  It's not supported, although if you can figure out how to
-% extract it, it's all yours.
-% \end{ignore}
+% \subsection{Punctuation in displays}
 %
-% \begin{old-eqnarray}
+% \begin{macro}{\mpunct}
 %
-% \subsection{The sparkly new \env{eqnarray}}
-%
-% Start off by writing a different package.
-%
-%    \begin{macrocode}
-%</package>
-%<*oldeqnarray>
-%    \end{macrocode}
-%
-% \subsubsection{Options handling}
-%
-% We need to be able to cope with \textsf{fleqn} and \textsf{leqno} options.
-% This will adjust our magic modified \env{eqnarray} environment
-% appropriately.
+% This is actually a little more subtle than you'd expect.  If the
+% \package{amstext} package is loaded, or something else has defined the
+% |\text| command, then we should use that; otherwise, just drop a box in and
+% hope for the best.
 %
 %    \begin{macrocode}
-\newif\if@fleqn
-\newif\if@leqno
-\DeclareOption{fleqn}{\@fleqntrue}
-\DeclareOption{leqno}{\@leqnotrue}
-\ProcessOptions
-%    \end{macrocode}
-%
-% This is all really different to the \LaTeX\ version.  I've looked at the
-% various \env{tabular} implementations, the original \env{eqnarray} and the
-% \textit{\TeX book} to see how best to do this, and then went my own way.
-% If it doesn't work it's all my fault.
-%
-% \subsubsection{Some useful registers}
-%
-% The old \LaTeX\ version puts the equation numbers in by keeping a count of
-% where it is in the alignment.  Since I don't know how may columns there are
-% going to be, I'll just use a switch in the preamble to tell me to stop
-% tabbing.
-%
-%    \begin{macrocode}
-\newif\if@eqalast
-%    \end{macrocode}
-%
-% Now define some useful length parameters.  First allocate them:
-%
-%    \begin{macrocode}
-\newskip\eqaopenskip
-\newskip\eqacloseskip
-\newskip\eqacolskip
-\newskip\eqainskip
-%    \end{macrocode}
-%
-% Now assign some default values.  Users can play with these if they really
-% want although I can't see the point myself.
-%
-%    \begin{macrocode}
-\if@fleqn
-  \AtBeginDocument{\eqaopenskip\leftmargini}
-\else
-  \eqaopenskip\@centering
-\fi
-\eqacloseskip\@centering
-\eqacolskip\@centering
-\eqainskip\z@
-%    \end{macrocode}
-%
-% We allow the user to play with the style if this is really wanted.  I dunno
-% why, really.  Maybe someone wants very small alignments.
-%
-%    \begin{macrocode}
-\let\eqa@style\displaystyle
-%    \end{macrocode}
-%
-% \subsubsection{The main environments}
-%
-% We define the toplevel commands here.  They just add in default arguments
-% and then call |\@eqnarray| with a preamble string.  The only difference is
-% the last column they add in -- \env{eqnarray$*$} throws away the last
-% column by sticking it in box~0.  (I used to |\@gobble| it but that caused
-% the |\cr| to be lost.)
-%
-%    \begin{macrocode}
-\def\eqnarray{\@ifnextchar[\eqnarray@i{\eqnarray@i[rcl]}}
-\def\eqnarray@i[#1]{%
-  \@eqnarray{#1!{\hb@xt@\z@{\hss##}\tabskip\z@}}
-}
-\@namedef{eqnarray*}{\@ifnextchar[\eqnarray@s@i{\eqnarray@s@i[rcl]}}
-\def\eqnarray@s@i[#1]{%
-  \@eqnarray{#1!{\nonumber\setbox\z@\hbox{##}\tabskip\z@}}%
-}
-%    \end{macrocode}
-%
-% \subsubsection{Set up the initial display}
-%
-% \begin{macro}{\@eqnarray}
-%
-% The |\@eqnarray| command does most of the initial work.  It sets up some
-% flags and things, builds the |\halign| preamble, and returns.
-%
-%    \begin{macrocode}
-\def\@eqnarray#1{%
-%    \end{macrocode}
-%
-% Start playing with the counter here.  The original does some icky internal
-% playing, which isn't necessary.  The |\if@eqnsw| switch is |true| if the
-% user hasn't supplied an equation number.  The |\if@eqalast| switch is
-% |true| in the final equation-number column.
-%
-%    \begin{macrocode}
-  \refstepcounter{equation}%
-  \@eqalastfalse%
-  \global\@eqnswtrue%
-  \m@th%
-%    \end{macrocode}
-%
-% Set things up for the |\halign| which is coming up.
-%
-%    \begin{macrocode}
-  \openup\jot%
-  \tabskip\eqaopenskip%
-  \let\\\@eqncr%
-  \everycr{}%
-  $$%
-%    \end{macrocode}
-%
-% We'll build the real |\halign| and preamble in a token register.  All we
-% need to do is stuff the header in the token register, clear a switch
-% (that'll be explained later), parse the preamble and then expand the
-% tokens we collected.  Easy, no?
-%
-%    \begin{macrocode}
-  \toks@{\halign to\displaywidth\bgroup}%
-  \@tempswafalse%
-  \eqa@preamble#1\end%
-  \the\toks@\cr%
-}
-%    \end{macrocode}
-%
-% \end{macro}
-%
-% \subsubsection{Parsing the preamble}
-%
-% All this actually involves is reading the next character and building a
-% command from it.  That can pull off an argument if it needs it.  Just make
-% sure we don't fall off the end and we'll be OK.
-%
-%    \begin{macrocode}
-\def\eqa@preamble#1{%
-  \ifx\end#1\else\csname eqa@char@#1\expandafter\endcsname\fi%
+\def\mpunct#1{%
+  \,%
+  \ifx\text\@@undefined\hbox%
+  \else\expandafter\text\fi%
+    {#1}%
 }
 %    \end{macrocode}
 %
-% Adding stuff to the preamble tokens is a simple matter of using
-% |\expandafter| in the correct way.\footnote{^^A
-%   I have no idea why \LaTeX\ uses \cmd\edef\ for building its preamble.  It
-%   seems utterly insane to me -- the amount of bodgery that \env{tabular}
-%   has to go through to make everything expand at the appropriate times is
-%   scary.  Maybe Messrs~Lamport and Mittelbach just forgot about token
-%   registers when they were writing the code.  Maybe I ought to rewrite the
-%   thing properly some time.  Sigh.
-%
-%   As a sort of postscript to the above, I \emph{have} rewritten the
-%   \env{tabular} environment, and made a damned fine job of it, in my
-%   oh-so-humble opinion.  All this \env{eqnarray} stuff has been remoulded
-%   in terms of the generic column-defining things in \package{mdwtab}.
-%   You're reading the documentation of the old version, which isn't
-%   supported any more, so any bugs here are your own problem.}
-%
-%    \begin{macrocode}
-\def\eqa@addraw#1{\expandafter\toks@\expandafter{\the\toks@#1}}
-%    \end{macrocode}
-%
-% Now for some cleverness again.  In order to put all the right bits of
-% |\tabskip| glue in the right places we must \emph{not} terminate each
-% column until we know what the next one is.  We set |\if@tempswa| to be
-% |true| if there's a column waiting to be closed (so it's initially
-% |false|).  The following macro adds a column correctly, assuming we're in
-% a formula.  Other column types make their own arrangements.
-%
-%    \begin{macrocode}
-\def\eqa@add#1{%
-  \if@tempswa%
-    \eqa@addraw{\tabskip\eqainskip&#1}%
-  \else%
-    \eqa@addraw{#1}%
-  \fi%
-  \@tempswatrue%
-}
-%    \end{macrocode}
-%
-% Now to defining column types.  Let's define a macro which allows us to
-% define column types:
-%
-%    \begin{macrocode}
-\def\eqa@def#1{\expandafter\def\csname eqa@char@#1\endcsname}
-%    \end{macrocode}
-%
-% Now we can define the column types.  Each column type must loop back to
-% |\eqa@preamble| once it's finished, to read the rest of the preamble
-% string.  Note the positioning of ord atoms in the stuff below.  This will
-% space out relations and binops correctly when they occur at the edges of
-% columns, and won't affect ord atoms at the edges, because ords pack
-% closely.
-%
-% First the easy onces.  Just stick |\hfil| in the right places and
-% everything will be all right.
-%
-%    \begin{macrocode}
-\eqa@def r{\eqa@add{\hfil$\eqa@style##{}$}\eqa@preamble}
-\eqa@def c{\eqa@add{\hfil$\eqa@style{}##{}$\hfil}\eqa@preamble}
-\eqa@def l{\eqa@add{$\eqa@style{}##$\hfil}\eqa@preamble}
-\eqa@def x{\eqa@add{\hfil$\eqa@style##$\hfil}\eqa@preamble}
-%    \end{macrocode}
-%
-% Now for the textual ones.  This is also fairly easy.
-%
-%    \begin{macrocode}
-\eqa@def T#1{%
-  \eqa@add{}%
-  \if#1l\else\eqa@addraw{\hfil}\fi%
-  \eqa@addraw{##}%
-  \if#1r\else\eqa@addraw{\hfil}\fi%
-  \eqa@preamble%
-}
-%    \end{macrocode}
-%
-% Sort of split types of equations.  I mustn't use |\rlap| here, or
-% everything goes wrong -- |\\| doesn't get noticed by \TeX\ in the same way
-% as |\cr| does.
-%
-%    \begin{macrocode}
-\eqa@def L{\eqa@add{\hb@xt@\z@{$\eqa@style##$\hss}\qquad}\eqa@preamble}
-%    \end{macrocode}
-%
-% The \lit{:} column type is fairly simple.  We set |\tabskip| up to make
-% lots of space and close the current column, because there must be one.^^A
-% \footnote{This is an assumption.}
-%
-%    \begin{macrocode}
-\eqa@def :{%
-  \eqa@addraw{\tabskip\eqacolskip&}\@tempswafalse\eqa@preamble%
-}
-\eqa@def q{\eqa@add{\quad}\@tempswafalse\eqa@preamble}
-%    \end{macrocode}
-%
-% The other column types just insert given text in an appropriate way.
-%
-%    \begin{macrocode}
-\eqa@def >#1{\eqa@add{#1}\@tempswafalse\eqa@preamble}
-\eqa@def <#1{\eqa@addraw{#1}\eqa@preamble}
-%    \end{macrocode}
-%
-% Finally, the magical \lit{!} column type, which sets the equation number.
-% We set up the |\tabskip| glue properly, tab on, and set the flag which
-% marks the final column.
-%
-%    \begin{macrocode}
-\eqa@def !#1{%
-  \eqa@addraw{\tabskip\eqacloseskip&\@eqalasttrue#1}\eqa@preamble%
-}
-%    \end{macrocode}
-%
-% \subsubsection{Newline codes}
-%
-% Newline sequences (|\\|) get turned into calls of |\@eqncr|.  The job is
-% fairly simple, really.  However, to avoid reading `|&|' characters
-% prematurely, we set up a magic brace (from the \package{array} package --
-% this avoids creating ord atoms and other nastyness).
-%
-%    \begin{macrocode}
-\def\@eqncr{%
-  \iffalse{\fi\ifnum0=`}\fi%
-  \@ifstar{\eqacr@i{\@M}}{\eqacr@i{\interdisplaylinepenalty}}%
-}
-\def\eqacr@i#1{\@ifnextchar[{\eqacr@ii{#1}}{\eqacr@ii{#1}[\z@]}}
-\def\eqacr@ii#1[#2]{%
-  \ifnum0=`{}\fi%
-  \eqa@eqnum%
-  \noalign{\penalty#1\vskip#2\relax}%
-}
-%    \end{macrocode}
-%
-% \subsubsection{Setting equation numbers}
-%
-% Before we start, we need to generalise the flush-left number handling bits.
-% The macro |\eqa@eqpos| will put its argument in the right place.
-%
-%    \begin{macrocode}
-\if@leqno
-  \def\eqa@eqpos#1{%
-    \hb@xt@.01\p@{}\rlap{\normalfont\normalcolor\hskip-\displaywidth#1}%
-  }
-\else
-  \def\eqa@eqpos#1{\normalfont\normalcolor#1}
-\fi
-%    \end{macrocode}
-%
-% First we need to move into the right column.  Then we just set the equation
-% number appropriately.  There is some subtlety here, ish.  The |\relax| is
-% important, to delay expansion of the |\if|\dots\ until the new column has
-% been started.  The two helper macros are important too, to hide `|&|'s and
-% `|\cr|'s from \TeX's scanner until the right time.
-%
-%    \begin{macrocode}
-\def\eqa@eqnum{%
-  \relax%
-  \if@eqalast\expandafter\eqa@eqnum@i\else\expandafter\eqa@eqnum@ii\fi%
-}
-\def\eqa@eqnum@i{%
-  \if@eqnsw%
-    \eqa@eqpos{(\theequation)}\stepcounter{equation}%
-  \else%
-    \eqa@eqpos\eqa@number%
-  \fi%
-  \global\@eqnswtrue%
-  \cr%
-}
-\def\eqa@eqnum@ii{&\eqa@eqnum}
-%    \end{macrocode}
-%
-% \subsubsection{Numbering control}
-%
-% This is trivial.  We set the |\if@eqnsw| flag to be |false| and store the
-% text in a macro.
-%
-%    \begin{macrocode}
-\let\nonumber\relax
-\newcommand\nonumber[1][]{\global\@eqnswfalse\global\def\eqa@number{#1}}
-%    \end{macrocode}
-%
-% \subsubsection{Closing the environments off}
-%
-% This is really easy.  Set the final equation number, close the |\halign|,
-% tidy up the equation counter (it's been stepped once too many times) and
-% close the display.
-%
-%    \begin{macrocode}
-\def\endeqnarray{%
-  \eqa@eqnum%
-  \egroup%
-  \global\advance\c@equation\m@ne%
-  $$%
-  \global\@ignoretrue%
-}
-\expandafter\let\csname endeqnarray*\endcsname\endeqnarray
-%    \end{macrocode}
-%
-% Now start up the other package again.
-%
-%    \begin{macrocode}
-%</oldeqnarray>
-%<*package>
-%    \end{macrocode}
-%
-% \end{old-eqnarray}
+%\end{macro}
 %
 % That's all there is.  Byebye.
 %
