%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
%%  bigmod_matrix.tex       LiDIA documentation
%%
%%  This file contains the documentation of the class bigint_matrix
%%  
%%  Copyright   (c)   1995   by  LiDIA-Group
%%
%%  Author: Stefan Neis
%%  \markright{\BF{bigint\_matrix}}
\begin{lidia_man}

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

\NAME
\BF{bigmod\_matrix} \DOTFILL Linear algebra over \MATH{\Z / m\Z}

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

\ABSTRACT
\BF{bigmod\_matrix} is a class for doing linear algebra over the residue
class ring \MATH{\Z / m\Z}, where \MATH{m} may be any non-negative
integer (for \MATH{m=0} we do the computations over
\MATH{\Z}). 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<k, 0\LE j<l}\IN (\Z / m\Z)^{k\TIMES l},\]
or for representing a homomorphism by its matrix. In the first case, the
class supports for example computing ``standard generating systems'', in
the second case it  may be used for computing the image or the kernel of
the homomorphism.

This version is an experimental version which mainly supplies routines
needed by \BF{modules} and \BF{ideals} in algebraic number fields. However,
we believe, our new algorithms might be of interest also to other
people. Note however, that the interface of this class is not yet very
stable and will change in future releases. Especially it is not yet very
consistent with the template classes for matrices.


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

\DESCRIPTION
A variable of type \BF{bigmod\_matrix} is derived from \BF{bigint\_matrix}
and contains an additional \BF{bigint} \MATH{m} which describes the modulus
of the matrix. Due to this derivation step, you may call all functions
written for \BF{bigint\_matrices} also on \BF{bigmod\_matrices}. Note
however, that the functions inherited from \BF{bigint\_matrix} will not
reduce their results mod \MATH{m}, but the functions written for
\BF{bigmod\_matrix} rely on a reduced input! However quite some functions
of \BF{bigint\_matrix} can be used safely anyway (for example
\TT{transpose} or \TT{diag} with reasonable arguments). However, be very
careful, which functions you do use. Especially the
\TT{sto\_column\_vector} or \TT{sto\_row\_vector} functions should be
avoided.

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}.

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

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


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

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

\fcode{ct}{bigmod\_matrix}{lidia\_size\_t a\k lidia\_size\_t b\k const
  bigint \& m}{
  constructs an \MATH{a \TIMES b} matrix over \MATH{\Z/m\Z} initialized with zero.}

\fcode{ct}{bigmod\_matrix}{const bigmod\_matrix \& A}
{
constructs a copy of matrix \MATH{A}.}

\fcode{ct}{bigmod\_matrix}{const base\_matrix\TEMPL{bigint} \& A\k const
  bigint \& m = 0}
{
 constructs a copy of matrix \MATH{A} where every entry is reduced mod \MATH{m}.}

\fcode{dt}{\SIM bigmod\_matrix}{}{}

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

\ASGN
Let \MATH{A} be of type \BF{bigmod\_matrix}.
The operator \TT{=} is overloaded. For consistency reasons, the following 
functions are also implemented:

\fcode{void}{A.assign}{const bigmod\_matrix \& B}{}

\fcode{void}{assign}{bigmod\_matrix \& A\k const bigmod\_matrix \& B}
{
  sets the dimensions and the modulus of matrix \MATH{A} to the dimensions
  and the modulus of matrix \MATH{B} and copies each entry of \MATH{B} to
  the corresponding position in \MATH{A}.
}

\fcode{void}{A.assign}{const base\_matrix\TEMPL{bigint} \& B\k const bigint
  \& m = 0}{}

\fcode{void}{assign}{bigmod\_matrix \& A\k const base\_matrix\TEMPL{bigint}
  \& B\k const bigint \& m = 0}{
  sets the dimensions of matrix \MATH{A} to the dimensions of matrix
  \MATH{B}, sets the modulus of matrix \MATH{A} to \MATH{m}, and reduces
  each entry of \MATH{B} mod \MATH{m} and stores it to the corresponding
  position in \MATH{A}.}

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

