%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
%%  bigint_matrix.tex       LiDIA documentation
%%
%%  This file contains the documentation of the class bigint_matrix
%%  
%%  Copyright   (c)   1995   by  LiDIA-Group
%%
%%  Authors: Patrick Theobald
%%  

\markright{\BF{bigint\_matrix}}
\begin{lidia_man}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\NAME
\BF{bigint\_matrix} \DOTFILL Linear algebra over \MATH{\Z}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\ABSTRACT
\BF{bigint\_matrix} is a class for doing linear algebra over the ring of rational integers. This class may 
either be used for representing a modul, which is generated by the columns of the matrix 
\[A=(a_{i,j})_{0\LE i<m, 0\LE j<n}\IN \Z^{m\TIMES n},\]
or for representing a homomorphism by its matrix. In the first case, the class supports for example 
computing bases, hermite normal form, smith normal form etc., in the second case it may be used for 
computing the determinant, the characteristic polynomial, the image, the  kernel etc.~of the homomorphism.

According to the template introduction (see page \pageref{template_introduction2}) the class 
\BF{bigint\_matrix} is derived from 
\BF{math\_matrix\LT bigint\GT}. So you can apply all the functions and operators of class 
\BF{base\_matrix\LT bigint\GT}\ and \BF{math\_matrix\LT bigint\GT}\ to instances of 
type \BF{bigint\_matrix}.\hfill\\

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\DESCRIPTION
A variable of type \BF{bigint\_matrix} contains the same components as
a \BF{math\_matrix\LT bigint\GT}. 

As usually in the following descriptions we use \MATH{A.rows} to label the number of rows and 
\MATH{A.columns} to label the number of columns of matrix \MATH{A}.

For some computations modular arithmetic is used, for which we use an external table of prime numbers. By 
default, this table is taken out of the file \TT{LIDIA\_INSTALL\_DIR/lib/LiDIA/LIDIA\_PRIMES}, where 
\TT{LIDIA\_INSTALL\_DIR} denotes the directory, where \LiDIA\ was installed by the installation procedure
(see page \pageref{Install}).
For efficiency reasons, we assume at first, that 300 prime numbers are sufficient. If this is not the case, the 
number of used prime numbers is successively doubled.

If you want to use some other file location for the file containing the prime numbers, you have to set the 
environment variable \TT{LIDIA\_PRIMES\_NAME} to point to this location. Depending on your architecture 
quite some gain in running time may be achieved by using lists of larger prime numbers, e.~g.~if you 
have a 64 bit CPU using our list of 26 bit primes (optimized for SPARC V7/V8 architectures) is just a 
convenient though slow 
way to get our library to work. If you do computations with very large numbers, you might consider to start 
with a larger buffer for the prime numbers by setting the environment variable \TT{LIDIA\_PRIMES\_SIZE} to 
some larger number, e.~g.~to 6000.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\CONS
If \MATH{a\LE 0} or \MATH{b\LE 0} or \MATH{v=NULL} in one of the following constructors the 
\TT{lidia\_error\_handler} will be invoked. 


\fcode{ct}{bigint\_matrix}{}
{
constructs a \MATH{1 \TIMES 1} matrix initialized with zero.}

\fcode{ct}{bigint\_matrix}{lidia\_size\_t a\k lidia\_size\_t b}
{
constructs an \MATH{a \TIMES b} matrix initialized with zero.}

\fcode{ct}{bigint\_matrix}{lidia\_size\_t a\k lidia\_size\_t b\k const bigint **v}
{
constructs an \MATH{a \TIMES b} matrix initialized with the values of the 2-dimensional array 
\MATH{v}. The behaviour of this constructor is undefined if the array \MATH{v} has less 
than \MATH{a} rows or less than \MATH{b} columns.}

\fcode{ct}{bigint\_matrix}{const base\_matrix\LT bigint\GT \& A}
{
constructs a copy of matrix A.}

\fcode{dt}{\SIM bigint\_matrix}{}{}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\ARTH
In addition to the arithmetical functions and operators of class \BF{math\_matrix\TEMPL{T}}
you can use the following operators and function:

The operators \TT{bigint\_matrix \% bigint} and \TT{bigint\_matrix \%= bigint} reduce componentwise each 
entry of the given matrix modulo the given \BF{bigint}.

To avoid copying this operator also exist as function:


