% generated by GAPDoc2LaTeX from XML source (Frank Luebeck)
\documentclass[a4paper,11pt]{report}
\usepackage{a4wide}
\sloppy
\pagestyle{myheadings}
\usepackage{amssymb}
\usepackage[utf8]{inputenc}
\usepackage{makeidx}
\makeindex
\usepackage{color}
\definecolor{DarkOlive}{rgb}{0.1047,0.2412,0.0064}
\definecolor{FireBrick}{rgb}{0.5812,0.0074,0.0083}
\definecolor{RoyalBlue}{rgb}{0.0236,0.0894,0.6179}
\definecolor{RoyalGreen}{rgb}{0.0236,0.6179,0.0894}
\definecolor{RoyalRed}{rgb}{0.6179,0.0236,0.0894}
\definecolor{LightBlue}{rgb}{0.8544,0.9511,1.0000}
\definecolor{Black}{rgb}{0.0,0.0,0.0}
\definecolor{FuncColor}{rgb}{1.0,0.0,0.0}
%% strange name because of pdflatex bug:
\definecolor{Chapter }{rgb}{0.0,0.0,1.0}

\usepackage{fancyvrb}

\usepackage{pslatex}

\usepackage[pdftex=true,
        a4paper=true,bookmarks=false,pdftitle={Written with GAPDoc},
        pdfcreator={LaTeX with hyperref package / GAPDoc},
        colorlinks=true,backref=page,breaklinks=true,linkcolor=RoyalBlue,
        citecolor=RoyalGreen,filecolor=RoyalRed,
        urlcolor=RoyalRed,pagecolor=RoyalBlue]{hyperref}