\ACCS
Let \MATH{A} be of type \BF{bigmod\_matrix}. Note that the
numbering of columns and rows starts with zero. Also note that for reading
access the functions of class \BF{bigint\_matrix} and thereby of class
\BF{base\_matrix\TEMPL{bigint}} can safely be used. However for storing
elements, we would like to reduce the elements by the modulus of the
matrix. For this purpose the following functions (and only these!!) are
supported.

\fcode{void}{A.sto\_row}{const bigint *v\k lidia\_size\_t j\k lidia\_size\_t i}
{
stores \MATH{j} entries of array \MATH{v} in row \MATH{i} of matrix 
\MATH{A} starting at column zero, reducing them by the modulus of
\MATH{A}. If \MATH{j>A.columns} or \MATH{j\LEQ 0} or \MATH{i\GEQ A.rows} or
\MATH{i<0}, the \TT{lidia\_error\_handler} will be invoked.
}

\fcode{void}{A.sto\_column}{const bigint *v\k lidia\_size\_t j\k lidia\_size\_t i}
{
stores \MATH{j} entries of array \MATH{v} in column \MATH{i} of 
matrix \MATH{A} starting at row zero, reducing them by the modulus of
\MATH{A}. If \MATH{j>A.rows} or \MATH{j\LEQ 0} or \MATH{i\GEQ A.columns} or
\MATH{i<0}, the  \TT{lidia\_error\_handler} will be invoked.
}

\fcode{void}{A.sto}{lidia\_size\_t i\k lidia\_size\_t j\k const bigint \& x}
{
stores \MATH{x} as \MATH{a_{i,j}} reducing it modulo the modulus of
\MATH{A}. If \MATH{i\GEQ A.rows} or \MATH{i<0} or \MATH{j\GEQ A.columns} or
\MATH{j<0}, the \TT{lidia\_error\_handler} will be invoked.
}

\cfcode{const bigint \&}{A.get\_modulus}{}{}

\fcode{const bigint \&}{get\_modulus}{const bigmod\_matrix \& A}{
  returns the modulus of the matrix \MATH{A}.}

\fcode{void}{A.set\_modulus}{const bigint \& m}{}

\fcode{void}{set\_modulus}{bigmod\_matrix \& A\k const bigint \& m}{
  sets the modulus of the matrix \MATH{A} to \MATH{m}. Note that the
  entries of the matrix are not changed!}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\STITLE{Lifting and Reducing}
Let \MATH{A} be of type \BF{bigmod\_matrix}.

\fcode{void}{A.reduce}{const bigint \& m}{}

\fcode{void}{reduce}{bigmod\_matrix \& A\k const bigint \& m}{
  This interprets \MATH{A} as generating a module over \MATH{\Z/m\Z} (and
  accordingly may modify \MATH{A}). Note that \MATH{m} must divide the
  previously set modulus, since otherwise this is not considered to be a
  valid operation and the \TT{lidia\_error\_handler} will be invoked.}

\fcode{void}{A.lift}{const bigint \& m}{}
\fcode{void}{lift}{bigmod\_matrix \& A\k const bigint \& m}{
  This interprets \MATH{A} as generating a module over \MATH{\Z/m\Z} (and
  accordingly may modify \MATH{A}). Note that \MATH{m} must be a multiple
  of the previously set modulus, since otherwise this is not considered to
  be a valid operation and the \TT{lidia\_error\_handler} will be invoked.}

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

\STITLE{Split Functions}
Let \MATH{A} be of type \BF{bigmod\_matrix}. The following 
split functions allow area overlap of the submatrices
as described in the documentation of the class \BF{base\_matrix\TEMPL{T}}.

If the given conditions in the descriptions of the following functions 
are not fulfilled, the \TT{lidia\_error\_handler} will be invoked.