\fcode{void}{remainder}{bigint\_matrix \& A\k const bigint\_matrix \& B\k const bigint \& e}
{
Let \MATH{r=B.rows} and \MATH{c=B.columns}.
\[\LEFT(\begin{array}{ccc}
a_{0,0} & \LDOTS & a_{0,c-1}\\
\vdots & \ddots & \vdots \\
a_{r-1,0} & \LDOTS & a_{r-1,c-1}
\end{array}\RIGHT)=
\LEFT(\begin{array}{ccc}
b_{0,0} mod\ e & \LDOTS & b_{0,c'-1} mod\ e\\
\vdots & \ddots & \vdots \\
b_{r-1,0} mod\ e & \LDOTS & b_{r'-1,c'-1} mod\ e
\end{array}\RIGHT).\] 
As modulo operation on \MATH{\Z} we use the best remainder function for integers.}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\COMP
Let \MATH{A} be an variable of type \BF{bigint\_matrix}.


\cfcode{bool}{A.is\_column\_zero}{lidia\_size\_t i}{}
\fcode{bool}{is\_column\_zero}{const bigint\_matrix \& A\k lidia\_size\_t i}
{
returns \TRUE\ if all entries of column \MATH{i} of matrix \MATH{A} are zero, \FALSE\ otherwise.}

\cfcode{bool}{A.is\_row\_zero}{lidia\_size\_t i}{}
\fcode{bool}{is\_row\_zero}{const bigint\_matrix \& A\k lidia\_size\_t i}
{
returns \TRUE\ if all entries of row \MATH{i} of matrix \MATH{A} are zero, \FALSE\ otherwise.}

\cfcode{bool}{A.is\_matrix\_zero}{}{}
\fcode{bool}{is\_matrix\_zero}{const bigint\_matrix \& A}
{
returns \TRUE\ if all entries of matrix \MATH{A} are zero, and \FALSE\ otherwise.}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\STITLE{Norms and Bounds}
\cfcode{bigint}{A.max}{}{}
\fcode{bigint}{max}{const bigint\_matrix \& A}
{
returns the maximum of all components of matrix \MATH{A}.}

\cfcode{void}{A.max}{bigint \& x}
{
\MATH{x=\TT{max}(A)}.}

\cfcode{bigint}{A.max\_abs}{}{}
\fcode{bigint}{max\_abs}{const bigint\_matrix \& A}
{
returns the maximum of the absolute values of all components of matrix \MATH{A}.}

\cfcode{void}{A.max\_abs}{bigint \& x}
{
\MATH{x=\TT{max\_abs}(A)}}

\cfcode{bigint}{A.max\_pos}{lidia\_size\_t \& x\k lidia\_size\_t \& y}{}
\fcode{bigint}{max\_pos}{const bigint\_matrix \& A\k lidia\_size\_t \& x\k lidia\_size\_t \& y}
{
returns the element \MATH{a_{x,y}} which is the maximum of all components of matrix \MATH{A}.}

\cfcode{void}{A.max\_pos}{bigint \& m\k lidia\_size\_t \& x\k lidia\_size\_t \& y}
{
\MATH{m=\TT{max\_pos}(A, x, y)}.}

\cfcode{bigint}{A.max\_abs\_pos}{lidia\_size\_t \& x\k lidia\_size\_t \& y}{}
\fcode{bigint}{max\_abs\_pos}{const bigint\_matrix \& A\k lidia\_size\_t \& x\k lidia\_size\_t \& y}
{
returns the element \MATH{a_{x,y}} which is the maximum of the absolute values of all components of 
matrix \MATH{A}.}

\cfcode{void}{A.max\_abs\_pos}{bigint \& m\k lidia\_size\_t \& x\k lidia\_size\_t \& y}
{
\MATH{m=\TT{max\_abs\_pos}(A, x, y)}}


\cfcode{bigint}{A.min}{}{}
\fcode{bigint}{min}{const bigint\_matrix \& A}
{
returns the minimum of all components of \MATH{A}.}

\cfcode{void}{A.min}{bigint \& x}
{
\MATH{x=\TT{min}(A)}}

\cfcode{bigint}{A.min\_abs}{}{}
\fcode{bigint}{min\_abs}{const bigint\_matrix \& A}
{
returns the minimum of the absolute values of all components of matrix \MATH{A}.}

\cfcode{void}{A.min\_abs}{bigint \& x}
{
\MATH{x=\TT{min\_abs}(A)}}

\cfcode{bigint}{A.min\_pos}{lidia\_size\_t \& x\k lidia\_size\_t \& y}{}
\fcode{bigint}{min\_pos}{const bigint\_matrix \& A\k lidia\_size\_t \& x\k lidia\_size\_t \& y}
{
returns the element \MATH{a_{x,y}} which is the minimum of all components of \MATH{A}.}

\cfcode{void}{A.min\_pos}{bigint \& m\k lidia\_size\_t \& x\k lidia\_size\_t \& y}
{
\MATH{m=\TT{min\_pos}(A,x,y)}}

\cfcode{bigint}{A.min\_abs\_pos}{lidia\_size\_t \& x\k lidia\_size\_t \& y}{}
\fcode{bigint}{min\_abs\_pos}{const bigint\_matrix \& A\k lidia\_size\_t \& x\k lidia\_size\_t \& y}
{
returns the element \MATH{a_{x,y}} which is the minimum of the absolute values of all components of 
matrix \MATH{A}.}

\cfcode{void}{A.min\_abs\_pos}{bigint \& x\k lidia\_size\_t \& x\k lidia\_size\_t \& y}
{
\MATH{x=\TT{min\_abs\_pos}(A,x,y)}}


\cfcode{bigint}{A.hadamard}{}{}
\fcode{bigint}{hadamard}{const bigint\_matrix \& A}
{
returns the hadamard bound of \MATH{A}.}

\cfcode{void}{A.hadamard}{bigint \& x}
{
\MATH{x=\TT{hadamard}(A)}}


\fcode{void}{A.row\_norm}{bigint \& x\k lidia\_size\_t i\k long j = 2}
{
sets \MATH{x=\SUM{l=0}{A.columns-1}{|a_{i,l}^j|}}. If \MATH{0\LE i< A.rows} doesn't hold, the 
\TT{lidia\_error\_handler} will be invoked.}

\fcode{bigint}{A.row\_norm}{lidia\_size\_t i\k long j = 2}{}
\fcode{bigint}{row\_norm}{const bigint\_matrix \& A\k lidia\_size\_t i\k long j = 2}
{
returns \MATH{\SUM{l=0}{A.columns-1}{|a_{i,l}^j|}}. If not \MATH{0\LE i< A.rows} the 
\TT{lidia\_error\_handler} will be invoked.}


\fcode{void}{A.column\_norm}{bigint \& x\k lidia\_size\_t i\k long j = 2}
{
sets \MATH{x=\SUM{l=0}{A.rows-1}{|a_{l,i}^j|}}. If not \MATH{0\LE i< A.columns} the 
\TT{lidia\_error\_handler} will be invoked.}

\fcode{bigint}{A.column\_norm}{lidia\_size\_t i\k long j = 2}{}
\fcode{bigint}{column\_norm}{const bigint\_matrix \& A\k lidia\_size\_t i\k long j = 2}
{
returns \MATH{\SUM{l=0}{A.rows-1}{|a_{l,i}^j|}}. If not \MATH{0\LE i< A.columns} the 
\TT{lidia\_error\_handler} will be invoked.}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\STITLE{Randomize}
\fcode{void}{A.randomize}{const bigint \& b}
{
fills matrix \MATH{A} with random values between \MATH{0} and
\MATH{b}. The dimensions of matrix \MATH{A} remain unchanged.}

\fcode{void}{A.randomize\_with\_det}{const bigint \& DET\k const bigint \& b}
{
generates a random matrix \MATH{A} with determinant \MATH{DET}. Internally this 
function creates two triangular matrices with values between \MATH{0} and \MATH{b}. One of these 
matrices has the determinant \MATH{1} and the other determinant \MATH{DET}. So the product of 
these matrices is the wanted matrix \MATH{A}. If matrix
\MATH{A} is not quadratic, the \TT{lidia\_error\_handler} will be invoked.}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\STITLE{Linear Algebra}
If the dimensions of the arguments in the following functions don't fulfill the usual restrictions known 
from linear algebra, the \TT{lidia\_error\_handler} will be invoked. Some of these are marked by (I). These 
functions are interface functions to select the algorithm, which is the fastest one on big, dense matrices. 
Depending on your application, you might want to choose some other algorithm from the list of algorithms 
described in the next section.


\fcode{void}{A.adj}{const bigint\_matrix \& B}{}
\fcode{bigint\_matrix}{adj}{const bigint\_matrix \& B}
{
stores the adjoint matrix of \MATH{B} to \MATH{A}.}


\cfcode{void}{A.charpoly}{base\_vector\LT bigint\GT \& v}{}
\fcode{void}{charpoly}{base\_vector\LT bigint\GT \& v\k const bigint\_matrix \& A}
{
stores the coefficients of the characteristic polynomial of \MATH{A} to \MATH{v}, where \MATH{v[i]} 
contains the coefficient of \MATH{x^i} (see \cite{Mueller94}). Note that the size of vector \MATH{v}
will be adapted if necessary.}


\cfcode{bigint *}{A.charpoly}{}{}
\fcode{bigint *}{charpoly}{const bigint\_matrix \& A}
{
returns an array \MATH{v} of coefficients of the characteristic polynomial of \MATH{A}, where \MATH{v[i]} 
contains the coefficient of \MATH{x^i} (see \cite{Mueller94}).}


\cfcode{bigint}{A.det}{}{}
\fcode{bigint}{det}{const bigint\_matrix \& A}
{
returns the determinant of matrix \MATH{A}.}

\cfcode{void}{A.det}{x}
{
\MATH{x = \TT{det}(A)}.}


\fcode{void}{A.hnf}{}
{
transforms \MATH{A} into hermite normal form. (I)}

\fcode{bigint\_matrix}{hnf}{const bigint\_matrix \& A}
{
returns the hermite normal form of \MATH{A}. (I)}

\fcode{void}{A.hnf}{bigint\_matrix \& T}
{
transforms \MATH{A} in hermite normal form and sets \MATH{T} to the corresponding transformation 
matrix. That means: 
\MATH{A * T=\IT{HNF}(A)} (I).}

\fcode{bigint\_matrix}{hnf}{const bigint\_matrix \& A\k bigint\_matrix \& T}
{
returns the hermite normal form of \MATH{A} and sets \MATH{T} to the corresponding transformation 
matrix. That means:
\MATH{A * T=\IT{HNF}(A)} (I).}


\fcode{void}{A.image}{const bigint\_matrix \& B}
{
stores a base of the image of the homomorphism defined by \MATH{B} to \MATH{A}. That means, the 
columns of matrix \MATH{A} form a generating system of this image.}

\fcode{bigint\_matrix}{image}{const bigint\_matrix \& B}
{
returns a base of the image of the homomorphism defined by \MATH{B}.}


\fcode{void}{A.invimage}{const bigint\_matrix \& B\k const bigint *v}
{
stores the solutions of the linear equation system \MATH{B*x=v} to matrix \MATH{A}. The last column of 
matrix \MATH{A} is a solution \MATH{x} of the system and the other columns form a generating system 
of the kernel of the homomorphism corresponding to matrix \MATH{B}. If there is no solution, matrix 
\MATH{A} has only one column of zeros. If no memory is allocated for array \MATH{v}, the
\TT{lidia\_error\_handler} will be invoked. The behaviour of this function is undefined if \MATH{v} 
has less than \MATH{B.rows} elements.}

\fcode{bigint\_matrix}{invimage}{const bigint\_matrix \& B\k const bigint * v}
{
returns a \BF{bigint\_matrix} \MATH{A} with the following properties: 
The last column of matrix \MATH{A} is a solution \MATH{x} of the system \MATH{B*x=v} and the other 
columns form a generating system of the kernel of the homomorphism corresponding to matrix \MATH{B}. 
If there is no solution, matrix \MATH{A} has only one column of zeros. If no memory is allocated 
for array \MATH{v}, the \TT{lidia\_error\_handler} will be invoked. The behaviour of this function is 
undefined if \MATH{v} has less than \MATH{B.rows} elements.}

\fcode{void}{A.invimage}{const bigint\_matrix \& B\k const math\_vector\LT bigint\GT \&v}
{
stores the solutions of the linear equation \MATH{B*x=v} to matrix \MATH{A}. The last column of 
matrix \MATH{A} is a solution \MATH{x} of the system and the other columns form a generating system 
of the kernel of the homomorphism corresponding to matrix \MATH{B}. If there is no solution, matrix 
\MATH{A} has only one column of zeros. If \MATH{v.size \not= B.rows}, the 
\TT{lidia\_error\_handler} will be invoked.}

\fcode{bigint\_matrix}{invimage}{const bigint\_matrix \& B\k const math\_vector\LT bigint\GT \&v}
{
returns a \BF{bigint\_matrix} \MATH{A} with the following properties: 
The last column of matrix \MATH{A} is a solution \MATH{x} of the system \MATH{B*x=v} and the other 
columns form a generating system of the kernel of the homomorphism corresponding to matrix \MATH{B}. 
If there is no solution, matrix \MATH{A} has only one column of zeros. If \MATH{v.size \not= B.rows},
the \TT{lidia\_error\_handler} will be invoked.}


\fcode{void}{A.kernel}{const bigint\_matrix \& B}
{
stores a basis of the kernel of the homomorphism defined by matrix \MATH{B} to \MATH{A} 
(see \cite{Mueller94}), i.e. the columns of the matrix A form a generating system of the kernel (I).}

\fcode{bigint\_matrix}{kernel}{const bigint\_matrix \& B}
{
stores a basis of the kernel of the homomorphism defined by matrix \MATH{B} to \MATH{A} 
(see \cite{Mueller94}), i.e. the columns of the matrix A form a generating system of the kernel (I).}


\cfcode{bigint}{A.latticedet}{}{}
\fcode{bigint}{latticedet}{const bigint\_matrix \& A}
{
returns a positive multiple of the determinant of the lattice generated by the columns of \MATH{A} 
(see \cite{Due91}) (I).}

\cfcode{void}{A.latticedet}{bigint \& x}
{
\MATH{x=\TT{latticedet}(A)} (I).}


\cfcode{lidia\_size\_t *}{A.lininc}{}{}
\fcode{lidia\_size\_t *}{lininc}{const bigint\_matrix \& A}
{
returns an array of type \BF{lidia\_size\_t} with the rank of \MATH{A} (at position zero) followed by the 
indices of the linearly independent columns of \MATH{A}.}

\cfcode{void}{A.lininc}{base\_matrix\LT lidia\_size\_t\GT \& v}{}
\fcode{void}{lininc}{base\_matrix\LT lidia\_size\_t\GT \& v\k const bigint\_matrix \& A}
{
stores the rank of \MATH{A} (at position zero) in \BF{base\_vector} \MATH{v} followed by the 
indices of the linearly independent columns of \MATH{A}. Note that the size of vector \MATH{v}
will be adapted if necessary.}


\cfcode{lidia\_size\_t *}{A.lininr}{}{}
\fcode{lidia\_size\_t *}{lininr}{const bigint\_matrix \& A}
{
returns an array of type \BF{lidia\_size\_t} with the rank of \MATH{A} (at position zero) followed by the 
indices of the linearly independent rows of \MATH{A} (see \cite{Mueller94}).}

\cfcode{void}{A.lininr}{base\_matrix\LT lidia\_size\_t\GT \& v}{}
\fcode{void}{lininr}{base\_matrix\LT lidia\_size\_t\GT \& v\k const bigint\_matrix \& A}
{
stores the rank of \MATH{A} (at position zero) in \BF{base\_vector} \MATH{v} followed by the 
indices of the linearly independent rows of \MATH{A}. Note that the size of vector \MATH{v}
will be adapted if necessary.}


\cfcode{lidia\_size\_t}{A.rank}{}{}
\fcode{lidia\_size\_t}{rank}{const bigint\_matrix \& A}
{
returns the rank of matrix \MATH{A} (see \cite{Mueller94}).}


\fcode{void}{A.reginvimage}{const bigint\_matrix \& B\k const bigint\_matrix \& C}
{
solves the equation systems \MATH{B*X=C} in the following sense:\\
The function calculates \BF{bigint} multipliers \MATH{g_0}, \LDOTS,\MATH{g_{m-1}}, where 
\MATH{m=C.columns} and a matrix \MATH{X}, such that
\[ B * X = C * \LEFT( \begin{array}{lll}
g_0 & \LDOTS &0\\
\vdots & \ddots & \vdots\\
0& \LDOTS & g_{m-1}
\end{array}
\RIGHT)\]
and sets the matrix
\[ A= \LEFT( \begin{array}{c}
X \\
g_0 \LDOTS g_{m-1}
\end{array} \RIGHT) \]
if \MATH{B} is regular.
Otherwise the \TT{lidia\_error\_handler} will be invoked.}

\fcode{bigint\_matrix}{reginvimage}{const bigint\_matrix \& B\k const bigint\_matrix \& C}
{
solves the equation systems \MATH{B*X=C} in the following sense:\\
The function calculates \BF{bigint} multipliers \MATH{g_0}, \LDOTS, \MATH{g_{m-1}}, where 
\MATH{m=C.columns} and a matrix \MATH{X}, such that
\[ B * X = C * \LEFT( \begin{array}{lll}
g_0 & \LDOTS &0\\
\vdots & \ddots & \vdots\\
0& \LDOTS & g_{m-1}
\end{array}
\RIGHT)\]
and returns the matrix
\[ \LEFT( \begin{array}{c}
X \\
g_0 \LDOTS g_{m-1}
\end{array} \RIGHT) \]
if \MATH{B} is regular.
Otherwise the \TT{lidia\_error\_handler} will be invoked.}


\fcode{void}{A.solve}{const bigint\_matrix \& B\k const bigint * v}
{
stores the solutions of the linear equation \MATH{B*x=v} to matrix \MATH{A}. The last column of 
matrix \MATH{A} is a solution \MATH{x} of the system and the other columns form a generating system 
of the kernel of the homomorphism corresponding to matrix \MATH{B}. If there is no solution, matrix 
\MATH{A} has only one column of zeros. If no memory is allocated 
for the array \MATH{v}, the \TT{lidia\_error\_handler} will be invoked. The behaviour of this function is 
undefined if \MATH{v} has less than \MATH{B.rows} elements.}

\fcode{bigint\_matrix}{solve}{const bigint\_matrix \& B\k const bigint * v}
{
returns a \BF{bigint\_matrix} \MATH{A} with the following properties:
The last column of matrix \MATH{A} is a solution \MATH{x} of the system \MATH{B*x=v} and the other 
columns form a generating system of the kernel of the homomorphism corresponding to matrix \MATH{B}. 
If there is no solution, matrix \MATH{A} has only one column of zeros. If no memory is allocated 
for the array \MATH{v}, the \TT{lidia\_error\_handler} will be invoked. The behaviour of this function is 
undefined if \MATH{v} has less than \MATH{B.rows} elements.}

\fcode{void}{A.solve}{const bigint\_matrix \& B\k const math\_vector\LT bigint\GT \& v}
{
stores the solutions of the linear equation \MATH{B*x=v} to matrix \MATH{A}. The last column of 
matrix \MATH{A} is a solution \MATH{x} of the system and the other columns form a generating system 
of the kernel of the homomorphism corresponding to matrix \MATH{B}. If there is no solution, matrix 
\MATH{A} has only one column of zeros. If \MATH{v.size \not= B.rows}, the 
\TT{lidia\_error\_handler} will be invoked.}

\fcode{bigint\_matrix}{solve}{const bigint\_matrix \& B\k const math\_vector\LT bigint\GT \& v}
{
returns a \BF{bigint\_matrix} \MATH{A} with the following properties:
The last column of matrix \MATH{A} is a solution \MATH{x} of the system \MATH{B*x=v} and the other 
columns form a generating system of the kernel of the homomorphism corresponding to matrix \MATH{B}. 
If there is no solution, matrix \MATH{A} has only one column of zeros. If \MATH{v.size \not= B.rows},
the \TT{lidia\_error\_handler} will be invoked.}


\fcode{void}{A.snf}{}
{
transforms \MATH{A} to Smith Normal Form (I).}

\fcode{bigint\_matrix}{snf}{const bigint\_matrix \& A}
{
returns the Smith Normal Form of \MATH{A}(I).}

\fcode{void}{A.snf}{bigint\_matrix \& B\k bigint\_matrix \& C}
{
transforms \MATH{A} in Smith Normal Form and sets \MATH{B}, \MATH{C} to the corresponding transformation 
matrices with \TT{snf}\MATH{(A) = B * A * C} (I).}

\fcode{bigint\_matrix}{snf}{const bigint\_matrix \& A\k bigint\_matrix \& B\k bigint\_matrix \& C}
{
returns the Smith Normal Form of \MATH{A} and sets \MATH{B}, \MATH{C} to the corresponding transformation 
matrices with \TT{snf}\MATH{(A) = B * A * C} (I).}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\STITLE{Special functions}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\SSTITLE{Multiple of the lattice determinant}
\begin{enumerate}
\item Method:

\cfcode{bigint}{A.latticedet1}{}{}
\fcode{bigint}{latticedet1}{const bigint\_matrix \& A}
{
returns a positive multiple of the determinant of the lattice generated by the columns of \MATH{A} 
(see \cite{Due91}).}

\cfcode{void}{A.latticedet1}{bigint \& x}
{
\MATH{x=\mbox{\TT{latticedet1}}(A)}}
\item Method:

\cfcode{bigint}{A.latticedet2}{}{}
\fcode{bigint}{latticedet2}{const bigint\_matrix \& A}
{
returns a positive multiple of the determinant of the lattice generated by the columns of \MATH{A}.
First this functions computes two regular submatrices with full rank. Then it computes the 
determinants \MATH{DET1} and \MATH{DET2} of these matrices. Finally it returns the greates common 
divisor of \MATH{DET1} and \MATH{DET2}.}

\cfcode{void}{A.latticedet2}{bigint \& x}
{
\MATH{x=\mbox{\TT{latticedet2}}(A)}}
\item Method:

\cfcode{bigint}{A.latticedet3}{}{}
\fcode{bigint}{latticedet3}{const bigint\_matrix \& A}
{
returns a positive multiple of the determinant of the lattice generated by the columns of \MATH{A}. 
In the first step the columns of matrix \MATH{A} are sorted by the euclidian norm. Next it computes 
a regular submatrix with full rank generated by columns with
norm as small as possible. Finally it 
returns the determinant of this builded matrix.}

\cfcode{void}{A.latticedet3}{bigint \& x}
{
\MATH{x=\mbox{\TT{latticedet3}}(A)}}
\end{enumerate}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\SSTITLE{Kernel}
\begin{enumerate}
\item Method:

\fcode{void}{A.kernel1}{const bigint\_matrix \& B}
{
stores a basis of the kernel of the homomorphism generated by matrix \MATH{B} to \MATH{A}.}

\fcode{bigint\_matrix}{kernel1}{const bigint\_matrix \& B}
{
returns a matrix where the columns form a base of the kernel of
the homomorphism generated by matrix \MATH{B}.}
The underlying  algorithm of these two functions is described in \cite{Mueller94}.
\item Method:

\fcode{void}{A.kernel2}{const bigint\_matrix \& B}
{
stores a basis of the kernel of the homomorphism with matrix
\MATH{B} to \MATH{A}.}

\fcode{bigint\_matrix}{kernel2}{const bigint\_matrix \& B}
{
returns a matrix where the columns form a base of the kernel of
the homomorphism generated by matrix \MATH{B}.}
The underlying algorithm of these two functions works as follow:

In a first step the algorithm computes the Hermite Normal Form of
matrix \MATH{B} and the corresponding transformation matrix
\MATH{T\!R} by using \TT{B.hnf\_havas()} (Description of this
algorithm follows later.) Then it counts the number of leading zero
columns in the normal form, say \MATH{l} is this number. Finally the
leading \MATH{l} columns of the matrix \MATH{T\!R} build the searched
basis.
\end{enumerate}
The differences in the results of these functions are that
on the one hand \SF{kernel1} usually creates a basis with smaller entries than
\SF{kernel2} but on the other hand the kernel2 functions are faster.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\SSTITLE{Hermite Normal Form}
The following functions transform the given matrix in Hermite Normal Form (HNF). 
A matrix \MATH{A} in HNF is an upper triangular matrix with:
\begin{center}
\MATH{a_{i,A.columns-A.rows+i}>a_{i,j}\GE 0\quad  \forall j > (A.columns-A.rows+i)}
\end{center}
In these functions we assume that for the given matrices the rank is equal to the number of rows. If this 
condition is not fulfilled, the functions using modular methods for the
computation (i.e. the functions, whose names start with \TT{hnfmod}) invoke the 
\TT{lidia\_error\_handler}, whereas the other functions terminate at 
the position, where this is detected, returning a partially HNF reduced matrix.
\begin{enumerate}
\item Method:

\fcode{void}{A.hnf\_simple}{}
{
transforms \MATH{A} to Hermite Normal Form using Gaussian Elimination.}

\fcode{bigint\_matrix}{hnf\_simple}{const bigint\_matrix \& A}
{
returns the Hermite Normal Form of \MATH{A} using Gaussian Elimination.}

\fcode{void}{A.hnf\_simple}{bigint\_matrix \& T}
{
transforms \MATH{A} in Hermite Normal Form and sets \MATH{T} to the corresponding transformation 
matrix (i.e. \IT{HNF}\MATH{(A) = A * T}) using a variant of Gaussian Elimination.}

\fcode{bigint\_matrix}{hnf\_simple}{const bigint\_matrix \& A\k bigint\_matrix \& T}
{
returns the Hermite Normal Form of \MATH{A} and sets \MATH{T} to the corresponding transformation 
matrix (i.e. \IT{HNF}\MATH{(A) = A * T}) using a variant of Gaussian Elimination.}
\item Method:

\fcode{void}{A.hnf\_havas}{}
{
transforms \MATH{A} to Hermite Normal Form using results of \cite{HaHoRe93} \cite{HaMa94} and 
\cite{HaSter79}.}

\fcode{bigint\_matrix}{hnf\_havas}{const bigint\_matrix \& A}
{
returns the Hermite Normal Form of \MATH{A} using results of \cite{HaHoRe93} \cite{HaMa94} and 
\cite{HaSter79}.}

\fcode{void}{A.hnf\_havas}{bigint\_matrix \& T}
{
transforms \MATH{A} in Hermite Normal Form and sets \MATH{T} to the corresponding transformation 
matrix (i.e. \IT{HNF}\MATH{(A) = A * T}) using results of \cite{HaHoRe93} \cite{HaMa94} and 
\cite{HaSter79}.}

\fcode{bigint\_matrix}{hnf\_havas}{const bigint\_matrix \& A\k bigint\_matrix \& T}
{
returns the Hermite Normal Form of \MATH{A} and sets \MATH{T} to the corresponding transformation 
matrix (i.e. \IT{HNF}\MATH{(A) = A * T}) using results of \cite{HaHoRe93} \cite{HaMa94} and 
\cite{HaSter79}.}
\item Method:

\fcode{void}{A.hnf\_havas\_cont}{}
{
transforms \MATH{A} to Hermite Normal Form using results of \cite{HaHoRe93} \cite{HaMa94} and 
\cite{HaSter79}. In difference to \TT{A.hnf\_havas()}, this algorithm
produces always an upper triangular matrix even if the rank
of matrix \MATH{A} is not equal to the number of rows of matrix \MATH{A}.}

\fcode{bigint\_matrix}{hnf\_havas\_cont}{const bigint\_matrix \& A}
{
returns the Hermite Normal Form of \MATH{A} using results of \cite{HaHoRe93} \cite{HaMa94} and 
\cite{HaSter79}. In difference to \TT{hnf\_havas(A)}, this algorithm
produces always an upper triangular matrix even if the rank
of matrix \MATH{A} is not equal to the number of rows of matrix \MATH{A}.}

\fcode{void}{A.hnf\_havas\_cont}{bigint\_matrix \& B}
{
transforms \MATH{A} in Hermite Normal Form and sets \MATH{T} to the corresponding transformation 
matrix (i.e. \IT{HNF}\MATH{(A) = A * T}) using results of \cite{HaHoRe93} \cite{HaMa94} and 
\cite{HaSter79}. In difference to \TT{A.hnf\_havas(B)} this algorithm
produces always an upper triangular matrix even if the rank
of matrix \MATH{A} is not equal to the number of rows of matrix \MATH{A}.}

\fcode{bigint\_matrix}{hnf\_havas\_cont}{const bigint\_matrix \& A\k bigint\_matrix \& T}
{
returns the Hermite Normal Form of \MATH{A} and sets \MATH{T} to the corresponding transformation 
matrix (i.e. \IT{HNF}\MATH{(A) = A * T}) using results of \cite{HaHoRe93} \cite{HaMa94} and 
\cite{HaSter79}. In difference to \TT{hnf\_havas(A,T)} this algorithm
produces always an upper triangular matrix even if the rank
of matrix \MATH{A} is not equal to the number of rows of matrix \MATH{A}.}
\item Method:

\fcode{void}{A.hnfmod\_dkt}{}
{
transforms \MATH{A} to Hermite Normal Form using the algorithm of \cite{Dom89}.}

\fcode{bigint\_matrix}{hnfmod\_dkt}{const bigint\_matrix \& A}
{
returns the Hermite Normal Form of \MATH{A} using the algorithm of \cite{Dom89}.}

\fcode{void}{A.hnfmod\_dkt}{const bigint \& x}
{
transforms \MATH{A} in Hermite Normal Form using the algorithm of \cite{Dom89} assuming that 
\MATH{x} is a multiple of the lattice determinant.}

\fcode{bigint\_matrix}{hnfmod\_dkt}{const bigint\_matrix \& A\k const bigint \& x}
{
returns the Hermite Normal Form of \MATH{A} using the algorithm of \cite{Dom89} assuming that 
\MATH{x} is a multiple of the lattice determinant.}
\item Method:

\fcode{void}{A.hnfmod\_cohen}{}
{
transforms \MATH{A} to Hermite Normal Form using the algorithm of \cite{cohen}.}

\fcode{bigint\_matrix}{hnfmod\_cohen}{const bigint\_matrix \& A}
{
returns the Hermite Normal Form of \MATH{A} using the algorithm of \cite{cohen}.}

\fcode{void}{A.hnfmod\_cohen}{const bigint \& x}
{
transforms \MATH{A} in Hermite Normal Form using the algorithm of \cite{cohen} assuming that 
\MATH{x} is a multiple of the lattice determinant.}

\fcode{bigint\_matrix}{hnfmod\_cohen}{const bigint\_matrix \& A\k const bigint \& x}
{
returns the Hermite Normal Form of \MATH{A} using the algorithm of \cite{cohen} assuming that 
\MATH{x} is a multiple of the lattice determinant.}
\item Method:

\fcode{void}{A.hnfmod\_mueller}{bigint\_matrix \& T}
{
transforms \MATH{A} in Hermite Normal Form and sets \MATH{T} to the corresponding transformation 
matrix with \IT{HNF}\MATH{(A) = A * T} (see \cite{Mueller94}).}

\fcode{bigint\_matrix}{hnfmod\_mueller}{const bigint\_matrix \& A\k bigint\_matrix \& T}
{
returns the Hermite Normal Form of \MATH{A} and sets \MATH{T} to the corresponding transformation 
matrix with \IT{HNF}\MATH{(A) = A * T} (see \cite{Mueller94}).}
\end{enumerate}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\SSTITLE{Smith Normal Form}
The following functions tranform the given matrix into Smith Normal Form (SNF). A matrix
in SNF is a diagonal matrix 
\MATH{A=(a_{i,j})_{0 \LEQ i \LEQ n, 0 \LEQ j \LEQ n}} such that for all  \MATH{0 \LEQ i < n}:
\begin{center}
\MATH{a_{i,i}\GE 0}\\
\MATH{a_{n,n}\GE 0}\\
\MATH{a_{i,i} | a_{i+1,i+1}}
\end{center}
\begin{enumerate}
\item Method:

\fcode{void}{A.snf\_simple}{}
{
transforms \MATH{A} to Smith Normal Form using a variant of Gau\ss--Jordan elimination.}

\fcode{bigint\_matrix}{snf\_simple}{const bigint\_matrix \& A}
{
returns the Smith Normal Form of \MATH{A} using a variant of Gau\ss--Jordan elimination.}

\fcode{void}{A.snf\_simple}{bigint\_matrix \& C\k bigint\_matrix \& B}
{
transforms \MATH{A} in Smith Normal Form and sets \MATH{B} and \MATH{C} to the corresponding 
transformation matrices (i.e. \IT{SNF}\MATH{(A) = C * A * B}) using a variant of Gau\ss--Jordan 
elimination.}

\fcode{bigint\_matrix}{snf\_simple}{const bigint\_matrix \& A\k bigint\_matrix \& C\k bigint\_matrix \& B}
{
returns the Smith Normal Form of \MATH{A} and sets \MATH{B} and \MATH{C} to the corresponding 
transformation matrices (i.e. \IT{SNF}\MATH{(A) = C * A * B}) using a variant of Gau\ss--Jordan 
elimination.}
\item Method:

\fcode{void}{A.snf\_hartley}{}
{
transforms \MATH{A} to Smith Normal Form using a variant of the algorithm of Hartley and Hawkes.}

\fcode{bigint\_matrix}{snf\_hartley}{const bigint\_matrix \& A}
{
returns the Smith Normal Form of \MATH{A} using a variant of the algorithm of Hartley and Hawkes.}

\fcode{void}{A.snf\_hartley}{bigint\_matrix \& C\k bigint\_matrix \& B}
{
transforms \MATH{A} in Smith Normal Form and sets \MATH{B} and \MATH{C} to the corresponding 
transformation matrices (i.e. \IT{SNF}\MATH{(A) = C * A* B}) using a variant of the algorithm of 
Hartley and Hawkes.}

\fcode{bigint\_matrix}{snf\_hartley}{const bigint\_matrix \& A\k bigint\_matrix \& C\k bigint\_matrix \& B}
{
returns the Smith Normal Form of \MATH{A} and sets \MATH{B} and \MATH{C} to the corresponding 
transformation matrices (i.e. \IT{SNF}\MATH{(A) = C * A* B}) using a variant of the algorithm of 
Hartley and Hawkes.}
\item Method:

\fcode{void}{A.snf\_havas}{}
{
transforms \MATH{A} to Smith Normal Form using results of \cite{HaHoRe93} \cite{HaMa94} and 
\cite{HaSter79}.}

\fcode{bigint\_matrix}{snf\_havas}{const bigint\_matrix \& A}
{
returns the Smith Normal Form of \MATH{A} using results of \cite{HaHoRe93} \cite{HaMa94} and 
\cite{HaSter79}.}

\fcode{void}{A.snf\_havas}{bigint\_matrix \& C\k bigint\_matrix \& B}
{
transforms \MATH{A} in Smith Normal Form and sets \MATH{B} and \MATH{C} to the corresponding 
transformation matrices (i.e. \IT{SNF}\MATH{(A) = C * A * B}) using results of \cite{HaHoRe93} 
\cite{HaMa94} \cite{HaSter79}.}

\fcode{bigint\_matrix}{snf\_havas}{const bigint\_matrix \& A\k bigint\_matrix \& C\k bigint\_matrix \& B}
{
returns the Smith Normal Form of \MATH{A} and sets \MATH{B} and \MATH{C} to the corresponding 
transformation matrices (i.e. \IT{SNF}\MATH{(A) = C * A * B}) using results of \cite{HaHoRe93} 
\cite{HaMa94} \cite{HaSter79}.}
\end{enumerate}
The following functions are based on results of \cite{HaHoRe93}, \cite{HaMa94} and \cite{HaSter79}.
The extensions \TT{add}, \TT{mult}, \TT{new} specify how column norms and row norms are combined for choosing 
the pivot strategy and the paramter \MATH{k} is used to select the \MATH{L_k}--norm which is used as described in 
these papers (default: \MATH{k = 1}). If \MATH{k < 0} the behaviour of the functions is undefined.

Member functions transform the given (member) matrix in Smith Normal Form.
Functions return the Smith Normal Form of the first argument. 

All functions with more then two arguments compute also the corresponding transformation matrices \MATH{B} and 
\MATH{C} with \IT{SNF}\MATH{(A) = C * A * B}:


\fcode{void}{A.snf\_mult}{lidia\_size\_t k =1}{}
\fcode{bigint\_matrix}{snf\_mult}{const bigint\_matrix \& A\k lidia\_size\_t k = 1}{}
\fcode{void}{A.snf\_mult}{bigint\_matrix \& C\k bigint\_matrix \& B\k lidia\_size\_t k =1}{}
\fcode{bigint\_matrix}{snf\_mult}{const bigint\_matrix \& A\k bigint\_matrix \& C\k bigint\_matrix \& B\k lidia\_size\_t k = 1}{}
\fcode{void}{A.snf\_add}{lidia\_size\_t k = 1}{}
\fcode{bigint\_matrix}{snf\_add}{const bigint\_matrix \& A\k lidia\_size\_t k = 1}{}
\fcode{void}{A.snf\_add}{bigint\_matrix \& C\k bigint\_matrix \& B\k lidia\_size\_t k = 1}{}
\fcode{bigint\_matrix}{snf\_add}{const bigint\_matrix \& A\k bigint\_matrix \& C\k bigint\_matrix \& B\k lidia\_size\_t k = 1}{}
\fcode{void}{A.snf\_new}{lidia\_size\_t k = 1}{}
\fcode{bigint\_matrix}{snf\_new}{const bigint\_matrix \& A\k lidia\_size\_t k = 1}{}
\fcode{void}{A.snf\_new}{bigint\_matrix \& C\k bigint\_matrix \& B\k lidia\_size\_t k = 1}{}
\fcode{bigint\_matrix}{snf\_new}{const bigint\_matrix \& A\k bigint\_matrix \& C\k bigint\_matrix \& B\k lidia\_size\_t k = 1}{}


The following functions use modular algorithms, which are based on \cite{cohen} and \cite{Dom89}.

\begin{enumerate}
\item Method:

\fcode{void}{A.snfmod\_dkt}{}
{
transforms \MATH{A} to Smith Normal Form \cite{Dom89}.}

\fcode{bigint\_matrix}{snfmod\_dkt}{const bigint\_matrix \& A}
{
returns the Smith Normal Form of \MATH{A} \cite{Dom89}.}

\fcode{void}{A.snfmod\_dkt}{const bigint \& x}
{
transforms \MATH{A} to Smith Normal Form assuming that \MATH{x} is a multiple of the lattice 
determinant \cite{Dom89}.}

\fcode{bigint\_matrix}{snfmod\_dkt}{const bigint\_matrix \& A\k const bigint \& x}
{
returns the Smith Normal Form of \MATH{A} assuming that \MATH{x} is a multiple of the lattice 
determinant \cite{Dom89}.}
\item Method:

\fcode{void}{A.snfmod\_cohen}{}
{
transforms \MATH{A} to Smith Normal Form \cite{cohen}.}

\fcode{bigint\_matrix}{snfmod\_cohen}{const bigint\_matrix \& A}
{
returns the Smith Normal Form of \MATH{A} \cite{cohen}.}

\fcode{void}{A.snfmod\_cohen}{const bigint \& x}
{
transforms \MATH{A} to Smith Normal Form assuming that \MATH{x} is a multiple of the lattice 
determinant \cite{cohen}.}

\fcode{bigint\_matrix}{snfmod\_cohen}{const bigint\_matrix \& A\k const bigint \& x}
{
returns the Smith Normal Form of \MATH{A} assuming that \MATH{x} is a multiple of the lattice 
determinant \cite{cohen}.}
\end{enumerate}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\SEEALSO
\BF{base\_matrix}, \BF{math\_matrix}, \BF{base\_vector}, \BF{math\_vector}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\NOTES
By inspection of the file \TT{bigint\_matrix.h} you will discover
additional routines for computing normal forms, the kernel, \dots.
These versions are not yet completely tested, but should be faster
than the well tested functions, that are documented. In the next
release these functions should be included. So, if you feel a bit
adventurous you might try them and help us to debug them.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\EXAMPLES
\begin{verbatim}
 #include <LiDIA/lidia.h>
 #include <LiDIA/bigint_matrix.h>

 main()
 {
   lidia_size_t c = 7, d = 5;
   bigint_matrix A(c,c);
   A.randomize((bigint)10);
   bigint *tmp = A.row(5);
   A.sto_row(tmp,7,3);
   bigint_matrix B, C;

   B = A;
   A.hnf_simple();
   cout << "hnf_simple" << A << flush;

   B = A;
   A.hnf_havas();
   cout << "hnf_havas" << A << flush;

   B = A;
   A.hnf_havas_cont();
   cout << "hnf_havas_cont" << A << flush;

   B = A;
   A.hnf_havas_cont(C);
   cout << A << B*C << flush;
 }
\end{verbatim}        

For further examples please refer to\\
\TT{LiDIA/src/simple\_classes/bigint\_matrix\_appl.c}.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\AUTHOR
Stefan Neis, Patrick Theobald


\end{lidia_man}