% write page numbers to a .pnr log file for online help
\newwrite\pagenrlog
\immediate\openout\pagenrlog =\jobname.pnr
\immediate\write\pagenrlog{PAGENRS := [}
\newcommand{\logpage}[1]{\protect\write\pagenrlog{#1, \thepage,}}
%% were never documented, give conflicts with some additional packages


\newcommand{\GAP}{\textsf{GAP}}

\begin{document}

\logpage{[ 0, 0, 0 ]}
\begin{titlepage}
\begin{center}{\Huge \textbf{ The \textsf{Gauss} Package Manual\mbox{}}}\\[1cm]
\hypersetup{pdftitle= The \textsf{Gauss} Package Manual}
\markright{\scriptsize \mbox{}\hfill  The \textsf{Gauss} Package Manual \hfill\mbox{}}
{\Large \textbf{Extended Gauss Functionality for \textsf{GAP}\mbox{}}}\\[1cm]
{ Version 2009.11.09 \mbox{}}\\[1cm]
{November 2009\mbox{}}\\[1cm]
\mbox{}\\[2cm]
{\large \textbf{Simon Goertzen\\
    \mbox{}}}\\
\hypersetup{pdfauthor=Simon Goertzen\\
    }
\end{center}\vfill

\mbox{}\\
{\mbox{}\\
\small \noindent \textbf{Simon Goertzen\\
    } --- Email: \href{mailto://simon.goertzen@rwth-aachen.de} {\texttt{simon.goertzen@rwth-aachen.de}}\\
 --- Homepage: \href{http://wwwb.math.rwth-aachen.de/goertzen/} {\texttt{http://wwwb.math.rwth-aachen.de/goertzen/}}\\
 --- Address: \begin{minipage}[t]{8cm}\noindent
 Lehrstuhl B f{\"u}r Mathematik\\
 Templergraben 64\\
 52062 Aachen\\
 (Germany) \end{minipage}
}\\
\end{titlepage}

\newpage\setcounter{page}{2}
{\small 
\section*{Abstract}
\logpage{[ 0, 0, 1 ]}
This document explains the primary uses of the \textsf{Gauss} package. Included is a documented list of the most important methods and
functions needed to work with sparse matrices and the algorithms provided by
the \textsf{Gauss} package. \mbox{}}\\[1cm]
{\small 
\section*{Copyright}
\logpage{[ 0, 0, 2 ]}
{\copyright} 2007-2009 by Simon Goertzen

 This package may be distributed under the terms and conditions of the GNU
Public License Version 2. \mbox{}}\\[1cm]
{\small 
\section*{Acknowledgements}
\logpage{[ 0, 0, 3 ]}
The \textsf{Gauss} package would not have been possible without the helpful contributions by 
\begin{itemize}
\item Max Neunh{\"o}ffer, University of St Andrews, and
\item Mohamed Barakat, Lehrstuhl B f{\"u}r Mathematik, RWTH Aachen.
\end{itemize}
 Many thanks to these two and the Lehrstuhl B f{\"u}r Mathematik in general. It
should be noted that the \textsf{GAP} algorithms for \texttt{SemiEchelonForm} and other methods formed an important and informative basis for the
development of the extended Gaussian algorithms. This manual was created with
the help of the \textsf{GAPDoc} package by F. L{\"u}beck and M. Neunh{\"o}ffer \cite{GAPDoc}. \mbox{}}\\[1cm]
\newpage

\def\contentsname{Contents\logpage{[ 0, 0, 4 ]}}

\tableofcontents
\newpage

 
\chapter{\textcolor{Chapter }{Introduction}}\label{chap:intro}
\logpage{[ 1, 0, 0 ]}
\hyperdef{L}{X7DFB63A97E67C0A1}{}
{
 
\section{\textcolor{Chapter }{Overview over this manual}}\label{sec:overview}
\logpage{[ 1, 1, 0 ]}
\hyperdef{L}{X786BACDB82918A65}{}
{
  Chapter \ref{chap:intro} is concerned with the technical details of installing and running this
package. Chapter \ref{chap:EGF} answers the question why and how the \textsf{GAP} functionality concerning a sparse matrix type and gaussian algorithms was
extended. The following chapters are concerned with the workings of the sparse
matrix type (\ref{chap:SM}) and sparse Gaussian algorithms (\ref{chap:Gauss}). Included is a documented list of the most important methods and functions
needed to work with sparse matrices and the algorithms provided by the \textsf{Gauss} package. Anyone interested in source code should just check out the files in
the \texttt{gap/pkg/Gauss/gap/} folder ($\to$ Appendix \ref{FileOverview}). }

   
\section{\textcolor{Chapter }{Installation of the \textsf{Gauss} Package}}\label{install}
\logpage{[ 1, 2, 0 ]}
\hyperdef{L}{X78AD64B87DEF5CE9}{}
{
  \index{\textsf{Gauss}} To install this package just extract the package's archive file to the GAP \texttt{pkg/} directory. The \textsf{Gauss} package utilizes some \textsf{C}-code by Max Neunhoeffer that has to be compiled before you can load Gauss. To
compile the code, first run \texttt{./configure}. If the package is not installed in the \texttt{pkg/} subdirectory of \textsf{GAP}'s root directory you will need to provide the correct path to the latter.
This will create a makefile. Complete the installation of the package by
running \texttt{make}. Recompiling the documentation is possible by the command \texttt{make doc} in the Gauss directory, but this should not be necessary.

 By default the \textsf{Gauss} package is not automatically loaded by \textsf{GAP} when it is installed. You must load the package with \texttt{LoadPackage("Gauss");} before its functions become available. Please, send me an e-mail if you have
any questions, remarks, suggestions, etc. concerning \textsf{Gauss}. Also, I would like to hear about applications of this package.\\
 Simon Goertzen\\
 }

 }

 
\chapter{\textcolor{Chapter }{Extending Gauss Functionality}}\label{chap:EGF}
\logpage{[ 2, 0, 0 ]}
\hyperdef{L}{X823150E97BE77525}{}
{
 
\section{\textcolor{Chapter }{The need for extended functionality}}\label{sec:need}
\logpage{[ 2, 1, 0 ]}
\hyperdef{L}{X84F709227E5EEB55}{}
{
 \textsf{GAP} has a lot of functionality for row echelon forms of matrices. These can be
called by \texttt{SemiEchelonForm} and similar commands. All of these work for the \textsf{GAP} matrix type over fields. However, these algorithms are not capable of
computing a reduced row echelon form (RREF) of a matrix, there is no way to
"Gauss upwards". While this is not neccessary for things like Rank or Kernel
computations, this was one in a number of missing features important for the
development of the \textsf{GAP} package \textsf{homalg} by M. Barakat \cite{homalg-package}.



 Parallel to this development I worked on \textsf{SCO} \cite{SCO}, a package for creating simplicial sets and computing the cohomology of
orbifolds, based on the paper "Simplicial Cohomology of Orbifolds" by I.
Moerdijk and D. A. Pronk \cite{MP_SCO}. Very early on it became clear that the cohomology matrices (with entries in
{\ensuremath{\mathbb Z}} or finite quotients of {\ensuremath{\mathbb Z}})
would grow exponentially in size with the cohomology degree. At one point in
time, for example, a 50651 x 1133693 matrix had to be handled.



 It should be quite clear that there was a need for a sparse matrix data type
and corresponding Gaussian algorithms. After an unfruitful search for a
computer algebra system capable of this task, the \textsf{Gauss} package was born - to provide not only the missing RREF algorithms, but also
support a new data type, enabling \textsf{GAP} to handle sparse matrices of almost arbritrary size.



 I am proud to tell you that, thanks to optimizing the algorithms for matrices
over GF(2), it was possible to compute the GF(2)-Rank of the matrix mentioned
above in less than 20 minutes with a memory usage of about 3 GB. }

 
\section{\textcolor{Chapter }{The applications of the \textsf{Gauss} package algorithms}}\label{sec:app}
\logpage{[ 2, 2, 0 ]}
\hyperdef{L}{X7F21EDDF81C27747}{}
{
 Please refer to \cite{homalg-project} to find out more about the \textsf{homalg} project and its related packages. Most of the motivation for the algorithms in
the \textsf{Gauss} package can be found there. If you are interested in this project, you might
also want to check out my \textsf{GaussForHomalg} \cite{GaussForHomalg} package, which, just as \textsf{RingsForHomalg} \cite{RingsForHomalg} does for external Rings, serves as the connection between \textsf{homalg} and \textsf{Gauss}. By allowing \textsf{homalg} to delegate computational tasks to \textsf{Gauss} this small package extends \textsf{homalg}'s capabilities to dense and sparse matrices over fields and rings of the form ${\ensuremath{\mathbb Z}} / \langle p^n \rangle$.

 For those unfamiliar with the \textsf{homalg} project let me explain a couple of points. As outlined in \cite{BR} by D. Robertz and M. Barakat homological computations can be reduced to three
basic tasks:

 
\begin{itemize}
\item Computing a row basis of a module (\texttt{BasisOfRowModule}).
\item Reducing a module with a basis (\texttt{DecideZeroRows}).
\item Compute the relations between module elements (\texttt{SyzygiesGeneratorsOfRows}).
\end{itemize}
 In addition to these tasks only relatively easy tools for matrix manipulation
are needed, ranging from addition and multiplication to finding the zero rows
in a matrix. However, to reduce the need for communication it might be helpful
to supply \textsf{homalg} with some more advanced procedures.



 While the above tasks can be quite difficult when, for example, working in
noncommutative polynomial rings, in the \textsf{Gauss} case they can all be done as long as you can compute a Reduced Row Echelon
Form. This is clear for \texttt{BasisOfRowModule}, as the rows of the RREF of the matrix are already a basis of the module. \texttt{EchelonMat} (\ref{EchelonMat}) is used to compute RREFs, based on the \textsf{GAP} internal method \texttt{SemiEchelonMat} for Row Echelon Forms.



 Lets look at the second point, the basic function \texttt{DecideZeroRows}: When you face the task of reducing a module $A$ with a given basis $B$, you can compute the RREF of the following block matrix: \begin{center}
\begin{tabular}{|c|c|}\hline
  $\begin{array}{ccc} 1&\\ &\ddots&\\ &&1\\ \end{array}$ &
A\\
\hline
0&
B\\
\hline
\end{tabular}\\[2mm]
\end{center}

 By computing the RREF (notice how important "Gaussing upwards" is here) $A$ is reduced with $B$. However, the left side of the matrix just serves the single purpose of
tricking the Gaussian algorithms into doing what we want. Therefore, it was a
logical step to implement \texttt{ReduceMat} (\ref{ReduceMat}), which does the same thing but without needing unneccessary columns.

 Note: When, much later, it became clear that it was important to compute the
transformation matrices of the reduction, \texttt{ReduceMatTransformation} (\ref{ReduceMatTransformation}) was born, similar to \texttt{EchelonMatTransformation} (\ref{EchelonMatTransformation}). This corresponds to the \textsf{homalg} procedure \texttt{DecideZeroRowsEffectively}.



 The third procedure, \texttt{SygygiesGeneratorsOfRows}, is concerned with the relations between rows of a matrix, each row
representing a module element. Over a field these relations are exactly the
kernel of the matrix. One can easily see that this can be achieved by taking a
matrix \begin{center}
\begin{tabular}{|c|c|}\hline
A&
  $\begin{array}{ccc} 1&\\ &\ddots&\\ &&1\\ \end{array}$ \\
\hline
\end{tabular}\\[2mm]
\end{center}

 and computing its Row Echelon Form. Then the row relations are generated by
the rows to the right of the zero rows of the REF. There are two problems with
this approach: The computation diagonalizes the kernel, which might not be
wanted, and, much worse, it does not work at all for rings with zero divisors.
For example, the $1 \times 1$ matrix $[2 + 8{\ensuremath{\mathbb Z}}]$ has a row relation $[4 + 8{\ensuremath{\mathbb Z}}]$ which would not have been found by this method.

 Approaching this problem led to the method \texttt{EchelonMatTransformation} (\ref{EchelonMatTransformation}), which additionally computes the transformation matrix $T$, such that RREF $= T \cdot M$. Similar to \texttt{SemiEchelonMatTransformation}, $T$ is split up into the rows needed to create the basis vectors of the RREF, and
the relations that led to zero rows. Focussing on the computations over
fields, it was an easy step to write \texttt{KernelMat} (\ref{KernelMat}), which terminates after the REF and returns the kernel generators.

 The syzygy computation over ${\ensuremath{\mathbb Z}} / \langle p^n \rangle$ was solved by carefully keeping track of basis vectors with a zero-divising
head. If, for $ v = (0,\ldots,0,h,*,\ldots,*), h \neq 0,$ there exists $g \neq 0$ such that $g \cdot h = 0$, the vector $g \cdot v$ is regarded as an additional row vector which has to be reduced and can be
reduced with. After some more work this allowed for the implementation of \texttt{KernelMat} (\ref{KernelMat}) for matrices over ${\ensuremath{\mathbb Z}} / \langle p^n \rangle$.

 This concludes the explanation of the so-called basic tasks \textsf{Gauss} has to handle when called by \textsf{homalg} to do matrix calculations. Here is a tabular overview of the current
capabilities of \textsf{Gauss} ($p$ is a prime, $n \in {\ensuremath{\mathbb N}}$):

 \begin{center}
\begin{tabular}{|c||c|c|c|c|c|}\hline
Matrix Type:&
Dense&
Dense&
Sparse&
Sparse&
Sparse\\
\hline
Base Ring:&
Field&
${\ensuremath{\mathbb Z}} / \langle p^n \rangle$&
Field&
GF(2)&
${\ensuremath{\mathbb Z}} / \langle p^n \rangle$\\
\hline
\hline
RankMat&
\textsf{GAP}&
n.a.&
+&
++&
n.a.\\
\hline
EchelonMat&
+&
-&
+&
++&
+\\
\hline
EchelonMatTransf.&
+&
-&
+&
++&
+\\
\hline
ReduceMat&
+&
-&
+&
++&
+\\
\hline
ReduceMatTransf.&
+&
-&
+&
++&
+\\
\hline
KernelMat&
+&
-&
+&
++&
+\\
\hline
\end{tabular}\\[2mm]
\end{center}

 As you can see, the development of hermite algorithms was not continued for
dense matrices. There are two reasons for that: \textsf{GAP} already has very good algorithms for {\ensuremath{\mathbb Z}}, and for small
matrices the disadvantage of computing over {\ensuremath{\mathbb Z}},
potentially leading to coefficient explosion, is marginal. }

 }

 
\chapter{\textcolor{Chapter }{The Sparse Matrix Data Type}}\label{chap:SM}
\logpage{[ 3, 0, 0 ]}
\hyperdef{L}{X7901751583E1B976}{}
{
 
\section{\textcolor{Chapter }{The inner workings of \textsf{Gauss} sparse matrices}}\label{sec:workings}
\logpage{[ 3, 1, 0 ]}
\hyperdef{L}{X81E717927E4029AB}{}
{
 When doing any kind of computation there is a constant conflict between memory
load and speed. On the one hand, memory usage is bounded by the total
available memory, on the other hand, computation time should also not exceed
certain proportions. Memory usage and CPU time are generally inversely
proportional, because the computer needs more time to perform operations on a
compactified data structure. The idea of sparse matrices mirrors exactly the
need for less memory load, therefore it is natural that sparse algorithms take
more time than dense ones. However, if the matrix is sufficiently large and
sparse at the same time, sparse algorithms can easily be faster than dense
ones while maintaining minimal memory load.

 It should be noted that, although matrices that appear naturally in
homological algebra are almost always sparse, they do not have to stay sparse
under (R)REF algorithms, especially when the computation is concerned with
transformation matrices. Therefore, in a perfect world there should be ways
implemented to not only find out which data structure to use, but also at what
point to convert from one to the other. This was, however, not the aim of the \textsf{Gauss} package and is just one of many points in which this package could be
optimized or extended. Take a look at this matrix $M$: \begin{center}
\begin{tabular}{|ccccc|}\hline
0&
0&
2&
9&
0\\
0&
5&
0&
0&
0\\
0&
0&
0&
1&
0\\
\hline
\end{tabular}\\[2mm]
\end{center}

 The matrix $M$ carries the same information as the following table, if and only if you know
how many rows and columns the matrix has. There is also the matter of the base
ring, but this is not important for now: \begin{center}
\begin{tabular}{|cc|}\hline
(i,j)&
Entry\\
\hline
(1,3)&
2\\
(1,4)&
9\\
(2,2)&
5\\
(3,4)&
1\\
\hline
\end{tabular}\\[2mm]
\end{center}

 This table relates each index tuple to its nonzero entry, all other matrix
entries are defined to be zero. This only works for known dimensions of the
matrix, otherwise trailing zero rows and columns could get lost (notice how
the table gives no hint about the existence of a 5th column). To convert the
above table into a sparse data structure, one could list the table entries in
this way:

 \begin{center}
\begin{tabular}{c}$[ [ 1, 3, 2 ], [ 1, 4, 9 ], [ 2, 2, 5 ], [ 3, 4, 1 ] ]$\\
\end{tabular}\\[2mm]
\end{center}

 However, this data structure would not be very efficient. Whenever you are
interested in a row $i$ of $M$ (this happens all the time when performing Gaussian elimination) the whole
list would have to be searched for 3-tuples of the form $[ i, *, * ]$. This is why I tried to manage the row index by putting the tuples into the
corresponding list entry:\\
 \begin{center}
\begin{tabular}{l}$[ [ 3, 2 ], [ 4, 9 ] ],$\\
$[ [ 2, 5 ] ],$\\
$[ [ 4, 1 ] ] ]$\\
\end{tabular}\\[2mm]
\end{center}

 As you can see, this looks fairly complicated. However, the same information
can be stored in this form, which would become the final data structure for \textsf{Gauss} sparse matrices: \begin{center}
\begin{tabular}{clcl}indices :=&
[ [ 3, 4 ],&
entries:=&
[ [ 2, 9 ],\\
&
 [ 2 ],&
&
 [ 5 ],\\
&
 [ 4 ] ]&
&
 [ 1 ] ]\\
\end{tabular}\\[2mm]
\end{center}

 Although now the number of rows is equal to the Length of both `indices' and
`entries', it is still stored in the sparse matrix. Here is the full data
structure ($\to$ \texttt{SparseMatrix} (\ref{SparseMatrix:constructor using gap matrices})): 
\begin{Verbatim}[fontsize=\small,frame=single,label=from SparseMatrix.gi]
      DeclareRepresentation( "IsSparseMatrixRep",
           IsSparseMatrix, [ "nrows", "ncols", "indices", "entries", "ring" ] );
      
\end{Verbatim}
 As you can see, the matrix stores its ring to be on the safe side. This is
especially important for zero matrices, as there is no way to determine the
base ring from the sparse matrix structure. For further information on sparse
matrix construction and converting, refer to \texttt{SparseMatrix} (\ref{SparseMatrix:constructor using gap matrices}). 
\subsection{\textcolor{Chapter }{A special case: GF(2)}}\label{sub:gf2}
\logpage{[ 3, 1, 1 ]}
\hyperdef{L}{X812222AB7F56717A}{}
{
 
\begin{Verbatim}[fontsize=\small,frame=single,label=from SparseMatrix.gi]
      DeclareRepresentation( "IsSparseMatrixGF2Rep",
           IsSparseMatrix, [ "nrows", "ncols", "indices", "ring" ] );
      
\end{Verbatim}
 Because the nonzero entries of a matrix over GF(2) are all "1", the entries of
M are not stored at all. It is of course crucial that all operations and
algorithms make 100\% sure that all appearing zero entries are deleted from
the `indices' as well as the `entries' list as they arise. }

 }

 
\section{\textcolor{Chapter }{Methods and functions for sparse matrices}}\label{sec:mfSM}
\logpage{[ 3, 2, 0 ]}
\hyperdef{L}{X78FB3DC27FF8769E}{}
{
 

\subsection{\textcolor{Chapter }{SparseMatrix (constructor using gap matrices)}}
\logpage{[ 3, 2, 1 ]}\nobreak
\hyperdef{L}{X829481DA85587996}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{SparseMatrix({\slshape mat[, R]})\index{SparseMatrix@\texttt{SparseMatrix}!constructor using gap matrices}
\label{SparseMatrix:constructor using gap matrices}
}\hfill{\scriptsize (function)}}\\
\textbf{\indent Returns:\ }
a sparse matrix over the ring \mbox{\texttt{\slshape R}}

\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{SparseMatrix({\slshape nrows, ncols, indices})\index{SparseMatrix@\texttt{SparseMatrix}!constructor using indices}
\label{SparseMatrix:constructor using indices}
}\hfill{\scriptsize (function)}}\\
\textbf{\indent Returns:\ }
a sparse matrix over GF(2)

\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{SparseMatrix({\slshape nrows, ncols, indices, entries[, R]})\index{SparseMatrix@\texttt{SparseMatrix}!constructor using indices and entries}
\label{SparseMatrix:constructor using indices and entries}
}\hfill{\scriptsize (function)}}\\
\textbf{\indent Returns:\ }
a sparse matrix over the ring \mbox{\texttt{\slshape R}}



 The sparse matrix constructor. In the one-argument form the SparseMatrix
constructor converts a \textsf{GAP} matrix to a sparse matrix. If not provided the base ring \mbox{\texttt{\slshape R}} is found automatically. For the multi-argument form \mbox{\texttt{\slshape nrows}} and \mbox{\texttt{\slshape ncols}} are the dimensions of the matrix. \mbox{\texttt{\slshape indices}} must be a list of length \mbox{\texttt{\slshape nrows}} containing lists of the column indices of the matrix in ascending order. 
\begin{Verbatim}[fontsize=\small,frame=single,label=Example]
  gap> M := [ [ 0 , 1 ], [ 3, 0 ] ] * One( GF(2) );
  [ [ 0*Z(2), Z(2)^0 ], [ Z(2)^0, 0*Z(2) ] ]
  gap> SM := SparseMatrix( M );
  <a 2 x 2 sparse matrix over GF(2)>
  gap> IsSparseMatrix( SM );
  true
  gap> Display( SM );
   . 1
   1 .
  gap> SN := SparseMatrix( 2, 2, [ [ 2 ], [ 1 ] ] );
  <a 2 x 2 sparse matrix over GF(2)>
  gap> SN = SM;
  true
  gap> SN := SparseMatrix( 2, 3,
  >                   [ [ 2 ], [ 1, 3 ] ],
  >                   [ [ 1 ], [ 3, 2 ] ] * One( GF(5) ) );
  <a 2 x 3 sparse matrix over GF(5)>
  gap> Display( SN );
   . 1 .
   3 . 2
\end{Verbatim}
 }

 

\subsection{\textcolor{Chapter }{ConvertSparseMatrixToMatrix}}
\logpage{[ 3, 2, 2 ]}\nobreak
\hyperdef{L}{X801B77A67B8A16DA}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{ConvertSparseMatrixToMatrix({\slshape sm})\index{ConvertSparseMatrixToMatrix@\texttt{ConvertSparseMatrixToMatrix}}
\label{ConvertSparseMatrixToMatrix}
}\hfill{\scriptsize (method)}}\\
\textbf{\indent Returns:\ }
a \textsf{GAP} matrix, [], or a list of empty lists



 This function converts the sparse matrix \mbox{\texttt{\slshape sm}} into a \textsf{GAP} matrix. In case of \texttt{nrows(sm)=0} or \texttt{ncols(sm)=0} the return value is the empty list or a list of empty lists, respectively. 
\begin{Verbatim}[fontsize=\small,frame=single,label=Example]
  gap> M := [ [ 0 , 1 ], [ 3, 0 ] ] * One( GF(3) );
  [ [ 0*Z(3), Z(3)^0 ], [ 0*Z(3), 0*Z(3) ] ]
  gap> SM := SparseMatrix( M );
  <a 2 x 2 sparse matrix over GF(3)>
  gap> N := ConvertSparseMatrixToMatrix( SM );
  [ [ 0*Z(3), Z(3)^0 ], [ 0*Z(3), 0*Z(3) ] ]
  gap> M = N;
  true
\end{Verbatim}
 }

 

\subsection{\textcolor{Chapter }{CopyMat}}
\logpage{[ 3, 2, 3 ]}\nobreak
\hyperdef{L}{X86C79A76865D4AF0}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{CopyMat({\slshape sm})\index{CopyMat@\texttt{CopyMat}}
\label{CopyMat}
}\hfill{\scriptsize (method)}}\\
\textbf{\indent Returns:\ }
a shallow copy of the sparse matrix \mbox{\texttt{\slshape sm}}

}

 

\subsection{\textcolor{Chapter }{GetEntry}}
\logpage{[ 3, 2, 4 ]}\nobreak
\hyperdef{L}{X7C46B38A8507EB61}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{GetEntry({\slshape sm, i, j})\index{GetEntry@\texttt{GetEntry}}
\label{GetEntry}
}\hfill{\scriptsize (method)}}\\
\textbf{\indent Returns:\ }
a ring element.



 This returns the entry \texttt{sm[i,j]} of the sparse matrix \mbox{\texttt{\slshape sm}} }

 

\subsection{\textcolor{Chapter }{SetEntry}}
\logpage{[ 3, 2, 5 ]}\nobreak
\hyperdef{L}{X83C9A07784AA4626}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{SetEntry({\slshape sm, i, j, elm})\index{SetEntry@\texttt{SetEntry}}
\label{SetEntry}
}\hfill{\scriptsize (method)}}\\
\textbf{\indent Returns:\ }
nothing.



 This sets the entry \texttt{sm[i,j]} of the sparse matrix \mbox{\texttt{\slshape sm}} to \mbox{\texttt{\slshape elm}}. }

 

\subsection{\textcolor{Chapter }{AddToEntry}}
\logpage{[ 3, 2, 6 ]}\nobreak
\hyperdef{L}{X8729D1F87E176150}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{AddToEntry({\slshape sm, i, j, elm})\index{AddToEntry@\texttt{AddToEntry}}
\label{AddToEntry}
}\hfill{\scriptsize (method)}}\\
\textbf{\indent Returns:\ }
\texttt{true} or a ring element



 AddToEntry adds the element \mbox{\texttt{\slshape elm}} to the sparse matrix \mbox{\texttt{\slshape sm}} at the \mbox{\texttt{\slshape (i,j)}}-th position. This is a Method with a side effect which returns true if you