\cfcode{void}{A.split}{bigmod\_matrix \& B\k bigmod\_matrix \& C\k bigmod\_matrix \& D\k bigmod\_matrix \& E}
{
takes matrix \MATH{A} apart into the submatrices \MATH{B}, \MATH{C}, 
\MATH{D}, and \MATH{E}, with
\latex{\[A=\LEFT(\begin{array}{cc} B & C \\ D & E \end{array}\RIGHT)\]}
\html{\begin{verbatim}

           ( B C )
       A = (     )
           ( D E )
         
\end{verbatim}}
where the following conditions have to be fulfilled: 

\vspace{0.2cm} 
\centerline{\MATH{B.rows,C.rows,D.rows,E.rows \LE A.rows}}
\centerline{\MATH{B.columns,C.columns,D.columns,E.columns \LE A.columns}.}
The entries that are stored into \MATH{B}, \MATH{C}, \MATH{D}, and
\MATH{E}, respectively, are always reduced modulo the corresponding modulus.
}

\cfcode{void}{A.split\_h}{bigmod\_matrix \& B\k bigmod\_matrix \& C}
{
takes matrix \MATH{A} apart into the submatrices \MATH{B} and 
\MATH{C}, with \latex{\MATH{A=\LEFT(\begin{array}{cc} B & C
\end{array}\RIGHT)}}\html{\MATH{A = ( B C )}},
where the following conditions have to be fulfilled:

\vspace{0.2cm}
\centerline{\MATH{B.rows,C.rows \LE A.rows}}
\centerline{\MATH{B.columns,C.columns \LE A.columns}.}
The entries that are stored into \MATH{B} and \MATH{C}, respectively, are
always reduced modulo the corresponding modulus.
}

\cfcode{void}{A.split\_v}{bigmod\_matrix \& B\k bigmod\_matrix \& C}
{
takes matrix \MATH{A} apart into the submatrices \MATH{B} and 
\MATH{C}, with \latex{\MATH{A=\LEFT(\begin{array}{c} B \\ C
\end{array}\RIGHT)}}\html{\MATH{A = ( B C )^t}},
where the following conditions have to be fulfilled:

\vspace{0.2cm}
\centerline{\MATH{B.rows,C.rows \LE A.rows}}
\centerline{\MATH{B.columns,C.columns \LE A.columns}.}
The entries that are stored into \MATH{B} and \MATH{C}, respectively, are
always reduced modulo the corresponding modulus.
}

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

\STITLE{Compose Functions}
Let \MATH{A} be of type \BF{bigmod\_matrix}. The following 
compose functions allow area overlap of the submatrices as described in the
documentation of class \BF{base\_matrix\TEMPL{T}}.
The matrices \MATH{B}, \MATH{C}, \MATH{D} and \MATH{E} remain unchanged.
\medskip\\
If the given conditions in the descriptions of the following functions 
are not fulfilled, the \TT{lidia\_error\_handler} will be invoked.

\fcode{void}{A.compose}{const bigmod\_matrix \& B\k const bigmod\_matrix \& C\k const bigmod\_matrix \& D\k const bigmod\_matrix \& E}
{
composes the matrices \MATH{B}, \MATH{C}, \MATH{D} and \MATH{E} to 
the matrix \MATH{A}, with 
\latex{\MATH{A=\LEFT(\begin{array}{cc} B & C \\ D & E \end{array}\RIGHT)}}
\html{\begin{verbatim}
     ( B C )
 A = (     )
     ( D E )
\end{verbatim}}
where the following conditions have to be fulfilled:

\vspace{0.2cm}
\centerline{\MATH{B.rows,C.rows,D.rows,E.rows \LE A.rows}}
\centerline{\MATH{B.columns,C.columns,D.columns,E.columns \LE A.columns}.}
The entries that are stored into \MATH{A} are always reduced modulo the
modulus of \MATH{A}. 
}

