From e0c6872cf40896c7be36b11dcc744620f10adf1d Mon Sep 17 00:00:00 2001 From: Norbert Preining Date: Mon, 2 Sep 2019 13:46:59 +0900 Subject: Initial commit --- macros/latex/contrib/gauss/README | 21 + macros/latex/contrib/gauss/gauss-doc.pdf | Bin 0 -> 120119 bytes macros/latex/contrib/gauss/gauss-ex.pdf | Bin 0 -> 33188 bytes macros/latex/contrib/gauss/gauss-ex.tex | 66 ++ macros/latex/contrib/gauss/gauss.sty | 1897 ++++++++++++++++++++++++++++++ 5 files changed, 1984 insertions(+) create mode 100644 macros/latex/contrib/gauss/README create mode 100644 macros/latex/contrib/gauss/gauss-doc.pdf create mode 100644 macros/latex/contrib/gauss/gauss-ex.pdf create mode 100644 macros/latex/contrib/gauss/gauss-ex.tex create mode 100644 macros/latex/contrib/gauss/gauss.sty (limited to 'macros/latex/contrib/gauss') 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 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 Binary files /dev/null and b/macros/latex/contrib/gauss/gauss-doc.pdf 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 Binary files /dev/null and b/macros/latex/contrib/gauss/gauss-ex.pdf 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\\#3\rowops \add[-#3/#1]01\end{gmatrix}} +% \def\littleB#1#2#3#4#5{\begin{gmatrix}[p]#1\\#3\rowops \mult0{\cdot #5}\end{gmatrix}} +% \def\littleC#1#2#3#4{\begin{gmatrix}[p]#1\\#3\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 .% +} +% \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 -- cgit v1.2.3