tried to add zero or the sum of \texttt{sm[i,j]} and \mbox{\texttt{\slshape elm}} otherwise. Please use this method whenever possible. }

 

\subsection{\textcolor{Chapter }{SparseZeroMatrix (constructor using number of rows)}}
\logpage{[ 3, 2, 7 ]}\nobreak
\hyperdef{L}{X7D59FA867A432607}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{SparseZeroMatrix({\slshape nrows[, ring]})\index{SparseZeroMatrix@\texttt{SparseZeroMatrix}!constructor using number of rows}
\label{SparseZeroMatrix:constructor using number of rows}
}\hfill{\scriptsize (function)}}\\
\textbf{\indent Returns:\ }
a sparse {\textless}\mbox{\texttt{\slshape nrows}} x \mbox{\texttt{\slshape nrows}}{\textgreater} zero matrix over the ring \mbox{\texttt{\slshape ring}}

\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{SparseZeroMatrix({\slshape nrows, ncols[, ring]})\index{SparseZeroMatrix@\texttt{SparseZeroMatrix}!constructor using number of rows and columns}
\label{SparseZeroMatrix:constructor using number of rows and columns}
}\hfill{\scriptsize (function)}}\\
\textbf{\indent Returns:\ }
a sparse {\textless}\mbox{\texttt{\slshape nrows}} x \mbox{\texttt{\slshape ncols}}{\textgreater} zero matrix over the ring \mbox{\texttt{\slshape ring}}

}

 