\fcode{void}{A.compose\_h}{const bigmod\_matrix \& B\k const bigmod\_matrix \& C}
{
composes the matrices \MATH{B} and \MATH{C} to the matrix \MATH{A}, 
with \latex{\MATH{A=\LEFT(\begin{array}{cc} B & C \end{array}\RIGHT)}}
\html{\MATH{A = ( B C )}} where 
the following conditions have to be fulfilled:

\vspace{0.2cm}
\centerline{\MATH{B.rows,C.rows \LE A.rows}}
\centerline{\MATH{B.columns,C.columns \LE A.columns}.}
The entries that are stored into \MATH{A} are always reduced modulo the
modulus of \MATH{A}. 
}

\fcode{void}{A.compose\_v}{const bigmod\_matrix \& B\k const bigmod\_matrix \& C}
{
composes the matrices \MATH{B} and \MATH{C} to the matrix \MATH{A}, 
with \latex{\MATH{A=\LEFT(\begin{array}{c} B \\ C \end{array}\RIGHT)}}
\html{\MATH{A = ( B C )^t}}
where the following conditions have to be fulfilled:

\vspace{0.2cm}
\centerline{\MATH{B.rows,C.rows \LE A.rows}}
\centerline{\MATH{B.columns,C.columns \LE A.columns}.}
The entries that are stored into \MATH{A} are always reduced modulo the
modulus of \MATH{A}. 
}

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

\STITLE{Swap Functions}
Obviously, the function \TT{swap\_rows} and \TT{swap\_columns} of class
\BF{bigint\_matrix} (or more precisely of \TT{base\_matrix\TEMPL{T}}) can
be safely used. Moreover there is the following function.

\fcode{void}{swap}{bigmod\_matrix \& A\k bigmod\_matrix \& B}
{
  swaps \MATH{A} and \MATH{B}.
}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\ARTH
The class \BF{bigmod\_matrix} supports the following operators, which
always involve reduction by the modulus of the input matrices.\hfill\\
\begin{tabular}{|c|rcl|l|}\hline
unary & & \MATH{op} & bigmod\_matrix & \MATH{op\IN\{\TT{-}\}} \\\hline
binary & bigmod\_matrix & \MATH{op} & bigmod\_matrix 
& \MATH{op\IN\{\TT{+},\TT{-},\TT{*}\}}\\\hline
binary with & bigmod\_matrix & \MATH{op} & bigmod\_matrix
& \MATH{op\IN\{\TT{+=},\TT{-=},\TT{*=}\}}\\
assignment & & & &\\\hline
binary & bigmod\_matrix & \MATH{op} & bigint
& \MATH{op \IN\{\TT{+},\TT{-},\TT{*}\}}\\\hline
binary with & bigmod\_matrix & \MATH{op} & bigint
& \MATH{op \IN\{\TT{+=},\TT{-=},\TT{*=}\}}\\
assignment & & & &\\\hline
binary & bigmod\_matrix & \MATH{op} & (bigint *) & \MATH{op \IN\{\TT{*}\}}\\\hline
\end{tabular}

Here the operators operating on two matrices and the unary minus implement
the usual operations known from linear algebra. Especially the moduli of
the input matrices have to be the same, otherwise the
\TT{lidia\_error\_handler} will be invoked; if the dimensions of the
operands do not fulfill the usual restrictions, the
\TT{lidia\_error\_handler} will also be invoked. Note that the dimensions
of the resulting matrix are adapted to the right dimensions known from linear
algebra if necessary.

The operator \TT{bigmod\_matrix\ * (bigint *)}
realizes the matrix--vector--multiplication. If the number of elements
does not fulfill the usual restrictions known from linear algebra the
behaviour is undefined.

The operators \MATH{op} which have a single element of type \BF{bigint} in
their list of arguments perform the operation \MATH{op} componentwise and
reduce the result by the modulus of the matrix.
E.g.~\TT{bigmod\_matrix*bigint} multiplies each entry of the matrix
by the given scalar, and reduces by the modulus of the matrix.

