summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/gauss
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /macros/latex/contrib/gauss
Initial commit
Diffstat (limited to 'macros/latex/contrib/gauss')
-rw-r--r--macros/latex/contrib/gauss/README21
-rw-r--r--macros/latex/contrib/gauss/gauss-doc.pdfbin0 -> 120119 bytes
-rw-r--r--macros/latex/contrib/gauss/gauss-ex.pdfbin0 -> 33188 bytes
-rw-r--r--macros/latex/contrib/gauss/gauss-ex.tex66
-rw-r--r--macros/latex/contrib/gauss/gauss.sty1897
5 files changed, 1984 insertions, 0 deletions
diff --git a/macros/latex/contrib/gauss/README b/macros/latex/contrib/gauss/README
new file mode 100644
index 0000000000..3aa9b67027
--- /dev/null
+++ b/macros/latex/contrib/gauss/README
@@ -0,0 +1,21 @@
+
+gauss.sty -- A Package for Typesetting Matrix Operations
+--------------------------------------------------------
+
+To use the package, just place the gauss.sty file at a
+location where TeX will find it, and insert
+
+ \usepackage{gauss}
+
+to your document's preamble. This will define a new
+environment gmatrix whose usage is well explained in
+the gauss-doc.dvi file.
+
+This program may be distributed and/or modified under the
+conditions of the LaTeX Project Public License, either
+version 1.1 of this license or (at your option) any later
+version.
+
+---
+
+(c) 2001, 2002 by Manuel Kauers <manuel@kauers.de>
diff --git a/macros/latex/contrib/gauss/gauss-doc.pdf b/macros/latex/contrib/gauss/gauss-doc.pdf
new file mode 100644
index 0000000000..10a20b939d
--- /dev/null
+++ b/macros/latex/contrib/gauss/gauss-doc.pdf
Binary files differ
diff --git a/macros/latex/contrib/gauss/gauss-ex.pdf b/macros/latex/contrib/gauss/gauss-ex.pdf
new file mode 100644
index 0000000000..51ada55ed8
--- /dev/null
+++ b/macros/latex/contrib/gauss/gauss-ex.pdf
Binary files differ
diff --git a/macros/latex/contrib/gauss/gauss-ex.tex b/macros/latex/contrib/gauss/gauss-ex.tex
new file mode 100644
index 0000000000..35a6bafaf5
--- /dev/null
+++ b/macros/latex/contrib/gauss/gauss-ex.tex
@@ -0,0 +1,66 @@
+%
+% This file is part of the gauss package by Manuel Kauers.
+% Its purpose is to demonstrate the usage of the package.
+% See the gauss-doc.dvi file for further information.
+%
+\documentclass{article}
+\usepackage{amsmath}
+\usepackage{gauss}
+\usepackage{amssymb} % to import \leadsto
+
+\begin{document}
+
+ \section{An Example for Gaussian Elimination}
+
+ Consider the real matrix
+ \[
+ A(t):=\begin{pmatrix}
+ 1 & 1 & 1 \\
+ t & 2t & 2 \\
+ t+1 & 0 & 2t
+ \end{pmatrix},
+ \]
+ which depends on a real valued parameter~$t$.
+ We want to find all solutions of the homogenous linear system defined by $A$
+ depending on the parameter~$t$.
+
+ Therefore, we use the Algorithm Gauss:
+ \begin{alignat*}1
+ A(t)=\begin{gmatrix}[p]
+ 1 & 1 & 1 \\
+ t & 2t & 2 \\
+ t+1 & 0 & 2t
+ \rowops
+ \add[-t]{0}{1}
+ \add[-(t+1)]{0}{2}
+ \end{gmatrix}\kern-6.23pt\leadsto&
+ \begin{gmatrix}[p]
+ 1 & 1 & 1 \\
+ 0 & t & 2-t \\
+ 0 & -t-1 & t-1
+ \rowops
+ \add12
+ \mult{2}{\cdot(-1)}
+ \end{gmatrix}\\
+ \leadsto&\begin{gmatrix}[p]
+ 1 & 1 & 1 \\
+ 0 & t & 2-t \\
+ 0 & 1 & -1
+ \rowops
+ \swap12
+ \add[-t]12
+ \mult2{:2}
+ \end{gmatrix}\\
+ \leadsto&\begin{pmatrix}
+ 1 & 1 & 1 \\
+ 0 & 1 & -1 \\
+ 0 & 0 & 1
+ \end{pmatrix}.
+ \end{alignat*}
+
+ \subsection*{Conclusion}
+
+ We have learned that the matrix $A$ defined above is regular for all real
+ valued~$t$, and we hopefully also have learned how to use the gauss package.
+
+\end{document} \ No newline at end of file
diff --git a/macros/latex/contrib/gauss/gauss.sty b/macros/latex/contrib/gauss/gauss.sty
new file mode 100644
index 0000000000..a6da7faa14
--- /dev/null
+++ b/macros/latex/contrib/gauss/gauss.sty
@@ -0,0 +1,1897 @@
+% TODO:
+% * ALLOW FINE TUNING OF ARROW ETC ARRANGEMENT BY PARAMETERS
+% (Suggestion by Antonis Tsolomitis)
+% * BUG: ROWOPMINSIZE AND COLOPMINSIZE DONT WORK IN \swap01 etc.
+% (MAXIMUM COMPUTATION MISSIG)
+% * BUG: ARROWHT HAS TWO CONTRADICTING MEANINGS
+%
+% \title{\texttt{gauss.sty} -- A Package for Typesetting Matrix Operations}
+% \author{Manuel Kauers}
+% \maketitle
+%
+% \MakeShortVerb{\|}
+%
+% \newenvironment{example}
+% {\par\goodbreak\medskip
+% \begin{minipage}[c]{.45\textwidth}
+% \def\switch{\end{minipage}\begin{minipage}[c]{.45\textwidth}\hfil$}
+% \obeylines
+% }{$\hfil\end{minipage}\medskip\goodbreak\par}
+%
+% \begin{abstract}
+% This package provides \LaTeX-macros for typesetting operations on a matrix.
+% By an ``operation on a matrix'' we understand a \textit{row operation}
+% or a \textit{column operation}.
+%
+% The user interface of the package is very straightforward and easy to understand
+% while the results look quite pretty.
+% \end{abstract}
+%
+% \tableofcontents
+%
+% \section{Usage}
+%
+% If you find yourself in search of a package that enables you to easily typeset
+% constructions like
+% \[
+% \begin{gmatrix}[v]
+% 1 & 0 & 5 & 7 & 2 \\
+% 3 & 1 & 1 & 5 & 1 \\
+% 1 & 0 & -7 & 1 & 4 \\
+% 4 & 3 & 6 & 5 & 4\\
+% 1 & 7 & 9 & 4 & 3 \\
+% 0 & 0 & 8 & 0 & -1
+% \rowops
+% \add[-3]01
+% \add[-1]02
+% \swap34
+% \mult5{\cdot 0}
+% \add[x^2-1]53
+% \colops
+% \swap01
+% \mult3{\cdot 1}
+% \add[0]24
+% \end{gmatrix} = \begin{gmatrix}[v]
+% 0 & 1 & 5 & 7 & 2 \\
+% 1 & 0 & -14 & -16 & -5 \\
+% 0 & 0 & -12 & -6 & 2 \\
+% 7 & 1 & 9 & 4 & 3 \\
+% 3 & 4 & 6 & 5 & 4\\
+% 0 & 0 & 0 & 0 & 0
+% \end{gmatrix},
+% \]
+% then this package is what you need.
+% It defines a new matrix environment which is extended by comprehensive macros for
+% typesetting so-called ``operations'' on the matrix.
+% An operation is either a row operation or a column operation, and may involve one or
+% two lines.
+% Examples of such operations arise in the context of Gaussian elimination for solving
+% systems of linear equations in linear algebra: swaping rows, adding the multiple of one
+% row to another, and multiply a row by a constant factor.
+%
+% \subsection{How to typeset matrix operations}
+%
+% \begin{environment}{gmatrix}
+% The package defines a new matrix environment |gmatrix| which
+% behaves just like \LaTeX's and \AmS\LaTeX's |matrix|. It takes an optional
+% parameter \meta{delimtype} to select the matrix delimiters. So, |gmatrix[p]|
+% corresponds to |pmatrix|, |gmatrix[v]| to |vmatrix|, and so on.
+%
+% The |gmatrix| environment can be used exaclty like its brothers and sisters
+% defined by \LaTeX\ and \AmS\LaTeX, for instance:
+% \begin{example}
+% |\begin{gmatrix}[p]|
+% | a & b \\|
+% | c & d|
+% |\end{gmatrix}|
+% \switch
+% \begin{gmatrix}[p] a&b\\ c&d\end{gmatrix}
+% \end{example}
+% The content of the |gmatrix| environment consists of three parts: matrix, row operations,
+% and column operations. The latter two are optional parts, and the ordering of them is
+% arbitrary (i.e.\ row operations may be stated before column operations and vice versa).
+% The matrix part is required, and it must be the first one.
+% \end{environment}
+%
+% \begin{macro}{\rowops}
+% \begin{macro}{\colops}
+% To skip to the next section, there are two comands |\rowops| which swiches to the row
+% operation section, and |\colops| which switches to the column operation section.
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\mult}
+% \begin{macro}{\add}
+% \begin{macro}{\swap}
+% Within the operation sections, you have to state the sequence of operations which are to
+% be typeset. There are the three commands |\mult|, |\add|, and |\swap| to do this. These
+% commands are specified as follows:
+%
+% \begin{enumerate}
+% \item |\mult{i}{\cdot b}| typesets the operation ``multiply the $i$th row (or column)
+% by~$b$'',
+% \item |\swap[a][b]{i}{j}| typesets the operation ``swap the $i$th and the $j$th row
+% (or column)''.
+% $a$~and~$b$ are labels to typeset at the end of the arrows, similar to the $\cdot b$ of
+% the |\mult| command. The command does nothing if $i=j$.
+% \item |\add[a][b]{i}{j}| typesets the operation ``add the $a$-fold of row (or column)~$i$ to
+% row (or column)~$j$. $b$~is a label for the $j$th line. The command does nothing if $i=j$.
+% \end{enumerate}
+%
+% In the standard implementation, optional arguments of |\swap| and the second optional
+% argument of |\add| are ignored. See Section~\ref{ssec:atp} for how to enable them.
+%
+% Rows are counted top-down, and columns are counted from left to right. The uppermost row
+% and the leftmost column have the index~0. There is also the posibility to use |*| as index
+% which causes the typesetting of several operations where |*| runs over all indices. For
+% example, |\mult{*}{5}| in the |\rowops| section of a $n\times n$ matrix is equivalent to
+% state |\mult{0}{5}|,\dots,|\mult{|$n-1$|}{5}|.
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Examples}
+%
+% \begin{itemize}
+% \item A matrix with row operations
+% \begin{example}
+% |\begin{gmatrix}[p]|
+% | 1 & 2 & 3 \\|
+% | 4 & 5 & 6 \\|
+% | 7 & 8 & 9|
+% |\rowops|
+% | \swap{0}{1}|
+% | \mult{0}{\cdot 7}|
+% | \add[5]{1}{2}|
+% |\end{gmatrix}|
+% \switch
+% \begin{gmatrix}[p] 1&2&3\\4&5&6\\7&8&9 \rowops
+% \swap01\mult0{\cdot 7}\add[5]12
+% \end{gmatrix}
+% \end{example}
+% \item The same operations in an other ordering
+% \begin{example}
+% |\begin{gmatrix}[p]|
+% | 1 & 2 & 3 \\|
+% | 4 & 5 & 6 \\|
+% | 7 & 8 & 9|
+% |\rowops|
+% | \add[5]{1}{2}|
+% | \swap{0}{1}|
+% | \mult{0}{\cdot 7}|
+% |\end{gmatrix}|
+% \switch
+% \begin{gmatrix}[p] 1&2&3\\4&5&6\\7&8&9 \rowops
+% \add[5]12\swap01\mult0{\cdot 7}
+% \end{gmatrix}
+% \end{example}
+% \item A matrix with column operations
+% \begin{example}
+% |\begin{gmatrix}[p]|
+% | 1 & 2 & 3 \\|
+% | 4 & 5 & 6 \\|
+% | 7 & 8 & 9|
+% |\colops|
+% | \swap{0}{1}|
+% | \mult{0}{\cdot 7}|
+% | \add[5]{1}{2}|
+% |\end{gmatrix}|
+% \switch
+% \begin{gmatrix}[p] 1&2&3\\4&5&6\\7&8&9 \colops
+% \swap01\mult0{\cdot 7}\add[5]12
+% \end{gmatrix}
+% \end{example}
+% \item A matrix with both row and column operations
+% \begin{example}
+% |\begin{gmatrix}[v]|
+% | 1 & 2 & 3 \\|
+% | 4 & 5 & 6 \\|
+% | 7 & 8 & 9|
+% |\rowops|
+% | \swap{1}{2}|
+% | \mult{2}{\cdot 3}|
+% | \add[-5]{1}{0}|
+% | \add[-3]{1}{2}|
+% |\colops|
+% | \swap{0}{1}|
+% | \mult{0}{\cdot 7}|
+% | \add[5]{1}{2}|
+% |\end{gmatrix}|
+% \switch
+% \begin{gmatrix}[v] 1&2&3\\4&5&6\\7&8&9 \rowops
+% \swap12\mult2{\cdot 3}\add[-5]10\add[-3]12 \colops
+% \swap01\mult0{\cdot 7}\add[5]12
+% \end{gmatrix}
+% \end{example}
+% \item Multiple operations using the |*| index
+% \begin{example}
+% |\begin{gmatrix}[p]|
+% | 1&2&3&4\\|
+% | 5&6&7&8\\|
+% | 9&10&11&12\\|
+% | 13&14&15&16|
+% |\rowops|
+% | \add[x]{0}{*}|
+% |\end{gmatrix}|
+% \switch
+% \begin{gmatrix}[p]
+% 1&2&3&4\\
+% 5&6&7&8\\
+% 9&10&11&12\\
+% 13&14&15&16
+% \rowops \add[x]0*
+% \end{gmatrix}
+% \end{example}
+% Note that the first row is not added to itself, because |\add[x]{0}{0}| has no effect.
+% You can also use two stars:
+% \begin{example}
+% |\begin{gmatrix}[p]|
+% | 1&2&3\\|
+% | 4&5&6\\|
+% | 7&8&9|
+% |\rowops|
+% | \add{*}{*}|
+% |\end{gmatrix}|
+% \switch
+% \kern-1.5em\begin{gmatrix}[p]
+% 1&2&3\\ 4&5&6\\ 7&8&9
+% \rowops \add**
+% \end{gmatrix}\kern-2em
+% \end{example}
+% \item The package clearly also handels a matrix with larger entries correctly:
+% \[
+% \begin{gmatrix}[p]
+% a & b & c & d & e \\
+% 0 & 0 & \displaystyle\int\limits_a^b f(x)\,dx & 0 & 0 \\
+% a & b & c & d & e
+% \rowops
+% \mult{1}{:\displaystyle\int\limits_a^b f(x)\,dx}%
+% \add[-c]10 \add[-1]02
+% \end{gmatrix}
+% \]
+% Even nested |gmatrix|es are possible:
+% \[
+% \def\littleA#1#2#3#4{\begin{gmatrix}[p]#1&#2\\#3&#4\rowops \add[-#3/#1]01\end{gmatrix}}
+% \def\littleB#1#2#3#4#5{\begin{gmatrix}[p]#1&#2\\#3&#4\rowops \mult0{\cdot #5}\end{gmatrix}}
+% \def\littleC#1#2#3#4{\begin{gmatrix}[p]#1&#2\\#3&#4\rowops \swap01\end{gmatrix}}
+% \kern-1.5em
+% \begin{gmatrix}[v]
+% \littleA 2233 & \littleC 1234 & \littleA abcd \\
+% \rule[-20pt]{0pt}{45pt}\littleB 0110\pi & \littleC vwxy & \littleC 1xx{x^2} \\
+% \littleB 12345 & \littleA \cdot \cdot \cdot \cdot & \littleB 54321
+% \rowops
+% \add[\pi^2/6]01
+% \mult1{\cdot 42}
+% \swap02
+% \end{gmatrix}
+% \kern-1.5em
+% \]
+% \end{itemize}
+%
+% \subsection{Adapting the package}\label{ssec:atp}
+%
+% \subsubsection{Distances and dimensions}
+%
+% The appearance of the operation lines and arrows depends strongly on the values of the
+% dimension parameters described in this section.
+%
+% \def\test{\begin{gmatrix}[p]a&b&c\\d&e&f\\g&h&i\rowops
+% \add[x]01\add[y]12\mult1{\cdot y}\swap02\end{gmatrix}}%
+% \def\ttest#1=#2.{\[#1=#2\relax\test\]}%
+%
+% \begin{macro}{\rowarrowsep}
+% \begin{macro}{\colarrowsep}
+% |\rowarrowsep| denotes the distance from the matrix to the operations.
+% For example, |\rowarrowsep=10pt| yields
+% \ttest\rowarrowsep=5pt.
+% and |\rowarrowsep=50pt| yiels
+% \ttest\rowarrowsep=50pt.
+% The corresponding dimension for column operations is |\colarrowsep|.
+% \end{macro}
+% \end{macro}
+% \begin{macro}{\opskip}
+% |\opskip| is the distance between two consecutive operations.
+% For example, |\opskip=6pt| yields
+% \ttest\opskip=6pt.
+% and |\opskip=30pt| yields
+% \ttest\opskip=25pt.
+% The |\opskip| length is responsible for both row and column operations.
+% \end{macro}
+% \begin{macro}{\labelskip}
+% |\labelskip| is the distance between an operation arrow and its labels.
+% For example, |\labelskip=3pt| yields
+% \ttest\labelskip=3pt.
+% and |\labelskip=15pt| yields
+% \ttest\labelskip=15pt.
+% The |\labelskip| length is responsible for both row and column operations.
+% \end{macro}
+% \begin{macro}{\rowopminsize}
+% \begin{macro}{\colopminsize}
+% The length |\rowopminsize| is the minimum amount of a horizontal operation
+% segment to go to the right.
+% For example, |\rowopminsize=3pt| yields
+% \ttest\rowopminsize=3pt.
+% If the horizontal segment ends with an arrow tip and |\rowopminsize| is less than
+% the width of |\leftarrow|, then the width of |\leftarrow| is taken. In the above
+% example, this is the case in the |\add[x]{0}{1}| operation. An example for an
+% exact use of a small value of |\rowopminsize| is the upper horizontal line of
+% |\add[y]{1}{2}|.
+% For comparation, |\rowopminsize=30pt| yields
+% \ttest\rowopminsize=30pt.
+% The corresponding value for column operations is |\colopminsize|.
+% \end{macro}
+% \end{macro}
+%
+% \subsubsection{Labels}
+%
+% The typesetting of a label can be changed by redefining the macros which are responsible
+% for label typesetting. Each label parameter of |\mult|, |\add|, and |\swap| is passed to
+% special ``fontifier'' macros which take one argument and fontify it according to the
+% semantical requirements. Here is a list of those fontifier macros and their default
+% definitions:
+%
+% \begin{macro}{\rowmultlabel}
+% |\rowmultlabel| is the label of a |\mult| operation in the |\rowops| section.
+% Its default definition is \verb?{|\,#1}?.
+% \end{macro}
+% \begin{macro}{\colmultlabel}
+% |\colmultlabel| is the respective macro for the |\colops| section. It is defined
+% to
+% \begin{example}
+% |\underline{\hbox to 1.2em{$\hss\mathstrut{}#1\hss$}}|\kern-20em
+% \switch
+% \end{example}
+% \noindent by default.
+% \end{macro}
+% \begin{macro}{\rowswapfromlabel}
+% |\rowswapfromlabel| is the label of a |\swap| operation in the |\rowops| section
+% which is to place at the first of the two rows. It is defaultly defined to |{}|, i.e.\
+% the label parameter is ignored.
+% \end{macro}
+% \begin{macro}{\colswapfromlabel}
+% |\colswapfromlabel| is the respective macro for the |\colops| section which is
+% also empty by default.
+% \end{macro}
+% \begin{macro}{\rowswaptolabel}
+% |\rowswaptolabel| is like |\rowswapfromlabel|, but for the other row. It is empy
+% by default.
+% \end{macro}
+% \begin{macro}{\colswaptolabel}
+% |\colswaptolabel| is |\rowswaptolabel|'s brother for the |\colops| section.
+% \end{macro}
+% \begin{macro}{\rowaddfromlabel}
+% |\rowaddfromlabel| is the macro for the label of the from-line of an |\add| command.
+% It is defined to |{\scriptstyle#1}| by default.
+% \end{macro}
+% \begin{macro}{\coladdfromlabel}
+% |\coladdfromlabel| is respective macro for the column operations.
+% \end{macro}
+% \begin{macro}{\rowaddtolabel}
+% |\rowaddtolabel| fontifies the label of the to-line of an |\add| command. This macro
+% is defined to |{\scriptscriptstyle +}| by default, i.e.\ it ignores the parameter.
+% \end{macro}
+% \begin{macro}{\coladdtolabel}
+% |\coladdtolabel| is the respective command for the column operation. It behaves
+% likewise.
+% \end{macro}
+%
+% For the following example, all of the above labels were defined to |{#1}|, i.e.\ to identity.
+%
+% \begin{example}
+% |\begin{gmatrix}[p]|
+% | a & b & c \\|
+% | d & e & f \\|
+% | g & h & i|
+% |\colops|
+% | \mult0{m}|
+% | \add[af][at]01|
+% | \swap[sf][st]02|
+% |\rowops|
+% | \mult0{m}|
+% | \add[af][at]01|
+% | \swap[sf][st]02|
+% |\end{gmatrix}|
+% \switch
+% \def\rowmultlabel#1{#1}
+% \def\colmultlabel#1{#1}
+% \def\rowswapfromlabel#1{#1}
+% \def\colswapfromlabel#1{#1}
+% \def\rowswaptolabel#1{#1}
+% \def\colswaptolabel#1{#1}
+% \def\rowaddfromlabel#1{#1}
+% \def\coladdfromlabel#1{#1}
+% \def\rowaddtolabel#1{#1}
+% \def\coladdtolabel#1{#1}
+% \begin{gmatrix}[p]
+% a & b & c \\
+% d & e & f \\
+% g & h & i
+% \colops
+% \mult0{m}
+% \add[af][at]01
+% \swap[sf][st]02
+% \rowops
+% \mult0{m}
+% \add[af][at]01
+% \swap[sf][st]02
+% \end{gmatrix}
+% \end{example}
+%
+% \subsubsection{Matrix delimiters}
+%
+% \begin{macro}{\newmatrix}
+% It is possible to define new delimiter specifiers to |gmatrix|, say |gmatrix[X]|,
+% by defining a matrix environment |Xmatrix|.
+% A definition of |Xmatrix| which fulfills the requirements needed for compatibility
+% with |gmatrix| is provided automatically by the call of
+%
+% \begin{example}
+% |\newmatrix{|\meta{left-delim}|}{|\meta{right-delim}|}{X}|,\kern-20em
+% \switch
+% \end{example}
+%
+% which defines the environment |Xmatrix|. The arguments \meta{left-delim} and
+% \meta{right-delim} need to be compatible to the |\left|-|\right| mechanism of \TeX.
+% As soon as |Xmatrix| exists, it is also possible to use |X| as optional argument
+% to |gmatrix|.
+%
+% By convention, the suffix is one single character. If you try to enter |g@| or
+% the empty string as suffix, nothing is done, otherwise, the definition works
+% as well.
+% \end{macro}
+%
+% \subsection{Features}
+%
+% \begin{itemize}
+% \item You need not care about the width or height of some macro cells,
+% operations are always aligned well, i.e. centered to the column or row.
+% \item Operation elements will not intersect each other, unless you give
+% some very huge labels.
+% \item There is no restriction to the order of operation commands, so you can
+% choose an arbitrary order to achive the best typographic result.
+% \item If no operations are given, the result is exactly the result of
+% the \AmS-\TeX\ |matrix| environment.
+% \item Unlike \AmS's |matrix| environment, there is no limit to the matrix' size
+% in our reimplementation |gmatrix|.
+% \item Nested |gmatrix|'s are possible.
+% \end{itemize}
+%
+% \subsection{Trap doors and hints}
+%
+% \begin{itemize}
+% \item The last row \emph{must not} end with an |\\|, but each other line
+% should end with |\\|.
+% \item The last row is used internally to measure the column's widths.
+% Therefore, if you want to point to a column~$i$, then the last row must have
+% at least $i+1$ entries.
+% \item In row operations, the package considers the width of labels
+% (that is, the width of factors in |\mult| and |\add|). But you have to
+% take care that your labels are not higher than the corresponding line,
+% otherwise they may intersect with other arrows or labels.
+% \item analogously for column operations.
+% \item The package should also run without the |amsmath| package, but if you
+% use that package (which is assumed to be the usual situation), you have to
+% load |gauss| after |amsmath|.
+% \end{itemize}
+%
+% \subsection{Bug parade}
+%
+% A list of submitted bugs and suggested work-arounds or fixes.
+% If you face any bug that is not in the list below, feel free to contact me
+% at |manuel@kauers.de|.
+%
+% \begin{itemize}
+% \item Hans Frederik Nordhaug faced problems with versions of \AmS-\LaTeX\
+% that don't define |*matrix| environments as expected (e.g.\ version 2.13).
+% The current version of |gauss| therefore redefines all those environments
+% using our |\newmatrix| tool, and requires |amsmath| to be loaded prior to
+% the |gauss| package.
+% \item Morten H{\o}gholm suggested the introduction of fontifying macros and
+% the use of changeable lengths as discussed in Section~\ref{ssec:atp}.
+% He also suggested some very fine typographic tunings.
+% \item Herbert Voss found that a |\unitlength=1pt| was missing to make the
+% behaviour of the package independent of redefinitions of |\unitlength|
+% outside |gmatrix|. (Fixed.)
+% \item Michael Hagedorn noticed that signs in entries a treated like
+% binary relations, i.e., wrong spacing is used. (Fixed.)
+% \end{itemize}
+%
+% \StopEventually
+%
+% \section{Implementation}
+%
+% \begin{macrocode}
+\ProvidesPackage{gauss}[2003/01/14]
+\RequirePackage{amsmath}
+\makeatletter
+% \end{macrocode}
+%
+% To avoid naming conflicts with other packages, our private control
+% sequences all start with |\g@|.
+% Permanently public are only the |gmatrix| environment, the fontifying macros (like
+% |\rowaddfromlabel|), and the dimensions (like |\opskip|).
+%
+% The |amsmath| package is not necessarily needed, but if used, it has to be
+% loaded prior to the |gauss| package. This is forced by the |\RequirePackage|
+% command.
+%
+% \subsection{Allocation of registers and definition of common macros}
+%
+% Boxes,\dots
+% \begin{macrocode}
+\newbox\g@trash
+\newbox\g@matrixbox
+\newbox\g@eastbox
+\newbox\g@northbox
+\newbox\g@label
+\newbox\g@b@tmp
+\newbox\g@b@tmpa
+\newbox\g@b@tmpb
+% \end{macrocode}
+% \dots counters,\dots
+% \begin{macrocode}
+\newcount\g@maxrow
+\newcount\g@maxcol
+\newcount\g@maxrow@old
+\newcount\g@maxcol@old
+\newcount\g@c@tmp
+\newcount\g@c@tmpa
+% \end{macrocode}
+% \dots and dimensions \dots
+% \begin{macrocode}
+\newdimen\g@axisHeight
+\newdimen\g@linethickness
+\newdimen\g@tab
+\newdimen\g@arrowht
+\newdimen\g@arrowwd
+\newdimen\g@d@tmp
+\newdimen\g@d@tmpa
+\newdimen\g@d@tmpb
+\newdimen\g@d@tmpc
+\newdimen\g@d@tmpd
+\newdimen\g@d@tmpe
+% \end{macrocode}
+% are allocated.
+%
+% \begin{macro}{\g@for}
+% For frequent use, we define a special loop mechanism, which allowes to
+% iterate over a given interval from a lower bound to a higher one, or
+% reversely. The code to execute is given as the third argument of |\g@for|,
+% using |#1| for the iteration variable that is substituted by |\the\loopCount|
+% for each value in the given bounds.
+%
+% Each of the bounds is also visited. Example: The following code prints out
+% the numbers from 1 to 37, inclusively:
+%
+% \begin{example}
+% |\g@for1\to37\do{#1 }|
+% \switch
+% \end{example}
+%
+% We first need some more control sequences: |\g@loopContent| is defined to the loop's
+% body when the loop is entered.
+% |\g@loopCount| is the variable to increment or decrement with each
+% iteration. |\g@loopEnd| marks the value at which to stop the loop,
+% and |\g@loopStep| contains the direction, i.e. $|\g@loopStep|=-1$ iff
+% $|\g@loopEnd| < \meta{start value}$.
+% \begin{macrocode}
+\def\g@loopContent#1{}
+\newcount\g@loopCount\g@loopCount=0
+\newcount\g@loopEnd\g@loopEnd=1
+\newcount\g@loopStep\g@loopStep=1
+% \end{macrocode}
+% The |\g@loop| command executes the loop initialized by |\g@for|.
+% Each iteration is executed in its own group to avoid side effects and
+% expecially to provide nested loops.
+% \begin{macrocode}
+\def\g@loop{%
+ % base case?
+ \ifnum\g@loopCount=\g@loopEnd\else
+ % no: execute loop body
+ {\expandafter\g@loopContent\expandafter{\the\g@loopCount}}%
+ % increment or decrement the loop variable
+ \advance\g@loopCount\g@loopStep
+ % call \g@loop recursivly.
+ \g@loop
+ \fi
+}
+% \end{macrocode}
+% Finally, here is the definition of |\g@for|. Each value in the interval
+% from |#1| to |#2|, including |#1| and |#2| is visited exactly one time.
+% \begin{macrocode}
+\def\g@for#1\to#2\do#3{%
+ \def\g@loopContent##1{#3}%
+ \g@loopCount=#1
+ \g@loopEnd=#2
+ \ifnum\g@loopEnd>\g@loopCount%
+ \g@loopStep=1
+ \else\g@loopStep=-1
+ \fi
+ \advance\g@loopEnd\g@loopStep % inclusive upper bound
+ \g@loop
+}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\g@checkBounds}
+% The next tool is used by the generic operation commands to check whether or not
+% a given index is valid. If $|#2|\leq|#3|\leq|#4|$ does not hold, a package
+% error is thrown that tells the user what happened.
+%
+% Parameter |#1| contains `r' or `c' to denote ``rows'' or ``columns'',
+% respectively. This piece of information is only used within the construction of
+% the error message.
+%
+% \begin{macro}{\ifg@indexCorrect}
+% The result of |\g@checkBounds| is returned via |\ifg@indexCorrect|.
+% \begin{macrocode}
+\newif\ifg@indexCorrect
+\def\g@checkBounds#1#2#3#4{%
+ \g@indexCorrectfalse
+ \ifnum#2>#3%
+ \PackageError{gauss}{\g@shorterror{#1} #3<#2}{\g@longerror{#1}}
+ \else
+ \ifnum#3>#4%
+ \PackageError{gauss}{\g@shorterror{#1} #3>#4}{\g@longerror{#1}}
+ \else
+ \g@indexCorrecttrue
+ \fi
+ \fi
+}
+% \end{macrocode}
+% We skip the definitions of |\g@shorterror| and |\g@longerror| which serve to
+% produce error messages.
+\def\g@shorterror#1{\ifx r#1 Row \else Column \fi index out of bounds: }
+\def\g@longerror#1{%
+ An index of an operation points to a \ifx r#1 row \else column \fi %
+ that does not exist.\MessageBreak
+ Note that the index of the %
+ \ifx r#1 bottom row \else leftmost column \fi is 0 while the index of the %
+ \ifx r#1 top row \else rightmost column \fi is <number of %
+ \ifx r#1 rows\else columns\fi - 1> .%
+}
+% \end{macro}\end{macro}
+%
+% \begin{macro}{\g@downarrow}
+% For drawing horizontal arrows of arbitrary length, we use the construction
+%
+% \begin{example}
+% |\hbox to|\meta{width}|{$\leftarrowfill$}|\kern-20em
+% \switch\end{example}
+%
+% \noindent which uses Plain-\TeX's |\leftarrowfill|. Unfortunately, there is no
+% vertical correspondence to that mechanism and thus, we have construct something
+% like this by ourselves. We will do so by reimplementing a mechanism that is used
+% by |\left| and |\right| to construct delimiters of arbitrary height.
+%
+% \begin{macrocode}
+\DeclareMathSymbol{\g@downarrowSymb}{\mathord}{largesymbols}{`\y}
+\DeclareMathSymbol{\g@vertlineSymb}{\mathord}{largesymbols}{`\?}
+\def\g@vertline{\hbox{$\g@vertlineSymb$}\kern-\lineskip}%
+% \end{macrocode}
+%
+% After allocating the basic symbols, we define |\g@downarrow| by a recursion
+% which fills up a vbox with the necessary number of |\g@vertline|'s and a
+% final |\g@downarrowSymb|.
+%
+% The resulting vbox has exactly the height given in |#1| (as \TeX-length), and
+% no depth. If |#1| is less than a minimum height, then it is set to that minimum
+% height.
+%
+% \begin{macrocode}
+\def\g@downarrow#1{\vbox{%
+ \vfill
+ \baselineskip\z@\relax
+ \g@d@tmpc=#1\relax
+ \ifdim \g@d@tmpc<\g@arrowht
+ \g@d@tmpc\g@arrowht\relax
+ \fi
+ \g@vlineRec
+ \kern\g@d@tmpc
+ \setbox\g@trash=\hbox{$\g@downarrowSymb$}%
+ \hbox{\raise\dp\g@trash\box\g@trash}%
+}}
+\def\g@vlineRec{%
+ \advance\g@d@tmpc-\g@arrowht
+ \ifdim \g@d@tmpc<\z@ \else
+ \g@vertline
+ \g@vlineRec
+ \fi
+}
+% \end{macrocode}
+%
+% \end{macro}
+%
+% \subsection{Converting floasts and lengths to each other}
+%
+% \begin{macro}{\g@defdim}%
+% \begin{macro}{\g@defdouble}%
+% \begin{macro}{\g@dim}%
+% \begin{macro}{\g@double}%
+% The typesetting of matrix operations is done by use of the |picture|
+% environment of \LaTeX. The macros of that environment require plain
+% numbers, possibly containing a decimal point. Though it is not clearly
+% correct, we will call that data format \emph{float} or \emph{double}.
+%
+% |picture|'s macros do not work if you give them dimensions as input.
+% And since the results of measuring a matrix are necessarily dimensions,
+% we need a mechanism to convert dimensions to floats and vice versa.
+%
+% This mechanism is the topic of the current section.
+%
+% In fact, we almost provide our own data structure whose values can be shown
+% as \TeX\ dimensions or as floats. You can ``construct a new instance'' of
+% that structure either by a dimension (using |\g@defdim|) or by a double
+% (using |\g@defdouble|). In both cases, a macro is defined to be the
+% corresponding double value.
+%
+% Given an instance of our data structure, i.e.\ given a double, you can get
+% its double representation using |\g@double| (this just typesets the double
+% representation), and you can store its value into a \TeX\ dimension using
+% |\g@dim|.
+%
+% Macros for manipulation on floats are defined in the following section.
+%
+% \medskip
+% We first need a macro that cuts away the ``pt''. This is rather tricky because
+% the ``pt'' that arises in the result of some |\the|\meta{counter} has not the
+% catcodes as expected. We can redefine them temporarily but we have to note that
+% constructions like |\g@defdim{|\meta{identifier}|}{12pt}| (i.e.\ giving the length
+% directly) are no longer possible, since the ``pt'' of a directly given length
+% has the ``normal'' catcodes.
+% \begin{macrocode}
+\edef\redo#1{\catcode`p=#1\catcode`t=#1\relax}
+\redo{12}
+\def\g@del#1pt{#1}
+\redo{11}
+% \end{macrocode}
+% Defining a float by a dimension. The first argument expects an idetifier
+% (identifiers are arbitrary strings), and the second argument expects a
+% \TeX\ dimension \emph{register}, i.e. some control sequence |\cs| that
+% evaluates to ``\dots pt'' if you say |\the\cs|.
+%
+% It is not possible to specify a double by directly give a length. Use
+% |\g@defdouble| below in that case.
+% \begin{macrocode}
+\def\g@defdim#1#2{%
+ \edef\g@defdim@arg{\the #2}%
+ \edef\g@defdim@arg{\expandafter\g@del\g@defdim@arg}%
+ \g@defdouble{#1}{\g@defdim@arg}%
+}
+% \end{macrocode}
+% And here is |\g@defdouble|. |#1| should be an identifier and |#2| should
+% be the value to store in float |#1|. To avoid naming conflics with other
+% macros, |#2| is stored into a macro based on |g@@| and the content of |#1|.
+% \begin{macrocode}
+\def\g@defdouble#1#2{%
+ \expandafter\expandafter\expandafter\global
+ \expandafter\edef\csname g@@#1 \endcsname{#2}%
+}
+% \end{macrocode}
+% We now come to the macros for ``reading'' a float. These are |\g@dim| (to
+% read the dimensional representation) and |\g@double| (for the double
+% representation).
+%
+% An error will occur if you try to read the value of a float that was not
+% previously defined. (``Missing number, treated as zero.'')
+%
+% First |\g@dim|: Let |#1| be the identifier and |#2| the \TeX\ dimension
+% registern to store the value of |#1| in.
+% \begin{macrocode}
+\def\g@dim#1#2{%
+ \edef\g@dim@arg{\g@double{#1}}%
+ #2=\g@dim@arg\p@\relax
+}
+% \end{macrocode}
+% And |\g@double| is even simpler:
+% \begin{macrocode}
+\def\g@double#1{%
+ \csname g@@#1 \endcsname
+}
+% \end{macrocode}
+% \end{macro}\end{macro}\end{macro}\end{macro}
+%
+% \subsection{Macros for calculus on floats}
+%
+% We need some macros that provide simple arithmetic calculation on
+% floats. Those are defined now.
+%
+% \begin{macro}{\g@advance}
+% Given a float $f_1$, the following macro performs $f_1 := f_1 + f_2$
+% where $f_2$ may be either a \TeX\ dimension or a float:
+% If |\csname|$f_2$|\encsname| does not evaluate to some control sequence,
+% it is assumed to denote a \TeX\ dimension (e.g. |5pt|, or |\the\something|)
+% \begin{macrocode}
+\def\g@advance#1#2{%
+ \g@dim{#1}{\g@d@tmpa}% f_1 := #1
+ \expandafter\ifx\csname g@@#2 \endcsname\relax
+ \g@d@tmpb=#2% f_2 := #2 (TeX dimension)
+ \else
+ \g@dim{#2}{\g@d@tmpb}% f_2 := #2 (float)
+ \fi
+ \advance\g@d@tmpa\g@d@tmpb\relax% f_1 += f_2
+ \g@defdim{#1}{\g@d@tmpa}% #1 := f_1
+}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\g@min}\begin{macro}{\g@minD}
+% Given two floats $f_1, f_2$ and a \TeX\ dimension $d_3$,
+% the following macro performs $d_3 := \min\{f_1, f_2\}$.
+% \begin{macrocode}
+\def\g@min#1#2#3{%
+ \g@dim{#1}{\g@d@tmpa}% f_1 := #1
+ \g@dim{#2}{\g@d@tmpb}% f_2 := #2
+ \ifdim \g@d@tmpa<\g@d@tmpb
+ #3=\g@d@tmpa
+ \else
+ #3=\g@d@tmpb
+ \fi
+ \relax
+}
+% \end{macrocode}
+% There is a so called $D$-version of the latter macro. By use of |\g@min|,
+% this macro also calculates $\min\{f_1,f_2\}$, but its result is translated
+% into a double representation which is then stored in control sequence |#3|.
+% \begin{macrocode}
+\def\g@minD#1#2#3{%
+ \g@min{#1}{#2}{\g@d@tmpc}%
+ \edef\g@minD@arg{\the\g@d@tmpc}%
+ \edef\g@minD@arg{\expandafter\g@del\g@minD@arg}%
+ \edef#3{\g@minD@arg}%
+}
+% \end{macrocode}
+% \end{macro}\end{macro}
+% \begin{macro}{\g@max}\begin{macro}{\g@maxD}
+% And here is are the two opposite macros of the preceeding two.
+% \begin{macrocode}
+\def\g@max#1#2#3{%
+ \g@dim{#1}{\g@d@tmpa}%
+ \g@dim{#2}{\g@d@tmpb}%
+ \ifdim \g@d@tmpa<\g@d@tmpb
+ #3=\g@d@tmpb
+ \else
+ #3=\g@d@tmpa
+ \fi
+ \relax
+}
+\def\g@maxD#1#2#3{%
+ \g@max{#1}{#2}{\g@d@tmpc}%
+ \edef\g@maxD@arg{\the\g@d@tmpc}%
+ \edef\g@maxD@arg{\expandafter\g@del\g@maxD@arg}%
+ \edef#3{\g@maxD@arg}%
+}
+% \end{macrocode}
+% \end{macro}\end{macro}
+% \begin{macro}{\g@dist}\begin{macro}{\g@distD}
+% Given two floats $f_1, f_2$ and a \TeX\ dimension $d_3$, the following
+% macro performs $d_3 := f_1 - f_2$.
+% \begin{macrocode}
+\def\g@dist#1#2#3{%
+ \g@dim{#1}{\g@d@tmpa}% f_1 := #1
+ \g@dim{#2}{\g@d@tmpb}% f_2 := #2
+ \ifdim \g@d@tmpa<\g@d@tmpb
+ #3=\g@d@tmpb
+ \advance#3 by-\g@d@tmpa
+ \else
+ #3=\g@d@tmpa
+ \advance#3 by-\g@d@tmpb
+ \fi
+ \relax
+}
+% \end{macrocode}
+% Again, we have a $D$-version, where the result is given in double
+% representation.
+% \begin{macrocode}
+\def\g@distD#1#2#3{%
+ \g@dist{#1}{#2}{\g@d@tmpc}%
+ \edef\g@distD@arg{\the\g@d@tmpc}%
+ \edef\g@distD@arg{\expandafter\g@del\g@distD@arg}%
+ \edef#3{\g@distD@arg}%
+}
+% \end{macrocode}
+% \end{macro}\end{macro}
+%
+% \begin{macro}{\g@updateArea}\begin{macro}{\g@update}
+% While the macros that we have seen in this section so far are mainly used
+% for elementary drawing purposes, we now define a slightly more sophisticated
+% macro.
+% It is needed to update the leftmost $x$-values of the so-far matrix operation
+% set (in terms of row operations). It is invoked after adding a new operation
+% to the set.
+%
+% To update a float $f_1$ with respect to $f_2$ is defined to execute
+% $f_1 := \max\{f_1, f_2\}$. This is what the following macro does.
+% \begin{macrocode}
+\def\g@update#1#2{%
+ \g@dim{#2}{\g@d@tmpe}
+ \g@dim{#1}{\g@d@tmpb}
+ \ifdim \g@d@tmpe>\g@d@tmpb
+ \g@defdim{#1}{\g@d@tmpe}%
+ \fi
+}
+% \end{macrocode}
+%
+% The matrix dimensions are stored in floats named
+% $\meta{name} + \meta{index}$ where \meta{name} spcifies the dimension
+% (e.g. ``cy'' for the current $y$ values of a \emph{c}olumn) and \meta{index}
+% is the index of the row/column to which the float's value belongs.
+%
+% Now, the following macro iterates over $i\in\{|#3|,\dots,|#4|\}$ and updates
+% all the floats with name $|#2| + i$ with respect to float |#1|.
+% \begin{macrocode}
+\def\g@updateArea#1#2#3#4{\g@for#3\to#4\do{\g@update{#2##1}{#1}}}
+% \end{macrocode}
+% \end{macro}\end{macro}
+%
+%
+%
+% \subsection{Macros for measurements}
+%
+% The macros defined in this section are used to measure the dimensions
+% of a given matrix and store the measured values into floats.
+%
+% For each row~$i$ of the matrix, the $y$-position of the center of
+% row~$i$ with respect to the bottom of the matrix is stored in a float
+% named $|ry| + i$. Another float $|rx| + i$ is initialized to~$0$. This latter
+% value will always contain the leftmost position at which a new row operation can
+% start without intersecting previous operations that crossed row~$i$.
+%
+% For each row~$j$ of the matrix we similarly define the values
+% $|cx| + i$ and $|cy| + i$. Note that $|cx| + i$ corresponds to $|ry| + i$
+% and $|cy| + i$ corresponds to $|rx| + i$, since column operations grow
+% vertically whereas row operations grow horizontally.
+%
+% \begin{macro}{\g@measureRows}
+% We first consider row measuring. The following macro assumes that the current
+% box is a |\vbox| that only contains a copy of the matrix,
+% i.e. one |\hbox| per row including all the intermediate glues and kerns and
+% whatever. You can initialize what we assume to have by saying
+%
+% \medskip
+% {\obeylines |\vbox{\halign{|\dots|}}| (typeset the matrix)
+% |\box0=\lastbox| (save the matrix)
+% |\vbox{\unhcopy0\g@measureRows}| (measure the row's heights)
+% |\box0| (restore the matrix)}
+% \medskip
+%
+% \noindent Caution: The following macros will not work if the matrix was not
+% constructed with an |\halign| because special knowledge about the structure
+% of |\halign|'s result is used.
+%
+% It is assumed that |\g@d@tmp| initially contains the $y$-position of the
+% matrix's bottom. It is further assumed that |\g@maxrow| contains the total
+% number of rows. These two counters will be modified during the recursion.
+% \begin{macrocode}
+\def\g@measureRows{%
+ \setbox\g@trash\lastbox
+ \ifnum\g@maxrow<0% base case: this box is not part of the matrix
+ \else
+ \ifdim\ht\g@trash=0pt%
+ \advance\g@d@tmp\lastskip\unskip
+ \advance\g@d@tmp\lastkern\unkern
+ \unpenalty
+ \else
+ \advance\g@d@tmp\dp\g@trash
+ \advance\g@d@tmp\g@axisHeight
+ \g@defdim{ry\the\g@maxrow}{\g@d@tmp}%
+ \g@defdim{rx\the\g@maxrow}{\z@}%
+ \advance\g@d@tmp-\g@axisHeight
+ \advance\g@d@tmp\ht\g@trash
+ \advance\g@maxrow-1%
+ \fi
+ \g@measureRows
+ \fi
+}
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\g@measureCols}
+% In fact, the row measurement is the easier case. The measurement of column
+% widths is more complicated by two reasons: 1.\ The number of columns is
+% unknown, and 2.\ we will meet the cells in reverse order.
+%
+% This is why column measurement is implemented in two main steps. First the
+% width of each cell and the distance between two preceeding cells is
+% measured and stored into temporary floats $|ct| + \meta{index}$ (distance) and
+% $|cy| + \meta{index}$ (width), where \meta{index} is counted from back to front.
+% By the way, we count the number of columns.
+%
+% In the base case of the recursion we start a second recursion that will
+% calculate the final results out of the intermediate results and that will
+% arange the indexing properly.
+%
+% What input do we expect? It is assumed that the current box is an |\hbox|
+% whose first item is an |\hbox| of width 100cm (to detect the base case),
+% followed by a copy of the last row of the matrix to measure. See the
+% definition of |g@matrix| to see how such a situation can be constructed.
+%
+% We further assume that |g@d@tmp| is initialized to 0.0pt.
+%
+% \begin{macrocode}
+\def\g@measureCols{%
+ \setbox\g@trash\lastbox
+ \ifdim \wd\g@trash=100cm%
+ % base case. Invert the ordering and sum the dimensions.
+ \g@defdouble{ct\the\g@maxcol}{0}%
+ \g@defdouble{cy\the\g@maxcol}{0}%
+ \global\g@maxcol\g@maxcol
+ \g@c@tmp\g@maxcol
+ \advance\g@c@tmp-1%
+ \g@measureColsSucc
+ \global\advance\g@maxcol-1%
+ \else
+ \ifdim \ht\g@trash=0pt%
+ \advance\g@d@tmp\lastskip\unskip
+ \advance\g@d@tmp\lastkern\unkern
+ \unpenalty
+ \else
+ % use ct temporaryly to store the skip between
+ % colnr + 1 and colnr.
+ \g@defdim{ct\the\g@maxcol}{\g@d@tmp}%
+ \g@d@tmp\z@
+ % use cy temporaryly to store the cell's width.
+ \g@defdim{cy\the\g@maxcol}{\wd\g@trash}%
+ \advance\g@maxcol1%
+ \fi
+ \g@measureCols
+ \fi
+}
+% \end{macrocode}
+% Now, the macro for the second step of the measurement algorithm is defined.
+% This is easier, since we now already know the total number of columns that
+% have been measured. Roughly speaking, we sum their width's from left to right
+% to obtain the $x$-values of the horizontal center of each column. Furthermore,
+% the $y$-values are now initialized to~$0$, and the order is inverted.
+%
+% Knowledge about the implementation of |g@matrix| is used!
+%
+% \begin{macrocode}
+\def\g@measureColsSucc{%
+ \ifnum \g@c@tmp<0\else
+ \g@c@tmpa=\g@maxcol
+ \advance\g@c@tmpa-\g@c@tmp
+ \advance\g@c@tmpa-1
+ \g@dim{cy\the\g@c@tmp}{\g@d@tmpa}% width of this cell
+ \g@dim{ct\the\g@c@tmp}{\g@d@tmpb}% glue right to this cell
+ \advance\g@d@tmp.5\g@d@tmpa%
+ \g@defdouble{cy\the\g@c@tmp}{0}%
+ \g@defdim{cx\the\g@c@tmpa}{\g@d@tmp}%
+ \advance\g@d@tmp.5\g@d@tmpa
+ \advance\g@d@tmp\g@d@tmpb
+ \ifnum \g@c@tmpa=0%
+ \advance\g@d@tmp.5\g@tab
+ \fi
+ \advance\g@c@tmp-1
+ \g@measureColsSucc
+ \fi
+}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\g@measureAxis}
+% This is an easier macro. It measures and defines some common lengths,
+% e.g.\ the distance between bottom line and math axis, and the dimensions
+% of math arrows which are used for drawing arrows in operations.
+% \begin{macrocode}
+\def\g@measureAxis{%
+ % 1. Where is the math axis relative to the ground line?
+ \setbox\g@trash=\hbox{$\vcenter{\hbox to 5pt{}}$}%
+ \global\g@axisHeight=\ht\g@trash
+ % 2. What is the minimum width of a horizontal arrow?
+ \setbox\g@trash=\hbox{$\leftarrow$}%
+ \global\g@arrowwd\wd\g@trash
+ % 3. What is the minimum height of a vertical arrow?
+ \setbox\g@trash=\vbox{\g@vertline}%
+ \global\g@arrowht=\ht\g@trash
+ \global\advance\g@arrowht\dp\g@trash
+ \global\advance\g@arrowht\lineskip
+ % 4. What should be the thickness of ordinary lines?
+ \global\g@linethickness=\fboxrule\relax
+}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\g@measureArea}
+% The last marco of this subsection provides the measurement of
+% a set of floats. (Therefore, it is rather a calculus macro.)
+%
+% Assuming that |#4| is a float identifier and for all $i\in I:=\{|#2|,\dots,|#3|\}$
+% $|#1|+i$ is a float identifier, the macro does
+% \[
+% |#4| := \max_{i\in I}\{|#1| + i\}
+% \]
+% \begin{macrocode}
+\def\g@measureArea#1#2#3#4{%
+ \g@defdim{#4}{\z@}%
+ \g@for#2\to#3\do{%
+ \g@max{#1##1}{#4}{\g@d@tmpe}%
+ \g@defdim{#4}{\g@d@tmpe}%
+ }%
+}
+% \end{macrocode}
+% \end{macro}
+%
+%
+%
+% \subsection{Macros for drawing purposes}
+%
+% This Section defines low level macros for drawing purposes within a
+% |picture| environment by use of floats.
+%
+% \begin{macro}{\g@vline}
+% Let $f_1, f_2$ and~$f_3$ be floats. Then,
+%
+% \begin{example}
+% |\g@vline{|$f_1$|}{|$f_2$|}{|$f_3$|}|
+% \switch\end{example}
+%
+% \noindent draws a vertical line from $(f_1,f_2)$ to $(f_2, f_3)$.
+% \begin{macrocode}
+\def\g@vline#1#2#3{%
+ \g@minD{#2}{#3}{\min}
+ \g@distD{#2}{#3}{\dist}
+ \put(\g@double{#1},\min){\line(0,1){\dist}}
+}
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\g@vvline}
+% Let $f_1, f_2$ and~$f_3$ be floats. Then,
+%
+% \begin{example}
+% |\g@vvline{|$f_1$|}{|$f_2$|}{|$f_3$|}|
+% \switch\end{example}
+%
+% \noindent draws a vertical line of length~$|f_3|$, starting at $(f_1,f_2)$, i.e.\
+% a line from $(f_1,f_2)$ to $(f_1, f_2+f_3)$.
+% \begin{macrocode}
+\def\g@vvline#1#2#3{%
+ \put(\g@double{#1},\g@double{#2}){\line(0,1){\g@double{#3}}}
+}
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\g@varrow}
+% Let $f_1, f_2$ and~$f_3$ be floats. Then,
+%
+% \begin{example}
+% |\g@varrow{|$f_1$|}{|$f_2$|}{|$f_3$|}|
+% \switch\end{example}
+%
+% \noindent draws an arrow from $(f_1, \max\{f_2,f_3\})$ to $(f_1, \min\{f_2,f_3\})$.
+% \begin{macrocode}
+\def\g@varrow#1#2#3{%
+ \g@dim{#2}{\g@d@tmpa}%
+ \g@dim{#3}{\g@d@tmpb}%
+ \advance\g@d@tmpb-\g@d@tmpa
+ \g@cbox{#1}{#2}{\g@downarrow{\g@d@tmpb}}%
+}
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\g@hline}
+% Let $f_1, f_2$ and~$f_3$ be floats. Then,
+%
+% \begin{example}
+% |\g@hline{|$f_1$|}{|$f_2$|}{|$f_3$|}|
+% \switch\end{example}
+%
+% \noindent draws a horizontal line from $(f_1,f_2)$ to $(f_3,f_2)$.
+% \begin{macrocode}
+\def\g@hline#1#2#3{%
+ \g@minD{#1}{#3}{\min}%
+ \g@distD{#1}{#3}{\dist}%
+ \put(\min,\g@double{#2}){\line(1,0){\dist}}%
+}
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\g@hhline}
+% Let $f_1, f_2$ and~$f_3$ be floats. Then,
+%
+% \begin{example}
+% |\g@hhline{|$f_1$|}{|$f_2$|}{|$f_3$|}|
+% \switch\end{example}
+%
+% \noindent draws a horizontal line of length~$|f_3|$, starting at $(f_1,f_2)$,
+% i.e.\ a line from $(f_1,f_2)$ to $(f_1+f_3, f_2)$.
+% \begin{macrocode}
+\def\g@hhline#1#2#3{%
+ \put(\g@double{#1},\g@double{#2}){\line(1,0){\g@double{#3}}}%
+}
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\g@harrow}
+% Let $f_1, f_2$ and~$f_3$ be floats. Then,
+%
+% \begin{example}
+% |\g@harrow{|$f_1$|}{|$f_2$|}{|$f_3$|}|
+% \switch\end{example}
+%
+% \noindent draws an arrow from $(\max\{f_1,f_3\},f_2)$ to $(\min\{f_1,f_3\},f_2)$.
+% \begin{macrocode}
+\def\g@harrow#1#2#3{%
+ \g@dim{#1}{\g@d@tmpa}%
+ \g@dim{#3}{\g@d@tmpb}%
+ \advance\g@d@tmpb-\g@d@tmpa
+ \advance\g@d@tmpb2\p@
+ \g@rbox{#1}{#2}{\hbox to\g@d@tmpb{\leftarrowfill}}%
+}
+% \end{macrocode}
+% \end{macro}
+%
+% The remaining two macros allow to put arbitrary math material to a
+% specified position. Those are used for typesetting so called labels within
+% matrix operations, for example, the factor at an |\add| arrow.
+%
+% \begin{macro}{\g@rbox}
+% The first one is intended to use for row operations.
+% Assuming that |#1|, |#2| are float identifiers and |#3| is math material,
+% we put |#3| into an |\hbox| and put that box to point $(|#1|,|#2|)$.
+%
+% The box will be vertically aligned to |#2| (i.e., the math axis of |#3| will
+% be at height |#2|), and horizontally start at |#1|.
+%
+% The macro puts the math material of |#3| into |\g@label| and just copies its content when
+% using, so you can reuse |\g@label| (e.g.\ for measuring purposes).
+% \begin{macrocode}
+\def\g@rbox#1#2#3{%
+ \setbox\g@label=\hbox{$\relax#3\relax$}%
+ \ht\g@label\z@\dp\g@label\z@
+ \setbox\g@label=\hbox{$\mathstrut\box\g@label$}%
+ \put(\g@double{#1},\g@double{#2})%
+ {\makebox(0,0)[l]{\kern-\p@\copy\g@label}}%
+}
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\g@cbox}
+% The last macro of this section does the corresponding job for columns.
+%
+% Here, |#3| will be centered horizontally to |#1|, whereas |#2| denotes the
+% height of the label's bottom.
+%
+% Again, you can reuse the constructed box, it remains in register |\g@label|.
+% \begin{macrocode}
+\def\g@cbox#1#2#3{%
+ \setbox\g@label=\hbox{$\relax#3\relax$}%
+ \setbox\g@label=\hbox{\raise\dp\g@label\box\g@label}%
+ \put(\g@double{#1},\g@double{#2})%
+ {\makebox(0,0)[b]{\copy\g@label}}%
+}
+% \end{macrocode}
+% \end{macro}
+%
+%
+%
+% \subsection{Generic operation commands}
+%
+% Before |\halign| begins, the matrix construction macro defines, what to do
+% if the matrix is finished. This is defined in |\g@endregion| (see the next
+% section for further information).
+%
+% The |\rowops| and |\colops| commands are temporarily set to |\g@east| or
+% |\g@north|, respectively. Thus, when entering an operation part, the first
+% thing to do is to invoke |\g@endregion| to do the things that have to be
+% done when the matrix input finishes. After that, |\g@endregion| has to be
+% redefined to avoid doing the same process two times. Fortunately, |\g@north|
+% and |\g@east| can easily reuse |\g@endregion| and store there those things
+% that have to be done at the end of a region.
+%
+% Hence, each switching to another part of the matrix input consists of three
+% parts:
+% \begin{enumerate}
+% \item Invoke |\g@endregion| to finish the current input part.
+% \item Redefine |\g@endregion| to do the stuff that has to be done at the end
+% of the region that is now starting. The result of the region is stored into
+% a special box register which is used in the |gmatrix| environment.
+% \item Initialize the new region.
+% \end{enumerate}
+% You can imagine that it is easy to define further regions (e.g.\ for operations
+% to the right or below the matrix).
+%
+% The two predefined regions |\rowops| and |\colops| are very similar, so we will
+% show just one of them in this documentation.
+%
+% \begin{macro}{\g@north}
+% The |\g@north| macro is the generic version of |\colops|, its corresponding
+% part is |\g@east|.
+%
+% \begin{macrocode}
+\def\g@north{%
+% \end{macrocode}
+% 1.\ Finish the current region
+% \begin{macrocode}
+ \g@endregion
+% \end{macrocode}
+% 2.\ Redefine |\g@endregion| and prevent |\colops| from being called again.
+% \begin{macrocode}
+ \gdef\colops{\PackageError{gauss}
+ {Two sets of column operations are specified in %
+ just one matrix. This is not allowed.}}%
+ \gdef\g@endregion{%
+ \end{picture}\egroup
+ \g@measureArea{cy}{0}{\the\g@maxcol}{sum}%
+ \g@dim{sum}{\ht\g@northbox}%
+ \global\setbox\g@northbox=\hbox{%
+ \raise\colarrowsep\box\g@northbox}%
+ }%
+% \end{macrocode}
+% 3.\ Initialization of the |\colops| region: Define the operation macros to be
+% the corresponding private versions of this region (see below), set $|sum|:=0$
+% and start the |picture| environment where the operations are painted in.
+% \begin{macrocode}
+ \def\swap{\g@north@arrow11\colswapfromlabel\colswaptolabel}%
+ \def\add{\g@north@arrow01\coladdfromlabel\coladdtolabel}%
+ \let\mult\g@north@mult
+ \g@defdim{sum}{\z@}%
+ \global\setbox\g@northbox=\hbox\bgroup
+ \begin{picture}(\g@double{w},0)(0,0)
+ \linethickness{\g@linethickness}%
+}
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\g@north@mult}
+% The multiplication macro is the simplest one because it affects only one single
+% column.
+% \begin{macrocode}
+\def\g@north@mult#1#2{%
+ \ifx *#1
+% \end{macrocode}
+% Reduce |*| to a set of numbers.
+% \begin{macrocode}
+ \g@for0\to\g@maxcol\do{\g@north@mult{##1}{#2}}%
+ \else
+% \end{macrocode}
+% Now |#1| is a number. Is it an index?
+% \begin{macrocode}
+ \g@checkBounds{c}{0}{#1}{\the\g@maxcol}%
+ \ifg@indexCorrect
+% \end{macrocode}
+% Yes, it is. Typeset the operation.
+% \begin{macrocode}
+ \g@cbox{cx#1}{cy#1}{\colmultlabel{#2}}%
+ \g@dim{cy#1}{\g@d@tmpc}%
+ \advance\g@d@tmpc\ht\g@label
+ \g@defdim{cy#1}{\g@d@tmpc}%
+ \g@advance{cy#1}{\the\opskip}%
+ \g@update{sum}{cx#1}%
+ \fi
+ \fi
+}
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\g@north@arrow}
+%
+% The |\g@north@arrow| macro is a generalisation of |\swap| and |\add|.
+% It takes the following eight parameters:
+%
+% \begin{itemize}
+% \item |#1|: 0 to make the `from' line non-arrowed, 1 to get an arrow tip
+% \item |#2|: 0 to make the `to' line non-arrowed, 1 to get an arrow tip
+% \item |#3|: macro for `from' label rendering
+% \item |#4|: macro for `to' label rendering
+% \item |#5|: [opt] label of the `from' row
+% \item |#6|: [opt] label of the `to' row
+% \item |#7|: index of the `from' row
+% \item |#8|: index of the `to' row
+% \end{itemize}
+%
+% If only one of the two optional arguments is given, then it is taken as |#5|
+% and |#6| is taken empty. If both are missing, both are taken empty.
+%
+% In |\g@north| above, |\add| is defined to
+% \begin{example}
+% |\g@north@arrow01\coladdfromlabel\coladdtolabel|\kern-20em
+% \switch\end{example}
+% and |\swap| is defined as
+% \begin{example}
+% |\g@north@arrow11\colswapfromlabel\colswaptolabel|\kern-20em
+% \switch\end{example}
+%
+% \begin{macrocode}
+\def\g@north@arrow#1#2#3#4{%
+ \@ifnextchar[%
+ {\g@north@arrow@a{#1}{#2}{#3}{#4}}%
+ {\g@north@arrow@b{#1}{#2}{#3}{#4}{}[]}%
+}
+\def\g@north@arrow@a#1#2#3#4[#5]{%
+ \@ifnextchar[%
+ {\g@north@arrow@b{#1}{#2}{#3}{#4}{#5}}%
+ {\g@north@arrow@b{#1}{#2}{#3}{#4}{#5}[]}%
+}
+\def\g@north@arrow@b#1#2#3#4#5[#6]#7#8{%
+ \ifx *#7
+% \end{macrocode}
+% Reduce star indices to loops of number indices.
+% |**| needs a special handling.
+% \begin{macrocode}
+ \ifx *#8
+ \g@for0\to\g@maxcol\do{%
+ \g@north@arrow@b{#1}{#2}{#3}{#4}{#5}[#6]{##1}{*}}%
+ \else
+% \end{macrocode}
+% Two loops rather than one because going from |#8| down
+% to 0 looks better than going from 0 to |#8|
+% \begin{macrocode}
+ \g@for#8\to0\do{%
+ \g@north@arrow@b{#1}{#2}{#3}{#4}{#5}[#6]{##1}{#8}}%
+ \g@for#8\to\g@maxcol\do{%
+ \g@north@arrow@b{#1}{#2}{#3}{#4}{#5}[#6]{##1}{#8}}%
+ \fi
+ \else
+ \ifx *#8
+% \end{macrocode}
+% Reduce star indices to loops of number indices.
+% \begin{macrocode}
+ \g@for#7\to0\do{%
+ \g@north@arrow@b{#1}{#2}{#3}{#4}{#5}[#6]{#7}{##1}}%
+ \g@for#7\to\g@maxcol\do{%
+ \g@north@arrow@b{#1}{#2}{#3}{#4}{#5}[#6]{#7}{##1}}%
+ \else
+% \end{macrocode}
+% Now, |#7| and |#8| are numbers.
+% \begin{macrocode}
+ \ifnum #7=#8\else
+ \g@checkBounds{c}{0}{#7}{\the\g@maxcol}%
+ \ifg@indexCorrect
+ \g@checkBounds{c}{0}{#8}{\the\g@maxcol}%
+ \ifg@indexCorrect
+% \end{macrocode}
+% Now, |#7| and |#8| are different from each other, and
+% both of them are legal indices.
+% Store the current hights of the operations tower
+% above column |#7| and |#8| into |tmp1| and |tmp2|,
+% respectively.
+% \begin{macrocode}
+ \g@defdouble{tmp1}{\g@double{cy#7}}%
+ \g@defdouble{tmp2}{\g@double{cy#8}}%
+% \end{macrocode}
+% Find out the height of the horizontal connection
+% line.
+% First increment |#7| and |#8| by the minimum amounts.
+% \begin{macrocode}
+ \ifx0#1
+ \g@advance{cy#7}{\the\colopminsize}%
+ \else
+ \g@advance{cy#7}{\the\g@arrowht}%
+ \fi
+ \ifx0#2
+ \g@advance{cy#8}{\the\colopminsize}%
+ \else
+ \g@advance{cy#8}{\the\g@arrowht}%
+ \fi
+% \end{macrocode}
+% Incorporate the columns between |#7| and |#8| into
+% the height. Then |sum| denotes the level of the
+% horizontal line.
+% \begin{macrocode}
+ \g@measureArea{cy}{#7}{#8}{sum}%
+% \end{macrocode}
+% Draw arrows and/or vertical lines from |#7|'s and
+% |#8|'s height up to |sum|.
+% \begin{macrocode}
+ \ifx0#1
+ \g@vline{cx#7}{tmp1}{sum}%
+ \else
+ \g@varrow{cx#7}{tmp1}{sum}%
+ \fi
+ \ifx0#2
+ \g@vline{cx#8}{tmp2}{sum}%
+ \else
+ \g@varrow{cx#8}{tmp2}{sum}%
+ \fi
+% \end{macrocode}
+% Draw the horizontal line.
+% \begin{macrocode}
+ \g@hline{cx#7}{sum}{cx#8}%
+% \end{macrocode}
+% Insert space between the horizontal line and
+% the labels if at least one of the labels |#5| and |#6| is not empty.
+% Typeset the labels into boxes and measure them.
+% \begin{macrocode}
+ \setbox\g@b@tmpa=\hbox{$#3{#5}$}%
+ \setbox\g@b@tmpb=\hbox{$#4{#6}$}%
+ \ifdim\ht\g@b@tmpa>\z@
+ \g@advance{sum}{\the\labelskip}%
+ \else
+ \ifdim\ht\g@b@tmpb>\z@
+ \g@advance{sum}{\the\labelskip}%
+ \fi
+ \fi
+% \end{macrocode}
+% Draw the `from' label if there is one
+% \begin{macrocode}
+ \g@d@tmpc\z@
+ \ifdim\ht\g@b@tmpa>\z@
+ \g@cbox{cx#7}{sum}{\kern-\p@\vcenter{\box\g@b@tmpa}}%
+ \g@d@tmpc=\ht\g@label
+ \fi
+% \end{macrocode}
+% Draw the `to' label if there is one
+% \begin{macrocode}
+ \ifdim\ht\g@b@tmpb>\z@
+ \g@cbox{cx#8}{sum}{\kern-\p@\vcenter{\box\g@b@tmpb}}%
+ \ifdim \ht\g@label>\g@d@tmpc
+ \g@d@tmpc=\ht\g@label
+ \fi
+ \fi
+% \end{macrocode}
+% Advance the sum by the maximum height of the two
+% labels and the desired space between two consecutive
+% operations
+% \begin{macrocode}
+ \g@advance{sum}{\the\g@d@tmpc}%
+ \g@advance{sum}{\the\opskip}%
+% \end{macrocode}
+% Update all column tower heights between |#7| and |#8| to
+% |sum|.
+% \begin{macrocode}
+ \g@updateArea{sum}{cy}{#7}{#8}%
+% \end{macrocode}
+% That's it.
+% \begin{macrocode}
+ \fi
+ \fi
+ \fi
+ \fi
+ \fi
+}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\g@east}
+% \begin{macro}{\g@east@mult}
+%
+% The corresponding eastern macros are very similar to the
+% above defined northern versions. Maybe there is a way
+% to define generic operation commands once for all regions,
+% but this would at least lead to less comprehesive definitions.
+%
+% We skip the definitions of |\g@east|, |\g@east@mult| and |\g@east@arrow|
+% in this documentation.
+%
+\def\g@east{%
+ \g@endregion
+ \def\swap{\g@east@arrow11\rowswapfromlabel\rowswaptolabel}
+ \def\add{\g@east@arrow01\rowaddfromlabel\rowaddtolabel}
+ \let\mult\g@east@mult
+ \g@defdim{sum}{\z@}%
+ \gdef\rowops{\PackageError{gauss}{Two sets of row operations were specified in %
+ just one matrix. This is not allowed.}}
+ \gdef\g@endregion{%
+ \end{picture}\egroup
+ \g@measureArea{rx}{0}{\the\g@maxrow}{sum}%
+ \g@dim{sum}{\wd\g@eastbox}%
+ }%
+ \global\setbox\g@eastbox=\hbox\bgroup
+ \begin{picture}(0,\g@double{h})(0,0)
+ \linethickness{\g@linethickness}%
+}
+\def\g@east@mult#1#2{%
+ \ifx *#1
+ \g@for0\to\g@maxrow\do{\g@east@mult{##1}{#2}}%
+ \else
+ \g@checkBounds{r}{0}{#1}{\the\g@maxrow}%
+ \ifg@indexCorrect
+ \g@rbox{rx#1}{ry#1}{\rowmultlabel{#2}}
+ \g@dim{rx#1}{\g@d@tmpc}\advance\g@d@tmpc\wd\g@label
+ \g@defdim{rx#1}{\g@d@tmpc}%
+ \g@advance{rx#1}{\the\labelskip}%
+ \g@update{sum}{rx#1}%
+ \fi
+ \fi
+}
+%
+\def\g@east@arrow#1#2#3#4{%
+ \@ifnextchar[%
+ {\g@east@arrow@a{#1}{#2}{#3}{#4}}%
+ {\g@east@arrow@b{#1}{#2}{#3}{#4}{}[]}%
+}
+\def\g@east@arrow@a#1#2#3#4[#5]{%
+ \@ifnextchar[%
+ {\g@east@arrow@b{#1}{#2}{#3}{#4}{#5}}%
+ {\g@east@arrow@b{#1}{#2}{#3}{#4}{#5}[]}%
+}
+\def\g@east@arrow@b#1#2#3#4#5[#6]#7#8{%
+ \ifx *#7
+ \ifx *#8
+ \g@for0\to\g@maxrow\do{\g@east@arrow@b{#1}{#2}{#3}{#4}{#5}[#6]{##1}{*}}%
+ \else
+ \g@for#8\to0\do{\g@east@arrow@b{#1}{#2}{#3}{#4}{#5}[#6]{##1}{#8}}%
+ \g@for#8\to\g@maxrow\do{\g@east@arrow@b{#1}{#2}{#3}{#4}{#5}[#6]{##1}{#8}}%
+ \fi
+ \else
+ \ifx *#8
+ \g@for#7\to0\do{\g@east@arrow@b{#1}{#2}{#3}{#4}{#5}[#6]{#7}{##1}}%
+ \g@for#7\to\g@maxrow\do{\g@east@arrow@b{#1}{#2}{#3}{#4}{#5}[#6]{#7}{##1}}%
+ \else
+ \ifnum #7=#8\else
+ \g@checkBounds{r}{0}{#7}{\the\g@maxrow}%
+ \ifg@indexCorrect
+ \g@checkBounds{r}{0}{#8}{\the\g@maxrow}%
+ \ifg@indexCorrect
+ \g@defdouble{tmp1}{\g@double{rx#7}}%
+ \g@defdouble{tmp2}{\g@double{rx#8}}%
+ \ifx0#1
+ \g@advance{rx#7}{\the\rowopminsize}%
+ \else
+ \g@advance{rx#7}{\the\g@arrowwd}%
+ \fi
+ \ifx0#2
+ \g@advance{rx#8}{\the\rowopminsize}%
+ \else
+ \g@advance{rx#8}{\the\g@arrowwd}%
+ \fi
+ \g@measureArea{rx}{#7}{#8}{sum}%
+ \ifx0#1
+ \g@hline{tmp1}{ry#7}{sum}%
+ \else
+ \g@harrow{tmp1}{ry#7}{sum}%
+ \fi
+ \ifx0#2
+ \g@hline{tmp2}{ry#8}{sum}%
+ \else
+ \g@harrow{tmp2}{ry#8}{sum}%
+ \fi
+ \g@vline{sum}{ry#7}{ry#8}%
+ \setbox\g@b@tmpa=\hbox{$#3{#5}$}%
+ \setbox\g@b@tmpb=\hbox{$#4{#6}$}%
+ \ifdim\wd\g@b@tmpa>\z@
+ \g@advance{sum}{\the\labelskip}%
+ \else
+ \ifdim\wd\g@b@tmpb>\z@
+ \g@advance{sum}{\the\labelskip}%
+ \fi
+ \fi
+ \g@d@tmpc\z@
+ \ifdim\wd\g@b@tmpa>\z@
+ \g@rbox{sum}{ry#7}{\kern-\p@\vcenter{\box\g@b@tmpa}}%
+ \g@d@tmpc=\wd\g@label
+ \fi
+ \ifdim\wd\g@b@tmpb>\z@
+ \g@rbox{sum}{ry#8}{\kern-\p@\vcenter{\box\g@b@tmpb}}%
+ \ifdim \wd\g@label>\g@d@tmpc
+ \g@d@tmpc=\wd\g@label
+ \fi
+ \fi
+ \g@advance{sum}{\the\g@d@tmpc}%
+ \g@advance{sum}{\the\opskip}%
+ \g@updateArea{sum}{rx}{#7}{#8}%
+ \fi
+ \fi
+ \fi
+ \fi
+ \fi
+}
+% \end{macro}\end{macro}
+%
+%
+%
+% \subsection{The \texttt{gmatrix} environment}
+%
+% |gmatrix| calls |#1matrix| where |matrix| is redefined to |g@matrix|.
+% |g@matrix| typesets the matrix using |\halign| and stores the
+% operations into box registers |\g@northbox| and |\g@eastbox|, respectively.
+% The matrix itself is stored into |\g@matrixbox|.
+%
+% The ``real'' typesetting is done at the end of |gmatrix|.
+%
+% \begin{environment}{gmatrix}
+% \dots and here is |gmatrix|:
+% \begin{macrocode}
+\newenvironment{gmatrix}[1][]
+{\unitlength=1pt\def\g@environment{#1matrix}%
+ \begin{g@matrix}%
+}{%
+ \end{g@matrix}%
+% \end{macrocode}
+% Delete temporarily the definition of |matrix|.
+% \begin{macrocode}
+ \let\matrix\@empty
+ \let\endmatrix\@empty
+% \end{macrocode}
+% Find out sizes of the matrix. Set |\g@d@tmp| to the height of the matrix.
+% \begin{macrocode}
+ \g@d@tmpa\ht\g@matrixbox \advance\g@d@tmpa\p@
+ \g@d@tmpb\dp\g@matrixbox \advance\g@d@tmpb\p@
+ \g@d@tmp\ht\g@northbox \ht\g@northbox\z@
+ \dp\g@northbox\z@
+ \ifdim \g@d@tmp>\z@
+ \advance\g@d@tmp-\opskip
+ \fi
+ \advance\g@d@tmp.5\ht\g@matrixbox
+ \advance\g@d@tmp.5\dp\g@matrixbox
+% \end{macrocode}
+% Start the matrix environment to get the left delimiter.
+% \begin{macrocode}
+ \begin{\g@environment}%
+% \end{macrocode}
+% Typeset the column operations to the north of the matrix,
+% and the matrix itself.
+% \begin{macrocode}
+ \vcenter{\hbox{%
+ \rlap{\raise\ht\g@matrixbox\box\g@northbox}% north
+ % 1 additional pt above and below the matrix
+ \rule\z@\g@d@tmpa\lower\g@d@tmpb\null
+ \box\g@matrixbox% the matrix itself
+ }}%
+% \end{macrocode}
+% Close the matrix environment to get now the right delimiter.
+% \begin{macrocode}
+ \end{\g@environment}%
+% \end{macrocode}
+% Finally typeset the eastern operations.
+% Insert vertical space of |\g@d@tmp| (the height
+% of the matrix) and horizontal space of |\rowarrowsep| before.
+% \begin{macrocode}
+ \rule\rowarrowsep\z@
+ \rule\z@\g@d@tmp
+ \g@dim{d}{\g@d@tmpa}%
+ \vcenter{\hbox{\lower\g@d@tmpa\box\g@eastbox}}%
+}
+% \end{macrocode}
+% \end{environment}
+% Here is the definition of |\g@endmatrix|. This is the initial |\g@endregion|
+% which is defined within |\begin{gmatrix}| to finish the matrix input.
+% \begin{macrocode}
+\def\g@endmatrix{%
+ \mathstrut\crcr
+ \egroup % end of \halign
+ \egroup % end of \vbox, this contains the matrix
+% \end{macrocode}
+% Save the matrix into matrixbox.
+% \begin{macrocode}
+ \global\setbox\g@matrixbox\lastbox
+% \end{macrocode}
+% Measure the matrix' dimensions.
+% \begin{macrocode}
+ \g@measureAxis
+ \setbox\g@trash=\vbox{%
+ \unvcopy\g@matrixbox
+% \end{macrocode}
+% Copy the last row of the matrix into |\g@eastbox| and reinsert it to the vbox.
+% \begin{macrocode}
+ \global\setbox\g@eastbox=\lastbox
+ \copy\g@eastbox
+ \g@d@tmp\z@ {\g@measureRows}% measure rows
+ }%
+ \setbox\g@trash=\hbox{%
+% \end{macrocode}
+% Insert a box of width 100cm to recognize the beginning of the hbox within the
+% measurement recursion.
+% \begin{macrocode}
+ \hbox to 100cm{.\hfill.}%
+ \unhbox\g@eastbox
+ \g@d@tmp\z@ {\g@measureCols}% measure columns
+ }%
+% \end{macrocode}
+% Determine global dimensions of the matrix (total height, etc.).
+% \begin{macrocode}
+ \g@d@tmpa=\ht\g@matrixbox\advance\g@d@tmpa\dp\g@matrixbox
+ \g@defdim{h}{\g@d@tmpa}%
+ \g@defdim{w}{\wd\g@matrixbox}%
+ \g@defdim{d}{\dp\g@matrixbox}%
+}%
+% \end{macrocode}
+% \begin{environment}{g@matrix}
+% Finally, we have the following definition of |g@matrix|:
+% \begin{macrocode}
+\edef\g@prae{\hfil\noexpand\mathstrut$\relax}
+\edef\g@post{\relax$\hfil}
+\newenvironment{g@matrix}
+{\setbox\g@trash=\hbox\bgroup
+ \global\g@maxrow@old\g@maxrow
+ \global\g@maxcol@old\g@maxcol
+ \global\g@maxrow0%
+ \global\g@maxcol0%
+ \let\rowops\g@east
+ \let\colops\g@north
+ \vbox\bgroup
+ % count rows while typesetting
+ \def\\{\mathstrut\cr\global\advance\g@maxrow1\relax}%
+ \global\let\g@endregion\g@endmatrix
+ \global\g@tab=2\arraycolsep
+ \ialign\bgroup\g@prae##\g@post&&\kern\g@tab\g@prae##\g@post\cr
+}{%
+ \g@endregion
+ \egroup % end of \hbox
+ % enable nested gmatrixes (for DniQ :-)
+ \global\g@maxrow\g@maxrow@old
+ \global\g@maxcol\g@maxcol@old
+ \global\let\g@endregion\g@endmatrix
+ \global\let\rowops\g@east
+ \global\let\colops\g@north
+}
+% \end{macrocode}
+% \end{environment}
+%
+%
+%
+% \subsection{Public tools}
+%
+% \begin{macro}{\newmatrix}
+% The |\newmatrix| command allows to define new matrix environments with
+% special delimiters as described in Section~1.
+%
+% \begin{macrocode}
+\def\newmatrix#1#2#3{%
+ \ifx g#3 \else
+ \ifx {#3}{g@} \else
+ \expandafter\ifx\csname#3matrix\endcsname\relax
+ \newenvironment{#3matrix}%
+ {\left#1\begin{matrix}}{\end{matrix}\right#2}%
+ \else
+ \renewenvironment{#3matrix}%
+ {\left#1\begin{matrix}}{\end{matrix}\right#2}%
+ \fi
+ \fi
+ \fi
+}
+% \end{macrocode}
+%
+% For compatibility reasons, we redefine predefined matrix environments such
+% as |pmatrix|. This is necessary to avoid problems that arise when dealing with
+% earlier \AmS\TeX\ versions.
+%
+% \begin{macrocode}
+\newmatrix()p
+\newmatrix[]b
+\newmatrix\lbrace\rbrace B
+\newmatrix\lvert\rvert v
+\newmatrix\lVert\rVert V
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\rowmultlabel}\begin{macro}{\colmultlabel}
+% \begin{macro}{\rowaddfromlabel}\begin{macro}{\coladdfromlabel}
+% \begin{macro}{\rowaddtolabel}\begin{macro}{\coladdtolabel}
+% \begin{macro}{\rowswapfromlabel}\begin{macro}{\colswapfromlabel}
+% \begin{macro}{\rowswaptolabel}\begin{macro}{\colswaptolabel}
+% Labels of operations are typeset using the so-called fontifying macros
+% described in Section~\ref{ssec:atp}.
+% All of them take exaclty one argument, and they are called within math
+% mode. The user may redefine them to adjust the appearence of operations
+% according to his needs. The following is the standard definition:
+
+% \begin{macrocode}
+\def\rowmultlabel#1{|\,#1}
+\def\rowswapfromlabel#1{}
+\def\rowswaptolabel#1{}
+\def\rowaddfromlabel#1{\scriptstyle #1}
+\def\rowaddtolabel#1{\scriptscriptstyle +}
+\def\colmultlabel#1{%
+ \underline{\hbox to 1.2em{$\hss\mathstrut{}#1\hss$}}%
+}
+\def\colswapfromlabel#1{}
+\def\colswaptolabel#1{}
+\def\coladdfromlabel#1{\scriptstyle #1}
+\def\coladdtolabel#1{\scriptscriptstyle +}
+% \end{macrocode}
+% \end{macro}\end{macro}
+% \end{macro}\end{macro}
+% \end{macro}\end{macro}
+% \end{macro}\end{macro}
+% \end{macro}\end{macro}
+%
+% \begin{macro}{\colarrowsep}
+% \begin{macro}{\rowarrowsep}
+% \begin{macro}{\labelskip}
+% \begin{macro}{\opskip}
+% \begin{macro}{\colopminsize}
+% \begin{macro}{\rowopminsize}
+% Finally, we define the public lengths of Section~\ref{ssec:atp}:
+% \begin{macrocode}
+\newdimen\colarrowsep\colarrowsep=.5em
+\newdimen\rowarrowsep\rowarrowsep=.5em
+\newdimen\opskip\opskip=5pt
+\newdimen\labelskip\labelskip=4pt
+\newdimen\colopminsize\colopminsize=3pt
+\newdimen\rowopminsize\rowopminsize=3pt
+% \end{macrocode}
+% \end{macro}\end{macro}
+% \end{macro}\end{macro}
+% \end{macro}\end{macro}
+%
+% And that's all.
+% \begin{macrocode}
+\makeatother
+% \end{macrocode}
+% \CheckSum{1188}
+% \Finale
+\endinput