\subsection{\textcolor{Chapter }{SparseIdentityMatrix}}
\logpage{[ 3, 2, 8 ]}\nobreak
\hyperdef{L}{X844E79E07E11A32E}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{SparseIdentityMatrix({\slshape dim[, ring]})\index{SparseIdentityMatrix@\texttt{SparseIdentityMatrix}}
\label{SparseIdentityMatrix}
}\hfill{\scriptsize (function)}}\\
\textbf{\indent Returns:\ }
a sparse {\textless}\mbox{\texttt{\slshape dim}} x \mbox{\texttt{\slshape dim}}{\textgreater} identity matrix over the ring \mbox{\texttt{\slshape ring}}. If no ring is specified (one should try to avoid this if possible) the
Rationals are the default ring.

}

 

\subsection{\textcolor{Chapter }{TransposedSparseMat}}
\logpage{[ 3, 2, 9 ]}\nobreak
\hyperdef{L}{X7D91261880BF76EC}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{TransposedSparseMat({\slshape sm})\index{TransposedSparseMat@\texttt{TransposedSparseMat}}
\label{TransposedSparseMat}
}\hfill{\scriptsize (method)}}\\
\textbf{\indent Returns:\ }
the transposed matrix of the sparse matrix \mbox{\texttt{\slshape sm}}

}

 