To avoid copying, all operators also exist as functions and of course the restrictions for the dimensions are 
still valid:

\fcode{void}{add}{bigmod\_matrix \& C\k const bigmod\_matrix \& A\k const bigmod\_matrix \& B}
{
\MATH{C=A+B}.}

\fcode{void}{add}{bigmod\_matrix \& C\k const bigmod\_matrix \& B\k const bigint \& e}
{
Let \MATH{r=B.rows} and \MATH{c=B.columns}.
\[\LEFT(\begin{array}{ccc}
c_{0,0} & \LDOTS & c_{0,c-1}\\
\vdots & \ddots & \vdots \\
c_{r-1,0} & \LDOTS & c_{r-1,c-1}
\end{array}\RIGHT)=
\LEFT(\begin{array}{ccc}
b_{0,0}+e & \LDOTS & b_{0,c-1}+e\\
\vdots & \ddots & \vdots \\
b_{r-1,0}+e & \LDOTS & b_{r-1,c-1}+e
\end{array}\RIGHT).\]}

\fcode{void}{subtract}{bigmod\_matrix \& C\k const bigmod\_matrix \& A\k const bigmod\_matrix \& B}
{
\MATH{C=A-B}.}

\fcode{void}{subtract}{bigmod\_matrix \& C\k const bigmod\_matrix \& B\k const bigint \& e}
{
Let \MATH{r=B.rows} and \MATH{c=B.columns}.
\[\LEFT(\begin{array}{ccc}
c_{0,0} & \LDOTS & c_{0,c-1}\\
\vdots & \ddots & \vdots \\
c_{r-1,0} & \LDOTS & c_{r-1,c-1}
\end{array}\RIGHT)=
\LEFT(\begin{array}{ccc}
b_{0,0}-e & \LDOTS & b_{0,c-1}-e\\
\vdots & \ddots & \vdots \\
b_{r-1,0}-e & \LDOTS & b_{r-1,c-1}-e
\end{array}\RIGHT).\]}

\fcode{void}{multiply}{bigmod\_matrix \& C\k const bigmod\_matrix \& A\k           const bigmod\_matrix \& B}
{
\MATH{C=A*B}.}


\fcode{void}{multiply}{bigmod\_matrix\& C\k const bigmod\_matrix \& B\k const bigint \& e}
{
Let \MATH{r=B.rows} and \MATH{c=B.columns}.
\[\LEFT(\begin{array}{ccc}
c_{0,0} & \LDOTS & c_{0,c-1}\\
\vdots & \ddots & \vdots \\
c_{r-1,0} & \LDOTS & c_{r-1,c-1}
\end{array}\RIGHT)=
\LEFT(\begin{array}{ccc}
b_{0,0}*e & \LDOTS & b_{0,c-1}*e\\
\vdots & \ddots & \vdots \\
b_{r-1,0}*e & \LDOTS & b_{r-1,c-1}*e
\end{array}\RIGHT).\] Note that in this special case reduction is done by
the modulus of \MATH{C}. This is helpful in some contexts while disturbing
in others!}


\fcode{void}{multiply}{bigint *\&v\k const bigmod\_matrix \& A\k const bigint *w}
{
  assigns the result of the muliplication \MATH{A * w} to \MATH{v}
  (matrix--vector--multiplication). If a suitable amount of memory has not
  been allocated for the arrays \MATH{w} and \MATH{v}, the behaviour of
  this function is undefined.}

\fcode{void}{negate}{bigmod\_matrix\& B\k const bigmod\_matrix \& A}
{
\MATH{B = -A}.}

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

\COMP
The  binary operators \TT{==} and \TT{!=} are overloaded and can be used for comparison by components. 
Let \MATH{A} be an instance of type \BF{bigmod\_matrix}.