\subsection{\textcolor{Chapter }{CertainRows}}
\logpage{[ 3, 2, 10 ]}\nobreak
\hyperdef{L}{X7BAE852578C6B839}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{CertainRows({\slshape sm, list})\index{CertainRows@\texttt{CertainRows}}
\label{CertainRows}
}\hfill{\scriptsize (method)}}\\
\textbf{\indent Returns:\ }
the submatrix \texttt{sm\texttt{\symbol{123}}[list]\texttt{\symbol{125}}} as a sparse matrix

}

 

\subsection{\textcolor{Chapter }{CertainColumns}}
\logpage{[ 3, 2, 11 ]}\nobreak
\hyperdef{L}{X7CE203DF7F323F87}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{CertainColumns({\slshape sm, list})\index{CertainColumns@\texttt{CertainColumns}}
\label{CertainColumns}
}\hfill{\scriptsize (method)}}\\
\textbf{\indent Returns:\ }
the submatrix \texttt{sm\texttt{\symbol{123}}[1..nrows(sm)]\texttt{\symbol{125}}\texttt{\symbol{123}}[list]\texttt{\symbol{125}}} as a sparse matrix

}

 

\subsection{\textcolor{Chapter }{UnionOfRows}}
\logpage{[ 3, 2, 12 ]}\nobreak
\hyperdef{L}{X81B6E8EC86BC649A}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{UnionOfRows({\slshape A, B})\index{UnionOfRows@\texttt{UnionOfRows}}
\label{UnionOfRows}
}\hfill{\scriptsize (method)}}\\
\textbf{\indent Returns:\ }
the row union of the sparse matrices \mbox{\texttt{\slshape A}} and \mbox{\texttt{\slshape B}}

}

 

\subsection{\textcolor{Chapter }{UnionOfColumns}}
\logpage{[ 3, 2, 13 ]}\nobreak
\hyperdef{L}{X81630C648148E324}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{UnionOfColumns({\slshape A, B})\index{UnionOfColumns@\texttt{UnionOfColumns}}
\label{UnionOfColumns}
}\hfill{\scriptsize (method)}}\\
\textbf{\indent Returns:\ }
the column union of the sparse matrices \mbox{\texttt{\slshape A}} and \mbox{\texttt{\slshape B}}

}

 

\subsection{\textcolor{Chapter }{SparseDiagMat}}
\logpage{[ 3, 2, 14 ]}\nobreak
\hyperdef{L}{X7A0CEF5F79A86190}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{SparseDiagMat({\slshape list})\index{SparseDiagMat@\texttt{SparseDiagMat}}
\label{SparseDiagMat}
}\hfill{\scriptsize (function)}}\\
\textbf{\indent Returns:\ }
the block diagonal matrix composed of the sparse matrices in \mbox{\texttt{\slshape list}}

}

 

\subsection{\textcolor{Chapter }{Nrows}}
\logpage{[ 3, 2, 15 ]}\nobreak
\hyperdef{L}{X8719F2477C0401FE}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{Nrows({\slshape sm})\index{Nrows@\texttt{Nrows}}
\label{Nrows}
}\hfill{\scriptsize (method)}}\\
\textbf{\indent Returns:\ }
the number of rows of the sparse matrix \mbox{\texttt{\slshape sm}}. This should be preferred to the equivalent \texttt{sm!.nrows}.

}

 

\subsection{\textcolor{Chapter }{Ncols}}
\logpage{[ 3, 2, 16 ]}\nobreak
\hyperdef{L}{X8300CDF181481EC6}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{Ncols({\slshape sm})\index{Ncols@\texttt{Ncols}}
\label{Ncols}
}\hfill{\scriptsize (method)}}\\
\textbf{\indent Returns:\ }
the number of columns of the sparse matrix \mbox{\texttt{\slshape sm}}. This should be preferred to the equivalent \texttt{sm!.ncols}.

}

 

\subsection{\textcolor{Chapter }{IndicesOfSparseMatrix}}
\logpage{[ 3, 2, 17 ]}\nobreak
\hyperdef{L}{X82615CEC7AD43F41}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{IndicesOfSparseMatrix({\slshape sm})\index{IndicesOfSparseMatrix@\texttt{IndicesOfSparseMatrix}}
\label{IndicesOfSparseMatrix}
}\hfill{\scriptsize (method)}}\\
\textbf{\indent Returns:\ }
the indices of the sparse matrix \mbox{\texttt{\slshape sm}} as a ListList. This should be preferred to the equivalent \texttt{sm!.indices}.

}

 

\subsection{\textcolor{Chapter }{EntriesOfSparseMatrix}}
\logpage{[ 3, 2, 18 ]}\nobreak
\hyperdef{L}{X7E3040828757BD37}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{EntriesOfSparseMatrix({\slshape sm})\index{EntriesOfSparseMatrix@\texttt{EntriesOfSparseMatrix}}
\label{EntriesOfSparseMatrix}
}\hfill{\scriptsize (method)}}\\
\textbf{\indent Returns:\ }
the entries of the sparse matrix \mbox{\texttt{\slshape sm}} as a ListList of ring elements. This should be preferred to the equivalent \texttt{sm!.entries} and has the additional advantage of working for sparse matrices over GF(2)
which do not have any entries.

}

 

\subsection{\textcolor{Chapter }{RingOfDefinition}}
\logpage{[ 3, 2, 19 ]}\nobreak
\hyperdef{L}{X85766EE5848E7402}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{RingOfDefinition({\slshape sm})\index{RingOfDefinition@\texttt{RingOfDefinition}}
\label{RingOfDefinition}
}\hfill{\scriptsize (method)}}\\
\textbf{\indent Returns:\ }
the base ring of the sparse matrix \mbox{\texttt{\slshape sm}}. This should be preferred to the equivalent \texttt{sm!.ring}.

}

 }

 }

 
\chapter{\textcolor{Chapter }{Gaussian Algorithms}}\label{chap:Gauss}
\logpage{[ 4, 0, 0 ]}
\hyperdef{L}{X86443AB17C0AD00C}{}
{
 
\section{\textcolor{Chapter }{A list of the available algorithms}}\label{sec:list}
\logpage{[ 4, 1, 0 ]}
\hyperdef{L}{X863F68B2858CC146}{}
{
 As decribed earlier, the main functions of \textsf{Gauss} are \texttt{EchelonMat} (\ref{EchelonMat}) and \texttt{EchelonMatTransformation} (\ref{EchelonMatTransformation}), \texttt{ReduceMat} (\ref{ReduceMat}) and \texttt{ReduceMatTransformation} (\ref{ReduceMatTransformation}), \texttt{KernelMat} (\ref{KernelMat}) and, additionally \texttt{Rank} (\ref{Rank}). These are all documented in the next section, but of course rely on specific
algorithms depending on the base ring of the matrix. These are not fully
documented but it should be very easy to find out how they work based on the
documentation of the main functions. \begin{center}
\begin{tabular}{lll}EchelonMat\\
&
Field:&
\texttt{EchelonMatDestructive}\\
&
Ring:&
\texttt{HermiteMatDestructive}\\
EchelonMatTransformation\\
&
Field:&
\texttt{EchelonMatTransformationDestructive}\\
&
Ring:&
\texttt{HermiteMatTransformationDestructive}\\
ReduceMat\\
&
Field:&
\texttt{ReduceMatWithEchelonMat}\\
&
Ring:&
\texttt{ReduceMatWithHermiteMat}\\
ReduceMatTransformation\\
&
Field:&
\texttt{ReduceMatWithEchelonMatTransformation}\\
&
Ring:&
\texttt{ReduceMatWithHermiteMatTransformation}\\
KernelMat\\
&
Field:&
\texttt{KernelEchelonMatDestructive}\\
&
Ring:&
\texttt{KernelHermiteMatDestructive}\\
Rank\\
&
Field (dense):&
\texttt{Rank} (\textsf{GAP} method)\\
&
Field (sparse):&
\texttt{RankDestructive}\\
&
GF(2) (sparse):&
\texttt{RankOfIndicesListList}\\
&
Ring:&
n.a.\\
\end{tabular}\\[2mm]
\end{center}

 }

 
\section{\textcolor{Chapter }{Methods and Functions for \textsf{Gauss}ian algorithms}}\label{sec:mfGauss}
\logpage{[ 4, 2, 0 ]}
\hyperdef{L}{X79093EFA828EF7D1}{}
{
 

\subsection{\textcolor{Chapter }{EchelonMat}}
\logpage{[ 4, 2, 1 ]}\nobreak
\hyperdef{L}{X8499C9FD7AD9908F}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{EchelonMat({\slshape mat})\index{EchelonMat@\texttt{EchelonMat}}
\label{EchelonMat}
}\hfill{\scriptsize (method)}}\\
\textbf{\indent Returns:\ }
a record that contains information about an echelonized form of the matrix \mbox{\texttt{\slshape mat}}.

 The components of this record are

 `vectors'

 the reduced row echelon / hermite form of the matrix \mbox{\texttt{\slshape mat}} without zero rows.

 `heads'

 list that contains at position {\textless}i{\textgreater}, if nonzero, the
number of the row for that the pivot element is in column
{\textless}i{\textgreater}. 



 computes the reduced row echelon form RREF of a dense or sparse matrix \mbox{\texttt{\slshape mat}} over a field, or the hermite form of a sparse matrix \mbox{\texttt{\slshape mat}} over ${\ensuremath{\mathbb Z}} / < p^n >$. 
\begin{Verbatim}[fontsize=\small,frame=single,label=Example]
  gap> M := [[0,0,0,1,0],[0,1,1,1,1],[1,1,1,1,0]] * One( GF(2) );;
  gap> Display(M);
   . . . 1 .
   . 1 1 1 1
   1 1 1 1 .
  gap> EchelonMat(M);
  rec( heads := [ 1, 2, 0, 3, 0 ],
    vectors := [ <a GF2 vector of length 5>, <a GF2 vector of length 5>,
        <a GF2 vector of length 5> ] )
  gap> Display( last.vectors );
   1 . . . 1
   . 1 1 . 1
   . . . 1 .
  gap> SM := SparseMatrix( M );
  <a 3 x 5 sparse matrix over GF(2)>
  gap> EchelonMat( SM );
  rec( heads := [ 1, 2, 0, 3, 0 ], vectors := <a 3 x 5 sparse matrix over GF(
      2)> )
  gap> Display(last.vectors);
   1 . . . 1
   . 1 1 . 1
   . . . 1 .
  gap> SM := SparseMatrix( [[7,4,5],[0,0,6],[0,4,4]] * One( Integers mod 8 ) );
  <a 3 x 3 sparse matrix over (Integers mod 8)>
  gap> Display( SM );
   7 4 5
   . . 6
   . 4 4
  gap> EchelonMat( SM );
  rec( heads := [ 1, 2, 3 ],
    vectors := <a 3 x 3 sparse matrix over (Integers mod 8)> )
  gap> Display( last.vectors );
   1 . 1
   . 4 .
   . . 2      
\end{Verbatim}
 }

 