\cfcode{bool}{A.equal}{const bigmod\_matrix \& B}
{
returns \TRUE\ if \MATH{A} and \MATH{B} are identical, \FALSE\ otherwise.}

\fcode{bool}{equal}{const bigmod\_matrix \& A\k const bigmod\_matrix \& B}
{
returns \TRUE\ if \MATH{A} and \MATH{B} are identical, \FALSE\ otherwise.}

\cfcode{bool}{A.unequal}{const bigmod\_matrix \& B}
{
returns \FALSE\ if \MATH{A} and \MATH{B} are identical, \TRUE\ otherwise.}

\fcode{bool}{unequal}{const bigmod\_matrix \& A\k const bigmod\_matrix \& B}
{
returns \FALSE\ if \MATH{A} and \MATH{B} are identical, \TRUE\ otherwise.}

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

\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. Linear algebra over
\MATH{\Z/m\Z} can be done following two philosophies: Either you are content
to get a partial result and a factor of \MATH{m} (for example for reducing
the partial result and using the chinese remainder theorem. This however is
not very good for ``small'' \MATH{m}) or you want a result over
\MATH{\Z/m\Z} no matter what. Since this can also be done efficiently, we
offer both methods. So far, however, not both versions of all functions are
supported.


\fcode{void}{A.adj}{const bigmod\_matrix \& B\k bigint \& f}{}
\fcode{bigmod\_matrix}{adj}{const bigmod\_matrix \& B\k bigint \& f}
{
  stores either the adjoint matrix of \MATH{B} to \MATH{A} or a
  non--trivial factor of \MATH{m} to \MATH{f}.}

\fcode{void}{A.inv}{const bigmod\_matrix \& B\k bigint \& f}{}
\fcode{bigmod\_matrix}{inv}{const bigmod\_matrix \& B\k bigint \& f}
{
  stores either the inverse matrix of \MATH{B} to \MATH{A} or a
  non--trivial factor of \MATH{m} to \MATH{f}.}


\cfcode{bigint *}{A.charpoly}{bigint \& f}{}
\fcode{bigint *}{charpoly}{const bigmod\_matrix \& A, bigint \& f}
{
returns either an array \MATH{v} of coefficients of the characteristic
polynomial of \MATH{A}, where \MATH{v[i]} contains the coefficient of
\MATH{x^i} or sets \MATH{f} to some non--trivial factor of \MATH{m}.}


\cfcode{bigint}{A.det}{bigint \& f}{}
\fcode{bigint}{det}{const bigmod\_matrix \& A\k bigint \& f}
{
either returns the determinant of matrix \MATH{A} or sets \MATH{f} to some
non--trivial factor of \MATH{m}.}

\cfcode{void}{A.det}{bigint \& x\k bigint \& f}
{
 either \MATH{x = \TT{det}(A)} or \MATH{f} is set  to some non--trivial
 factor of \MATH{m}.}

\fcode{void}{A.image}{const bigmod\_matrix \& B\k bigint \& f}
{
  either stores a generating system of the image of the homomorphism defined by
  \MATH{B} to \MATH{A} or sets \MATH{f} to some non--trivial factor of \MATH{m}.}

\fcode{bigmod\_matrix}{image}{const bigmod\_matrix \& B\k bigint \& f}
{
  either returns a generating system of the image of the homomorphism defined by
  \MATH{B} or sets \MATH{f} to some non--trivial factor of \MATH{m}.} 

\fcode{void}{A.image}{const bigmod\_matrix \& B}
{
  stores a generating system of the image of the homomorphism defined by
  \MATH{B} to \MATH{A}.}

\fcode{bigmod\_matrix}{image}{const bigmod\_matrix \& B}
{
  returns a generating system of the image of the homomorphism defined by
  \MATH{B}.} 

\fcode{void}{A.unique\_image}{const bigmod\_matrix \& B}
{
  stores a uniquely determined generating system of the image of the
  homomorphism defined by \MATH{B} to \MATH{A} .}