\subsection{\textcolor{Chapter }{EchelonMatTransformation}}
\logpage{[ 4, 2, 2 ]}\nobreak
\hyperdef{L}{X869107627EBA2177}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{EchelonMatTransformation({\slshape mat})\index{EchelonMatTransformation@\texttt{EchelonMatTransformation}}
\label{EchelonMatTransformation}
}\hfill{\scriptsize (method)}}\\
\textbf{\indent Returns:\ }
a record that contains information about an echelonized form of the matrix \mbox{\texttt{\slshape mat}}.

 The components of this record are

 `vectors'

 the reduced row echelon / hermite form of the matrix \mbox{\texttt{\slshape mat}} without zero rows.

 `heads'

 list that contains at position {\textless}i{\textgreater}, if nonzero, the
number of the row for that the pivot element is in column
{\textless}i{\textgreater}.

 `coeffs'

 the transformation matrix needed to obtain the RREF from \mbox{\texttt{\slshape mat}}.

 `relations'

 the kernel of the matrix \mbox{\texttt{\slshape mat}} if RingOfDefinition(\mbox{\texttt{\slshape mat}}) is a field. Otherwise these are only the obvious row relations of \mbox{\texttt{\slshape mat}}, there might be more kernel vectors - $\to$ \texttt{KernelMat} (\ref{KernelMat}). 



 computes the reduced row echelon form RREF of a dense or sparse matrix \mbox{\texttt{\slshape mat}} over a field, or the hermite form of a sparse matrix \mbox{\texttt{\slshape mat}} over ${\ensuremath{\mathbb Z}} / < p^n >$. In either case, the transformation matrix $T$ is calculated as the row union of `coeffs' and `relations'. 
\begin{Verbatim}[fontsize=\small,frame=single,label=Example]
  gap> M := [[1,0,1],[1,1,0],[1,0,1],[1,1,0],[1,1,1]] * One( GF(2) );;
  gap> EchelonMatTransformation( M );
  rec( heads := [ 1, 2, 3 ],
    vectors := [ <a GF2 vector of length 3>, <a GF2 vector of length 3>,
        <a GF2 vector of length 3> ],
    coeffs := [ <a GF2 vector of length 5>, <a GF2 vector of length 5>,
        <a GF2 vector of length 5> ],
    relations := [ <a GF2 vector of length 5>, <a GF2 vector of length 5> ] )
  gap> Display(last.vectors);
   1 . .
   . 1 .
   . . 1
  gap> Display(last.coeffs);
   1 1 . . 1
   1 . . . 1
   . 1 . . 1
  gap> Display(last.relations);
   1 . 1 . .
   . 1 . 1 .
  gap> Display( Concatenation( last.coeffs, last.relations ) * M );
   1 . .
   . 1 .
   . . 1
   . . .
   . . .
  gap> SM := SparseMatrix( M );
  <a 5 x 3 sparse matrix over GF(2)>
  gap> EchelonMatTransformation( SM );
  rec( heads := [ 1, 2, 3 ], vectors := <a 3 x 3 sparse matrix over GF(2)>,
    coeffs := <a 3 x 5 sparse matrix over GF(2)>,
    relations := <a 2 x 5 sparse matrix over GF(2)> )
  gap> Display(last.vectors);
   1 . .
   . 1 .
   . . 1
  gap> Display(last.coeffs);
   1 1 . . 1
   1 . . . 1
   . 1 . . 1
  gap> Display(last.relations);
   1 . 1 . .
   . 1 . 1 .
  gap> Display( UnionOfRows( last.coeffs, last.relations ) * SM );
   1 . .
   . 1 .
   . . 1
   . . .
   . . .
\end{Verbatim}
 }

 

\subsection{\textcolor{Chapter }{ReduceMat}}
\logpage{[ 4, 2, 3 ]}\nobreak
\hyperdef{L}{X811A3B547A27A895}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{ReduceMat({\slshape A, B})\index{ReduceMat@\texttt{ReduceMat}}
\label{ReduceMat}
}\hfill{\scriptsize (method)}}\\
\textbf{\indent Returns:\ }
a record with a single component `reduced{\textunderscore}matrix' := M. M is
created by reducing \mbox{\texttt{\slshape A}} with \mbox{\texttt{\slshape B}}, where \mbox{\texttt{\slshape B}} must be in Echelon/Hermite form. M will have the same dimensions as \mbox{\texttt{\slshape A}}.



 
\begin{Verbatim}[fontsize=\small,frame=single,label=Example]
  gap> M := [[0,0,0,1,0],[0,1,1,1,1],[1,1,1,1,0]] * One( GF(2) );;
  gap> Display(M);
   . . . 1 .
   . 1 1 1 1
   1 1 1 1 .
  gap> N := [[1,1,0,0,0],[0,0,1,0,1]] * One( GF(2) );;
  gap> Display(N);
   1 1 . . .
   . . 1 . 1
  gap> ReduceMat(M,N);
  rec(
    reduced_matrix := [ <a GF2 vector of length 5>, <a GF2 vector of length 5>,
        <a GF2 vector of length 5> ] )
  gap> Display(last.reduced_matrix);
   . . . 1 .
   . 1 . 1 .
   . . . 1 1
  gap> SM := SparseMatrix(M); SN := SparseMatrix(N);
  <a 3 x 5 sparse matrix over GF(2)>
  <a 2 x 5 sparse matrix over GF(2)>
  gap> ReduceMat(SM,SN);
  rec( reduced_matrix := <a 3 x 5 sparse matrix over GF(2)> )
  gap> Display(last.reduced_matrix);
   . . . 1 .
   . 1 . 1 .
   . . . 1 1
\end{Verbatim}
 }

 

\subsection{\textcolor{Chapter }{ReduceMatTransformation}}
\logpage{[ 4, 2, 4 ]}\nobreak
\hyperdef{L}{X816CA6D37F0DB74F}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{ReduceMatTransformation({\slshape A, B})\index{ReduceMatTransformation@\texttt{ReduceMatTransformation}}
\label{ReduceMatTransformation}
}\hfill{\scriptsize (method)}}\\
\textbf{\indent Returns:\ }
a record with a component `reduced{\textunderscore}matrix' := M. M is created
by reducing \mbox{\texttt{\slshape A}} with \mbox{\texttt{\slshape B}}, where \mbox{\texttt{\slshape B}} must be in Echelon/Hermite form. M will have the same dimensions as \mbox{\texttt{\slshape A}}. In addition to the (identical) output as ReduceMat this record also includes
the component `transformation', which stores the row operations that were
needed to reduce \mbox{\texttt{\slshape A}} with \mbox{\texttt{\slshape B}}. This differs from "normal" transformation matrices because only rows of \mbox{\texttt{\slshape B}} had to be moved. Therefore, the transformation matrix solves M = A + T * B.



 
\begin{Verbatim}[fontsize=\small,frame=single,label=Example]
  gap> M := [[0,0,0,1,0],[0,1,1,1,1],[1,1,1,1,0]] * One( GF(2) );;
  gap> Display(M);
   . . . 1 .
   . 1 1 1 1
   1 1 1 1 .
  gap> N := [[1,1,0,0,0],[0,0,1,0,1]] * One( GF(2) );;
  gap> Display(N);
   1 1 . . .
   . . 1 . 1
  gap> ReduceMatTransformation(M,N);
  rec(
    reduced_matrix := [ <a GF2 vector of length 5>, <a GF2 vector of length 5>,
        <a GF2 vector of length 5> ],
    transformation := [ <a GF2 vector of length 2>, <a GF2 vector of length 2>,
        <a GF2 vector of length 2> ] )
  gap> Display(last.reduced_matrix);
   . . . 1 .
   . 1 . 1 .
   . . . 1 1
  gap> Display(last.transformation);
   . .
   . 1
   1 1
  gap> Display( M + last.transformation * N );
   . . . 1 .
   . 1 . 1 .
   . . . 1 1 
  gap> SM := SparseMatrix(M); SN := SparseMatrix(N);
  <a 3 x 5 sparse matrix over GF(2)>
  <a 2 x 5 sparse matrix over GF(2)>
  gap> ReduceMatTransformation(SM,SN);
  rec( reduced_matrix := <a 3 x 5 sparse matrix over GF(2)>,
    transformation := <a 3 x 2 sparse matrix over GF(2)> )
  gap> Display(last.reduced_matrix);
   . . . 1 .
   . 1 . 1 .
   . . . 1 1
  gap> Display(last.transformation);
   . .
   . 1
   1 1
  gap> Display( SM + last.transformation * SN );
   . . . 1 .
   . 1 . 1 .
   . . . 1 1
\end{Verbatim}
 }

 

\subsection{\textcolor{Chapter }{KernelMat}}
\logpage{[ 4, 2, 5 ]}\nobreak
\hyperdef{L}{X78E97A0E7F1ED8AA}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{KernelMat({\slshape M})\index{KernelMat@\texttt{KernelMat}}
\label{KernelMat}
}\hfill{\scriptsize (function)}}\\
\textbf{\indent Returns:\ }
a record with a single component `relations'.



 If \mbox{\texttt{\slshape M}} is a matrix over a field this is the same output as \texttt{EchelonMatTransformation} (\ref{EchelonMatTransformation}) provides in the `relations' component, but with less memory and CPU usage. If
the base ring of \mbox{\texttt{\slshape M}} is a non-field, the Kernel might have additional generators, which are added
to the output. 
\begin{Verbatim}[fontsize=\small,frame=single,label=Example]
  gap> M := [[2,1],[0,2]];
  [ [ 2, 1 ], [ 0, 2 ] ]
  gap> SM := SparseMatrix( M * One( GF(3) ) );
  <a 2 x 2 sparse matrix over GF(3)>
  gap> KernelMat(SM);
  rec( relations := <a 0 x 2 sparse matrix over GF(3)> )
  gap> SN := SparseMatrix( M * One( Integers mod 4 ) );
  <a 2 x 2 sparse matrix over (Integers mod 4)>
  gap> KernelMat(SN);
  rec( relations := <a 1 x 2 sparse matrix over (Integers mod 4)> )
  gap> Display(last.relations);
   2 1
\end{Verbatim}
 }

 

\subsection{\textcolor{Chapter }{Rank}}
\logpage{[ 4, 2, 6 ]}\nobreak
\hyperdef{L}{X827146F37E2AA841}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{Rank({\slshape sm[, boundary]})\index{Rank@\texttt{Rank}}
\label{Rank}
}\hfill{\scriptsize (method)}}\\
\textbf{\indent Returns:\ }
the rank of the sparse matrix \mbox{\texttt{\slshape sm}}. Only works for fields.



 Computes the rank of a sparse matrix. If the optional argument \mbox{\texttt{\slshape boundary}} is provided, some algorithms take into account the fact that Rank(\mbox{\texttt{\slshape sm}}) {\textless}= \mbox{\texttt{\slshape boundary}}, thus possibly terminating earlier. 
\begin{Verbatim}[fontsize=\small,frame=single,label=Example]
  gap> M := SparseDiagMat( ListWithIdenticalEntries( 10,
  >         SparseMatrix( [[1,1],[1,1]] * One( GF(5) ) ) ) );
  <a 20 x 20 sparse matrix over GF(5)>
  gap> Display(M);
   1 1 . . . . . . . . . . . . . . . . . .
   1 1 . . . . . . . . . . . . . . . . . .
   . . 1 1 . . . . . . . . . . . . . . . .
   . . 1 1 . . . . . . . . . . . . . . . .
   . . . . 1 1 . . . . . . . . . . . . . .
   . . . . 1 1 . . . . . . . . . . . . . .
   . . . . . . 1 1 . . . . . . . . . . . .
   . . . . . . 1 1 . . . . . . . . . . . .
   . . . . . . . . 1 1 . . . . . . . . . .
   . . . . . . . . 1 1 . . . . . . . . . .
   . . . . . . . . . . 1 1 . . . . . . . .
   . . . . . . . . . . 1 1 . . . . . . . .
   . . . . . . . . . . . . 1 1 . . . . . .
   . . . . . . . . . . . . 1 1 . . . . . .
   . . . . . . . . . . . . . . 1 1 . . . .
   . . . . . . . . . . . . . . 1 1 . . . .
   . . . . . . . . . . . . . . . . 1 1 . .
   . . . . . . . . . . . . . . . . 1 1 . .
   . . . . . . . . . . . . . . . . . . 1 1
   . . . . . . . . . . . . . . . . . . 1 1
  gap> Rank(M);
  10
\end{Verbatim}
 }

 }

 }

 

\appendix


\chapter{\textcolor{Chapter }{An Overview of the \textsf{Gauss} package source code}}\label{FileOverview}
\logpage{[ "A", 0, 0 ]}
\hyperdef{L}{X78EED4F77E698478}{}
{
  \begin{center}
\begin{tabular}{l|l}Filename&
Content\\
\hline
SparseMatrix.gi&
Definitions and methods for the sparse matrix type\\
SparseMatrixGF2.gi&
Special case GF(2): no matrix entries needed\\
GaussDense.gi&
Gaussian elmination for \textsf{GAP} matrices over fields\\
Sparse.gi&
Documentation and forking depending on the base ring\\
GaussSparse.gi&
Gaussian elimination for sparse matrices over fields\\
HermiteSparse.gi&
Hermite elimination for sparse matrices over ${\ensuremath{\mathbb Z}} / \langle p^n \rangle$\\
\end{tabular}\\[2mm]
\textbf{Table: }\emph{The \textsf{Gauss} package files.}\end{center}

 }

\def\bibname{References\logpage{[ "Bib", 0, 0 ]}
\hyperdef{L}{X7A6F98FD85F02BFE}{}
}

\bibliographystyle{alpha}
\bibliography{GaussBib.xml}

\def\indexname{Index\logpage{[ "Ind", 0, 0 ]}
\hyperdef{L}{X83A0356F839C696F}{}
}


\printindex

\newpage
\immediate\write\pagenrlog{["End"], \arabic{page}];}
\immediate\closeout\pagenrlog
\end{document}