\fcode{bigmod\_matrix}{unique\_image}{const bigmod\_matrix \& B}
{
  returns a uniquely determined generating system of the image of the
  homomorphism defined by \MATH{B}.} 

\fcode{void}{A.kernel}{const bigmod\_matrix \& B\k bigint \&f}{
  either stores a generating system of the kernel of the homomorphism
  defined by matrix \MATH{B} to \MATH{A} or sets \MATH{f} to some
  non--trivial factor of \MATH{m}.}

\fcode{bigmod\_matrix}{kernel}{const bigmod\_matrix \& B\k bigint \& f}{
  either returns a generating system of the kernel of the homomorphism defined by
  matrix \MATH{B} to \MATH{A} or sets \MATH{f} to some non--trivial factor
  of \MATH{m}.}
\fcode{void}{A.kernel}{const bigint\_matrix \& B}
{
stores a generating system of the kernel of the homomorphism defined by
matrix \MATH{B} to \MATH{A}.} 

\fcode{bigint\_matrix}{kernel}{const bigint\_matrix \& B}
{
  returns a generating system of the kernel of the homomorphism defined by
  matrix \MATH{B} to \MATH{A}.} 


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

\IO
The \BF{istream} operator \TT{>>} and the \BF{ostream} operator 
\TT{<<} are overloaded. The \BF{istream} operator \TT{>>} reads 
matrices in the following format from istream:
 
\[r \SQCUP c \SQCUP m \SQCUP a_{0,0} \SQCUP a_{0,1} \SQCUP 
\LDOTS \SQCUP a_{0,c-1} \SQCUP a_{1,0} \SQCUP \LDOTS \SQCUP a_{1,c-1}
\SQCUP  \LDOTS \SQCUP a_{r-1,0} \SQCUP \LDOTS \SQCUP a_{r-1,c-1}\]
where \MATH{r = A.rows}, \MATH{c = A.columns}, and \MATH{m = A.modulus}.

The \BF{ostream} operator \TT{<<} outputs the matrix in a beautified format
which looks as follows:
\latex{
\begin{center}
\[\begin{array}{cccccc}
(& a_{0,0} & a_{0,1} & \LDOTS & a_{0,c-1}&)\\ 
(& a_{1,0} &  \LDOTS & \LDOTS & a_{1,c-1}&)\\
(& \vdots & \vdots & \vdots & \vdots &)\\
(& a_{r-1,0} & \LDOTS &\LDOTS & a_{r-1,c-1}&)
\end{array} {\rm mod}\quad m\]
\end{center}}
\html{\begin{verbatim}
        
 ( a_0,0   a_0,1  .   .   .   a_0,c-1  )
 ( a_1,0     .    .   .   .   a_1,c-1  )
 (   .       .    .   .   .      .     )
 (   .       .    .   .   .      .     )
 (   .       .    .   .   .      .     )
 ( a_r-1,0   .    .   .   .  a_r-1,c-1 ) mod m
        
\end{verbatim}}

For supporting more input and output formats we suggest to read and write
\BF{bigint\_matrices} and the modulus separately, thus enabling all the
formats supported by \BF{bigint\_matrix}.

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

\WARNINGS
The behaviour of the function

\fcode{void}{multiply}{bigmod\_matrix\& C\k const bigmod\_matrix \& B\k
  const bigint \& e}{}
may be surprising sometimes, since the modulus of \MATH{C} is {\em not\/}
set to the modulus of \MATH{B} and reduction is done by the modulus of
\MATH{C}, {\em not\/} by the modulus of \MATH{B}.

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

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

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

\NOTES
\begin{enumerate}
\item As described in the introduction this version is very preliminary.

\item As usually in ''C'' the numbering of columns and rows starts with zero.
\end{enumerate}

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

\AUTHOR
Stefan Neis, Patrick Theobald

\end{lidia_man}