%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
%%  bigint_lattice.tex       LiDIA documentation
%%
%%  This file contains the documentation of the lattice classes 
%%
%%  Copyright   (c)   1995   by  LiDIA-Group
%%
%%  Authors: Thorsten Lauer, Susanne Wetzel
%%

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

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

\NAME
\BF{bigint\_lattice}  \DOTFILL    lattice algorithms

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

\ABSTRACT
The class \BF{bigint\_lattice} is derived from the class 
\BF{bigint\_matrix} and therefore inherits all their functions. 
In addition the class \BF{bigint\_lattice} provides algorithms
for shortest vector computations, lattice reduction of lattice bases 
or linearly independent Gram matrices as well as computations 
of lattice bases and relations from generating systems or linearly 
dependent Gram matrices. A lattice \MATH{L} is given by 
\MATH{A=(a_0, \LDOTS, a_{k-1}) \IN M^{n \TIMES k}} (\MATH{n,k \IN \N}) 
where \MATH{M} consists of elements of type \BF{bigint} and \MATH{A} is
a linearly (in)dependent Gram matrix, a generating system or
a lattice basis of \MATH{L}. 

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

\DESCRIPTION
A variable of type \BF{bigint\_lattice} cosists of the same components as
\BF{bigint\_matrix}.

\medskip
Let \MATH{A} be of class \BF{bigint\_lattice}. In the present version of
\LiDIA\ the following algorithms are implemented:
\begin{enumerate}
 \item Generating systems:
       \begin{itemize}
	\item The MLLL algorithm \cite{ZAS} which computes for a 
              \MATH{k-1}-dimensional lattice \MATH{L} represented by
	      a generating system \MATH{A=(a_0, \LDOTS, a_{k-1}) \IN M^{k-1 \TIMES k}}
              a reduced basis \MATH{B=(b_0, \LDOTS, b_{k-2})} as well as a 
              relation i.e., integers \MATH{x_0, \LDOTS , x_{k-1} \IN \Z~} 
              satisfying \MATH{\SUM{i=0}{k-1}{x_ia_i =0}}.   
	\item The Buchmann-Kessler algorithm \cite{BUK} which computes a reduced
              basis for a lattice represented by a generating system \MATH{A}.
        \item The Schnorr-Euchner algorithm \cite{SEN} (modified for generating
              systems) as well as variations
              \cite{new} which compute an LLL 
	      reduced basis of the lattice \MATH{L} represented by 
              the generating system \MATH{A}.
       \end{itemize}
 \item Lattice bases:
       \begin{itemize}
	\item The original Schnorr-Euchner lattice reduction algorithm \cite{SEN} as
              well as variations \cite{new}. 
	\item The Benne de Weger variation \cite{BEW} of the original
              LLL algorithm \cite{LAK} which uses rational arithmetic.
	\item The Fincke-Pohst algorithm for computing shortest vectors of
              a lattice \MATH{L = \Z a_0 \XOR \dots \XOR \Z a_{k-1}} \cite{FiP}.
        \item The algorithm of Babai \cite{Babai} for computing a close lattice vector to
              a given vector.       
       \end{itemize}
 \item Gram matrices:
       \begin{itemize}
        \item The original Schnorr-Euchner lattice reduction algorithm \cite{SEN} as
              well as variations \cite{new}.
       \end{itemize}
\end{enumerate}
In the following we will explain the constructors, destructors and 
basic functions of the classes \BF{bigint\_lattice}. Lattices can be stored
column by column or row by row. Independent of the the storage mode either
the columns or the rows of the lattice can be reduced. The following 
description is done with respect to column-oriented lattices i.e\ the
reduction is done columnwise. For 
row-oriented lattices one has to change the representation. The 
corresponding computations will then be adjusted automatically.

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

\CONS

For the following constructors the variable \MATH{A} is assumed to 
represent a lattice.  If in the following constructors \MATH{n\LE 1}, 
\MATH{k\LE 1}, \MATH{n < k}, \MATH{A=NULL} or the dimension of \MATH{A}
does not correspond to the input parameters which declare the dimension,
the \TT{lidia\_error\_handler} will be invoked. 

\fcode{ct}{bigint\_lattice}{}
{
constructs a \MATH{1 \TIMES 1} \BF{bigint\_lattice}.
}

\fcode{ct}{bigint\_lattice}{lidia\_size\_t n\k lidia\_size\_t k}
{
constructs a \BF{bigint\_lattice} of \MATH{k} vectors embedded 
in an \MATH{n}-dimensional vector space initialized with zero.
}

\fcode{ct}{bigint\_lattice}{const bigint\_matrix \& A}
{
constructs a copy of \MATH{A}.
}

\fcode{ct}{bigint\_lattice}{lidia\_size\_t n\k lidia\_size\_t k\k bigint** \& A}
{
constructs an \MATH{n\TIMES k}-\BF{bigint\_lattice} initialized 
with the values of the 2-dimensional array \MATH{A} where *\MATH{A} 
is a row vector.
}

\fcode{dt}{\SIM bigint\_lattice}{}{}

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

\INIT

Let \MATH{A} be of type \BF{bigint\_lattice}. If none of the following functions
is called explicitly by the user, \MATH{A} will be considered as column-oriented
generating system representing the lattice \MATH{L}. Changes of the lattice by
the user will automatically result in the deletion of the basis and gram flag.

\fcode{void}{A.set\_basis\_flag}{}
{sets the basis flag without checking whether \MATH{A} fulfills the basis property
or not. For future computations \MATH{A} is now considered as basis 
representing the lattice \MATH{L}. Setting the flag without knowing whether 
\MATH{A} is a basis or not may result in abortions of further computations or
wrong results. By default the representation is set as generating system.
}

\fcode{void}{A.delete\_basis\_flag}{}
{sets the basis flag to \FALSE. For future computations \MATH{A} is now 
considered as generating system representing the lattice \MATH{L}. 
}

\fcode{void}{A.set\_gram\_flag}{}
{sets the gram flag without checking whether \MATH{A} fulfills the properties
of a Gram matrix or not. For future computations \MATH{A} is now considered as 
Gram matrix representing the lattice \MATH{L}. Setting the flag without knowing 
whether \MATH{A} is a Gram matrix or not may result in abortions of further 
computations or wrong results. By default the gram flag is not set.
}

\fcode{void}{A.delete\_gram\_flag}{}
{sets the gram flag to \FALSE.}

\fcode{void}{A.set\_red\_orientation\_columns}{}
{sets the orientation such that the reduction will be done column-oriented.
By default the orientation is taken as column-oriented.
}

\fcode{void}{A.set\_red\_orientation\_rows}{}
{sets the orientation such that the reduction will be done row-oriented.
By default the orientation is taken as column-oriented.
}

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

\BASIC

Let \MATH{A} be of type \BF{bigint\_lattice}.

\fcode{bool}{A.check\_basis}{}
{returns \TRUE\ and sets the basis flag if the columns or rows of \MATH{A} are 
linearly independent
according to the orientation of \MATH{A}, \FALSE\ otherwise.
}

\fcode{bool}{A.check\_gram}{}
{returns \TRUE\ and sets the gram flag if \MATH{A} is symmetric and positive 
semi-definete and therefore
fulfills the properties of a Gram matrix, \FALSE\ otherwise.
}

\fcode{bool}{A.get\_basis\_flag}{}
{returns \TRUE\ if the basis flag is set, \FALSE\ otherwise. 
}

\fcode{bool}{A.get\_gram\_flag}{}
{returns \TRUE\ if the gram flag is set, \FALSE\ otherwise. 
}

\fcode{bool}{A.get\_red\_orientation}{}
{returns \TRUE\ for column-oriented lattices, \FALSE\ otherwise. 
}

\fcode{bool}{A.lll\_check}{double y}
{
returns \TRUE\ if the basis is reduced for the reduction parameter 
\MATH{y}, \FALSE\ otherwise. The \TT{lidia\_error\_handler} will be invoked
if the function is applied to generating systems or the gram flag is set.
}

\fcode{bool}{A.lll\_check}{sdigit p\k sdigit q}
{
returns \TRUE\ if the basis is reduced for the reduction parameter 
\MATH{\FRAC{p}{q}}, \FALSE\ otherwise.
The \TT{lidia\_error\_handler} will be invoked
if the function is applied to generating systems or the gram flag is set.
}

\fcode{double}{A.lll\_check\_search}{}
{
if \MATH{A} is LLL reduced, this function will return the largest
\MATH{y\IN ]\FRAC{1}{2},1]} for which the basis \MATH{A} is still LLL reduced, 
see \cite{LAK,SEN}. If the basis \MATH{A} is not LLL reduced, \MATH{0.0} 
will be returned.
The \TT{lidia\_error\_handler} will be invoked
if the function is applied to generating systems or the gram flag is set.
}

\fcode{void}{A.lll\_check\_search}{sdigit p\&\k sdigit\& q}
{
if \MATH{A} is LLL reduced, this function will return the largest
\MATH{\FRAC{p}{q}\IN ]\FRAC{1}{2},1]} for which the basis \MATH{A} is still 
LLL reduced, see \cite{LAK,SEN}. If the basis \MATH{A} is not LLL reduced, 
0 will be returned. The \TT{lidia\_error\_handler} will be invoked
if the function is applied to generating systems or the gram flag is set.
}

\fcode{void}{A.randomize\_vectors}{}
{
permutes the vectors of the given lattice randomly.
}

\fcode{void}{A.sort\_vectors}{bin\_cmp\_func}
{
sorts the vectors of the given lattice such that their lengths 
(length in the meaning of the \MATH{bin\_cmp\_func}, which is defined 
as \TT{int (*bin\_cmp\_func)(const bigint*, const bigint*, long)}) are in 
descending order. The function \TT{bin\_cmp\_func} has to return \MATH{-1}
(\MATH{1}) if the first vector is shorter (longer) as the second one and 
\MATH{0} if they have the same length.
}

\fcode{void}{A.sort\_big\_vectors}{}
{
sorts the vectors of the given lattice such that their lengths 
(by means of the Euclidian norm) are in descending order.
}

\fcode{void}{A.sort\_small\_vectors}{}
{
sorts the vectors of the given lattice such that their lengths 
(by means of the Euclidian norm) are in ascending order.
}

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

\STITLE{Lattice Reduction}

The following functions can be used for performing LLL reductions.
These functions are interface functions and point to the fastest algorithms 
described in the section 'Special Functions' for solving arbitrarily chosen
lattice instances. Depending on the application of the lattice problem you
might want to use a different algorithm mentioned in that section though.
Please note that those algorithms might change in the future and we
therefore suggest to use the interface functions. At the moment the
interface functions point to the \TT{lll\_schnorr\_euchner\_orig} implementation. 

\medskip
The union {\TT lattice\_info} is defined as:
\begin{verbatim}
typedef union {
          struct {
            lidia_size_t rank;
            double y;
            sdigit y_nom;
            sdigit y_denom; 
            sdigit reduction_steps;
            sdigit correction_steps;
            sdigit swaps;
          } lll;
        } lattice_info;
\end{verbatim}
So far {\TT lattice\_info} provides only information about the performed LLL 
reduction (e.g.\ number of swaps, reduction or correction steps) but in the future
the union will be extended for providing information about the performance of
other lattice algorithms. 

\medskip
In order to use a self-defined scalar product one has to define four functions
corresponding to the following typedefs:
\begin{verbatim}
typedef void (*scal_dbl)(double&, double*, double*, lidia_size_t);
typedef void (*scal_xdbl)(xdouble&, xdouble*, xdouble*, lidia_size_t);
typedef void (*scal_bin)(bigint&, bigint*, bigint*, lidia_size_t);
typedef void (*scal_bfl)(bigfloat&, bigfloat*, bigfloat*, lidia_size_t);
\end{verbatim}
The first parameter is the return value, the second and third parameter stand
for the input vectors and the last parameter indicates the length of the vectors.
With the addresses of the functions one defines the actual scalar product as:
\begin{verbatim}
typedef struct {
          scal_dbl dbl;
          scal_xdbl xdbl;
          scal_bin bin;
          scal_bfl bfl;
        } user_SP;
\end{verbatim}
Please note that it is allowed to change the precision for \BF{bigfloat}s within
{\TT void (*scal\_bfl)(bigfloat\&, bigfloat*, bigfloat*, lidia\_size\_t);} but
one has to guarantee that after the computation of the scalar product the 
precision is set back to its original value (before entering the function).  

\medskip
Let \MATH{A} be of type \BF{bigint\_lattice}. 

\medskip
\fcode{void}{A.lll}{double y\k lattice\_info \& li\k user\_SP\k sdigit factor = 1}{}
\fcode{bigint\_lattice}{lll}{const bigint\_lattice \& A\k double y\k lattice\_info \& li\k user\_SP\k sdigit factor = 1}{}
\fcode{void}{A.lll}{double y\k lattice\_info \& li\k sdigit factor = 1}{}
\fcode{bigint\_lattice}{lll}{const bigint\_lattice \& A\k double y\k lattice\_info \& li\k sdigit factor = 1}{}
\fcode{void}{A.lll}{double y\k user\_SP\k sdigit factor = 1}{}
\fcode{bigint\_lattice}{lll}{const bigint\_lattice \& A\k double y\k user\_SP\k sdigit factor = 1}{}
\fcode{void}{A.lll}{double y\k sdigit factor = 1}{}
\fcode{bigint\_lattice}{lll}{const bigint\_lattice \& A\k double y\k sdigit factor = 1}
{
if \MATH{A} is not a Gram matrix, these functions compute
\latex{\MATH{A = (\underbrace{a_0, \LDOTS , a_{r-1}}_{=B},\underbrace{0, \LDOTS , 0}_{k-r})}} 
\html{
 A = ( a_0, ..., a_r-1, 0, ..., 0 ),
       \_____  ______/  \___  __/
             \/             \/
             =B             k-r          
}
where \MATH{B} is an LLL reduced basis of \MATH{L} with rank \MATH{r}. For
linearly (in)dependent Gram matrices the computations are done according to
\cite{cohen}. \MATH{y\IN ]\FRAC{1}{2},1]} is the 
reduction parameter. With factor the precision for the
approximations of computations (depending on the algorithm) will be determined as 
(factor \MATH{\CDOT} double precision).  
For factor \MATH{=1} (factor \MATH{=2}) the approximations are done by using doubles
(xdoubles), otherwise \BF{bigfloat}s with appropriate precision will be used.
}

\fcode{void}{A.lll}{math\_matrix<bigint> \& T\k double y\k lattice\_info \& li\k user\_SP\k sdigit factor = 1}{}
\fcode{bigint\_lattice}{lll}{const bigint\_lattice \& A\k math\_matrix<bigint> \& T\k double y\k lattice\_info \& li\k user\_SP\k sdigit factor = 1}{}
\fcode{void}{A.lll}{math\_matrix<bigint> \& T\k double y\k lattice\_info \& li\k sdigit factor = 1}{}
\fcode{bigint\_lattice}{lll}{const bigint\_lattice \& A\k math\_matrix<bigint> \& T\k double y\k lattice\_info \& li\k sdigit factor = 1}{}
\fcode{void}{A.lll}{math\_matrix<bigint> \& T\k double y\k user\_SP\k sdigit factor = 1}{}
\fcode{bigint\_lattice}{lll}{const bigint\_lattice \& A\k math\_matrix<bigint> \& T\k double y\k user\_SP\k sdigit factor = 1}{}
\fcode{void}{A.lll}{math\_matrix<bigint> \& T\k double y\k sdigit factor = 1}{}
\fcode{bigint\_lattice}{lll}{const bigint\_lattice \& A\k math\_matrix<bigint> \& T\k double y\k sdigit factor = 1}
{
if \MATH{A} is not a Gram matrix, these functions compute the transformation matrix \MATH{T}
and
\latex{\MATH{A =(\underbrace{b_0, \LDOTS , b_{r-1}}_{=B},\underbrace{0, \LDOTS , 0}_{k-r})}} 
\html{
 A = ( b_0, ..., b_r-1, 0, ..., 0 ),
       \_____  ______/  \___  __/
             \/             \/
             =B             k-r          
} 
where \MATH{B} is an LLL reduced basis of \MATH{L} with rank \MATH{r}. 
The last \MATH{k-r} columns of \MATH{T} are relations for the original generating
system.
For linearly (in)dependent Gram matrices the computations are done according to
\cite{cohen}. \MATH{y\IN ]\FRAC{1}{2},1]} is the 
reduction parameter. With factor the precision for the
approximations of computations (depending on the algorithm) will be determined as 
(factor \MATH{\CDOT} double precision).  
For factor \MATH{=1} (factor \MATH{=2}) the approximations are done by using doubles
(xdoubles), otherwise \BF{bigfloat}s with appropriate precision will be used.
}

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

\STITLE{Shortest Vector Computation}

Let \MATH{A} be of type \BF{bigint\_lattice}.

\fcode{lidia\_size\_t}{A.shortest\_vector}{math\_matrix<bigint> \& V\k lidia\_size\_t p = 20} 
{}
\fcode{lidia\_size\_t}{shortest\_vector}{const bigint\_lattice \& A\k math\_matrix<bigint> \& V\k lidia\_size\_t p = 20}
{
returns the length of the shortest vector(s) of \MATH{A} and computes the shortest
vector{s} \MATH{V} of \MATH{A} using the Fincke-Pohst algorithm \cite{FiP}. For 
Gram matrices the shortest vector(s) can not be computed explicitly and therefore
\MATH{V} is a \MATH{1 \times 1} matrix with entry zero. By default \MATH{p} is
set to the standard \BF{bigfloat} precision. Depending on the application it might
be necessary to use a higher precision in order to achieve a speed-up of
the computation.   
The \TT{lidia\_error\_handler} will be invoked if the basis flag is not set.
}

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

\STITLE{Close Vector Computation}

Let \MATH{A} be of type \BF{bigint\_lattice}.

\fcode{void}{A.close\_vector}{const base\_vector<bigint> \& v\k base\_vector<bigint>\& w\k sdigit factor = 1} 
{}
\fcode{base\_vector<bigint>}{close\_vector}{const bigint\_lattice \& A\k const base\_vector<bigint> \& v\k sdigit factor = 1}
{
computes a close lattice vector to a given vector \MATH{v} by using the algorithm of Babai \cite{Babai}.  With factor the precision for the approximations of computations of the LLL reduction which
is part of the algorithm of Babai, will be determined as (factor \MATH{\CDOT} double precision).  
For factor \MATH{=1} (factor \MATH{=2}) the approximations are done by using doubles
(xdoubles), otherwise \BF{bigfloat}s with appropriate precision will be used.
The \TT{lidia\_error\_handler} will be invoked if the gram flag is set or the basis flag is not set.
}

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

\STITLE{Special Functions}

The union {\TT lattice\_info} is defined as:
\begin{verbatim}
typedef union {
          struct {
            lidia_size_t rank;
            double y;
            sdigit y_nom;
            sdigit y_denom; 
            sdigit reduction_steps;
            sdigit correction_steps;
            sdigit swaps;
          } lll;
        } lattice_info;
\end{verbatim}
So far {\TT lattice\_info} provides only information about the performed LLL 
reduction (e.g.\ number of swaps, reduction or correction steps) but in the future
the union will be extended for providing information about the performance of
other lattice algorithms. 

\medskip
In order to use a self-defined scalar product one has to define four functions
corresponding to the following typedefs:
\begin{verbatim}
typedef void (*scal_dbl)(double&, double*, double*, lidia_size_t);
typedef void (*scal_xdbl)(xdouble&, xdouble*, xdouble*, lidia_size_t);
typedef void (*scal_bin)(bigint&, bigint*, bigint*, lidia_size_t);
typedef void (*scal_bfl)(bigfloat&, bigfloat*, bigfloat*, lidia_size_t);
\end{verbatim}
The first parameter is the return value, the second and third parameter stand
for the input vectors and the last parameter indicates the length of the vectors.
With the addresses of the functions one defines the actual scalar product as:
\begin{verbatim}
typedef struct {
          scal_dbl dbl;
          scal_xdbl xdbl;
          scal_bin bin;
          scal_bfl bfl;
        } user_SP;
\end{verbatim}
Please note that it is allowed to change the precision for \BF{bigfloat}s within
{\TT void (*scal\_bfl)(bigfloat\&, bigfloat*, bigfloat*, lidia\_size\_t);} but
one has to guarantee that after the computation of the scalar product the 
precision is set back to its original value (before entering the function).  

\medskip
Let \MATH{A} be of type \BF{bigint\_lattice}. 

\medskip
\fcode{void}{A.buchmann\_kessler}{math\_matrix<bigint> \& T\k double y\k lattice\_info \& li}{}
\fcode{bigint\_lattice}{buchmann\_kessler}{const bigint\_lattice \& A\k math\_matrix<bigint> \& T\k double y\k lattice\_info \& li}{}
\fcode{void}{A.buchmann\_kessler}{math\_matrix<bigint> \& T\k double y}{}
\fcode{bigint\_lattice}{buchmann\_kessler}{const bigint\_lattice \& A\k math\_matrix<bigint> \& T\k double y}
{these functions compute the transformation matrix \MATH{T} as well as 
\latex{\MATH{A =(\underbrace{b_0, \LDOTS , b_{r-1}}_{=B},\underbrace{0, \LDOTS , 0}_{k-r})}} 
\html{
 A = ( b_0, ..., b_r-1, 0, ..., 0 ),
       \_____  ______/  \___  __/
             \/             \/
             =B             k-r          
} where \MATH{B} is an LLL reduced basis of \MATH{L} with rank \MATH{r} by using the
Buchmann-Kessler algorithm \cite{BUK}. 
The last \MATH{k-r} columns of \MATH{T} are relations for the original generating
system.
The \TT{lidia\_error\_handler} will be invoked if the basis or gram flag is set.
}

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

\fcode{void}{A.lll\_schnorr\_euchner\_orig}{double y\k lattice\_info \& li\k user\_SP\k sdigit factor = 1}{}
\fcode{bigint\_lattice}{lll\_schnorr\_euchner\_orig}{const bigint\_lattice \& A\k double y\k lattice\_info \& li\k user\_SP\k sdigit factor = 1}{}
\fcode{void}{A.lll\_schnorr\_euchner\_orig}{double y\k lattice\_info \& li\k sdigit factor = 1}{}
\fcode{bigint\_lattice}{lll\_schnorr\_euchner\_orig}{const bigint\_lattice \& A\k double y\k lattice\_info \& li\k sdigit factor = 1}{}
\fcode{void}{A.lll\_schnorr\_euchner\_orig}{double y\k user\_SP\k sdigit factor = 1}{}
\fcode{bigint\_lattice}{lll\_schnorr\_euchner\_orig}{const bigint\_lattice \& A\k double y\k user\_SP\k sdigit factor = 1}{}
\fcode{void}{A.lll\_schnorr\_euchner\_orig}{double y\k sdigit factor = 1}{}
\fcode{bigint\_lattice}{lll\_schnorr\_euchner\_orig}{const bigint\_lattice \& A\k double y\k sdigit factor = 1}
{
if \MATH{A} is not a Gram matrix, these functions compute 
\latex{\MATH{A =(\underbrace{b_0, \LDOTS , b_{r-1}}_{=B},\underbrace{0, \LDOTS , 0}_{k-r})}} 
\html{
 A = ( b_0, ..., b_r-1, 0, ..., 0 ),
       \_____  ______/  \___  __/
             \/             \/
             =B             k-r          
} 
where \MATH{B} is an LLL reduced basis of \MATH{L} with rank \MATH{r} by
using the original Schnorr-Euchner algorithm \cite{SEN}. For
linearly (in)dependent Gram matrices the computations are done according to
\cite{cohen}. \MATH{y\IN ]\FRAC{1}{2},1]} is the 
reduction parameter. With factor the precision for the
approximations of computations (depending on the algorithm) will be determined as 
(factor \MATH{\CDOT} double precision).  
For factor \MATH{=1} (factor \MATH{=2}) the approximations are done by using doubles
(xdoubles), otherwise \BF{bigfloat}s with appropriate precision will be used.
}

\fcode{void}{A.lll\_schnorr\_euchner\_orig}{math\_matrix<bigint> \& T\k double y\k lattice\_info \& li\k user\_SP\k sdigit factor = 1}{}
\fcode{bigint\_lattice}{lll\_schnorr\_euchner\_orig}{const bigint\_lattice \& A\k math\_matrix<bigint> \& T\k double y\k lattice\_info \& li\k user\_SP\k sdigit factor = 1}{}
\fcode{void}{A.lll\_schnorr\_euchner\_orig}{math\_matrix<bigint> \& T\k double y\k lattice\_info \& li\k sdigit factor = 1}{}
\fcode{bigint\_lattice}{lll\_schnorr\_euchner\_orig}{const bigint\_lattice \& A\k math\_matrix<bigint> \& T\k double y\k lattice\_info \& li\k sdigit factor = 1}{}
\fcode{void}{A.lll\_schnorr\_euchner\_orig}{math\_matrix<bigint> \& T\k double y\k user\_SP\k sdigit factor = 1}{}
\fcode{bigint\_lattice}{lll\_schnorr\_euchner\_orig}{const bigint\_lattice \& A\k math\_matrix<bigint> \& T\k double y\k user\_SP\k sdigit factor = 1}{}
\fcode{void}{A.lll\_schnorr\_euchner\_orig}{math\_matrix<bigint> \& T\k double y\k sdigit factor = 1}{}
\fcode{bigint\_lattice}{lll\_schnorr\_euchner\_orig}{const bigint\_lattice \& A\k math\_matrix<bigint> \& T\k double y\k sdigit factor = 1}
{
if \MATH{A} is not a Gram matrix, these functions computes the transformation matrix
\MATH{T} and  
\latex{\MATH{A =(\underbrace{b_0, \LDOTS , b_{r-1}}_{=B},\underbrace{0, \LDOTS , 0}_{k-r})}} 
\html{
 A = ( b_0, ..., b_r-1, 0, ..., 0 ),
       \_____  ______/  \___  __/
             \/             \/
             =B             k-r          
} 
where \MATH{B} is an LLL reduced basis of \MATH{L} with rank \MATH{r} by using
the orignal Schnorr-Euchner algorithm \cite{SEN}. 
The last \MATH{k-r} columns of \MATH{T} are relations for the original generating
system. For
linearly (in)dependent Gram matrices the computations are done according to
\cite{cohen}. \MATH{y\IN ]\FRAC{1}{2},1]} is the 
reduction parameter. With factor the precision for the
approximations of computations (depending on the algorithm) will be determined as 
(factor \MATH{\CDOT} double precision).  
For factor \MATH{=1} (factor \MATH{=2}) the approximations are done by using doubles
(xdoubles), otherwise \BF{bigfloat}s with appropriate precision will be used.
}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\fcode{void}{A.lll\_schnorr\_euchner\_fact}{double y\k lattice\_info \& li\k user\_SP \k sdigit factor = 1}{}
\fcode{bigint\_lattice}{lll\_schnorr\_euchner\_fact}{const bigint\_lattice \& A\k double y\k lattice\_info \& li\k user\_SP \k sdigit factor = 1}{}
\fcode{void}{A.lll\_schnorr\_euchner\_fact}{double y\k lattice\_info \& li\k sdigit factor = 1}{}
\fcode{bigint\_lattice}{lll\_schnorr\_euchner\_fact}{const bigint\_lattice \& A\k double y\k lattice\_info \& li\k sdigit factor = 1}{}
\fcode{void}{A.lll\_schnorr\_euchner\_fact}{double y\k user\_SP \k sdigit factor = 1}{}
\fcode{bigint\_lattice}{lll\_schnorr\_euchner\_fact}{const bigint\_lattice \& A\k double y\k user\_SP \k sdigit factor = 1}{}
\fcode{void}{A.lll\_schnorr\_euchner\_fact}{double y\k sdigit factor = 1}{}
\fcode{bigint\_lattice}{lll\_schnorr\_euchner\_fact}{const bigint\_lattice \& A\k double y\k sdigit factor = 1}
{
if \MATH{A} is not a Gram matrix, these functions compute 
\latex{\MATH{A =(\underbrace{b_0, \LDOTS , b_{r-1}}_{=B},\underbrace{0, \LDOTS , 0}_{k-r})}} 
\html{
 A = ( b_0, ..., b_r-1, 0, ..., 0 ),
       \_____  ______/  \___  __/
             \/             \/
             =B             k-r          
} 
where \MATH{B} is an LLL reduced basis of \MATH{L} with rank \MATH{r} by
using a variation of the Schnorr-Euchner algorithm \cite{new}. For
linearly (in)dependent Gram matrices the computations are done according to
\cite{cohen}. \MATH{y\IN ]\FRAC{1}{2},1]} is the 
reduction parameter. With factor the precision for the
approximations of computations (depending on the algorithm) will be determined as 
(factor \MATH{\CDOT} double precision).  
For factor \MATH{=1} (factor \MATH{=2}) the approximations are done by using doubles
(xdoubles), otherwise \BF{bigfloat}s with appropriate precision will be used.
This function is not completely tested yet but should be faster since one can
use doubles and xdoubles for doing the approximations even for higher 
dimensions and larger lattice entries.
}
\fcode{void}{A.lll\_schnorr\_euchner\_fact}{math\_matrix<bigint> \& T\k double y\k lattice\_info \& li\k user\_SP\k sdigit factor = 1}{}
\fcode{bigint\_lattice}{lll\_schnorr\_euchner\_fact}{const bigint\_lattice \& A\k math\_matrix<bigint> \& T\k double y\k lattice\_info \& li\k user\_SP\k sdigit factor = 1}{}
\fcode{void}{A.lll\_schnorr\_euchner\_fact}{math\_matrix<bigint> \& T\k double y\k lattice\_info \& li\k sdigit factor = 1}{}
\fcode{bigint\_lattice}{lll\_schnorr\_euchner\_fact}{const bigint\_lattice \& A\k math\_matrix<bigint> \& T\k double y\k lattice\_info \& li\k sdigit factor = 1}{}
\fcode{void}{A.lll\_schnorr\_euchner\_fact}{math\_matrix<bigint> \& T\k double y\k user\_SP\k sdigit factor = 1}{}
\fcode{bigint\_lattice}{lll\_schnorr\_euchner\_fact}{const bigint\_lattice \& A\k math\_matrix<bigint> \& T\k double y\k user\_SP\k sdigit factor = 1}{}
\fcode{void}{A.lll\_schnorr\_euchner\_fact}{math\_matrix<bigint> \& T\k double y\k sdigit factor = 1}{}
\fcode{bigint\_lattice}{lll\_schnorr\_euchner\_fact}{const bigint\_lattice \& A\k math\_matrix<bigint> \& T\k double y\k sdigit factor = 1}
{
if \MATH{A} is not a Gram matrix, these functions compute the transformation matrix 
\MATH{T} and 
\latex{\MATH{A=(\underbrace{b_0, \LDOTS , b_{r-1}}_{=B},\underbrace{0, \LDOTS , 0}_{k-r})}} 
\html{
 A = ( b_0, ..., b_r-1, 0, ..., 0 ),
       \_____  ______/  \___  __/
             \/             \/
             =B             k-r          
} 
where \MATH{B} is an LLL reduced basis of \MATH{L} with rank \MATH{r} by using
a variation of the Schnorr-Euchner algorithm \cite{new}. 
The last \MATH{k-r} columns of \MATH{T} are relations for the original generating
system. For
linearly (in)dependent Gram matrices the computations are done according to
\cite{cohen}. \MATH{y\IN ]\FRAC{1}{2},1]} is the 
reduction parameter. With factor the precision for the
approximations of computations (depending on the algorithm) will be determined as 
(factor \MATH{\CDOT} double precision).  
For factor \MATH{=1} (factor \MATH{=2}) the approximations are done by using doubles
(xdoubles), otherwise \BF{bigfloat}s with appropriate precision will be used.
This function is not completely tested yet
but should be faster since one can
use doubles and xdoubles for doing the approximations even for higher 
dimensions and larger lattice entries.
}

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

\fcode{void}{A.lll\_benne\_de\_weger}{sdigit p\k sdigit q\k lattice\_info \& li}{}
\fcode{bigint\_lattice}{lll\_benne\_de\_weger}{const bigint\_lattice \& A\k sdigit p\k sdigit q\k lattice\_info \& li}{}
\fcode{void}{A.lll\_benne\_de\_weger}{sdigit p\k sdigit q}{}
\fcode{bigint\_lattice}{lll\_benne\_de\_weger}{const bigint\_lattice \& A\k sdigit p\k sdigit q}
{
reduces the lattice \MATH{A} by using the algorithm of Benne de 
Weger \cite{BEW}. The \TT{lidia\_error\_handler} will be invoked
if the generating system or gram flag is set.
}

\fcode{void}{A.lll\_benne\_de\_weger}{math\_matrix<bigint> \& T\k sdigit p\k sdigit q\k lattice\_info \& li}{}
\fcode{bigint\_lattice}{lll\_benne\_de\_weger}{const bigint\_lattice \& A\k math\_matrix<bigint> \& T\k sdigit p\k sdigit q\k lattice\_info \& li}{}
\fcode{void}{A.lll\_benne\_de\_weger}{math\_matrix<bigint> \& T\k sdigit p\k sdigit q}{}
\fcode{bigint\_lattice}{lll\_benne\_de\_weger}{const bigint\_lattice \& A\k math\_matrix<bigint> \& T\k sdigit p\k sdigit q} {
reduces the lattice \MATH{A} and computes the Transformation matrix \MATH{T} by 
using the algorithm of Benne de 
Weger \cite{BEW}. The \TT{lidia\_error\_handler} will be invoked
if the generating system or gram flag is set.
}

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

\fcode{void}{A.mlll}{double y\k bigint*\& v\k lattice\_info \& li}{}
\fcode{bigint\_lattice}{mlll}{const bigint\_lattice \& A\k double y\k bigint*\& v\k lattice\_info \& li}{}
\fcode{void}{A.mlll}{double y\k base\_vector<bigint> \& v\k lattice\_info \& li}{}
\fcode{bigint\_lattice}{mlll}{const bigint\_lattice \& A\k double y\k base\_vector<bigint> \& v\k lattice\_info \& li}{}
\fcode{void}{A.mlll}{double y\k bigint*\& v}{}
\fcode{bigint\_lattice}{mlll}{const bigint\_lattice \& A\k double y\k bigint*\& v}{}
\fcode{void}{A.mlll}{double y\k base\_vector<bigint> \& v}{}
\fcode{bigint\_lattice}{mlll}{const bigint\_lattice \& A\k double y\k base\_vector<bigint> \& v}{
these functions compute a \MATH{k-2}-dimensional reduced basis of \MATH{A=(a_0, \LDOTS, a_{k-1}) 
\IN M^{k-1 \TIMES k}} as well as a vector \MATH{v} satisfying 
\MATH{\SUM{i=0}{k-1}{v_ia_i}=0} by using the modified LLL-algorithm 
\cite{ZAS}. \MATH{y\IN ]\FRAC{1}{2},1]} is the 
reduction parameter. The \TT{lidia\_error\_handler} will be invoked
if the basis or gram flag is set.
}

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

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

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

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

void double_scalar(double &x, double *a, double *b, lidia_size_t len)
{
        lidia_size_t i;

        x = 0;
        for(i=0; i<len; i++)
                x += a[i] * b[i];
}

void xdouble_scalar(xdouble &x, xdouble *a, xdouble *b, lidia_size_t len)
{
        lidia_size_t i;

        x = 0;
        for(i=0; i<len; i++)
                x += a[i] * b[i];
}

void bigfloat_scalar(bigfloat &x, bigfloat *a, bigfloat *b, lidia_size_t len)
{
        lidia_size_t i;

        x = 0;
        for(i=0; i<len; i++)
                x += a[i] * b[i];
}

void bigint_scalar(bigint &x, bigint *a, bigint *b, lidia_size_t len)
{
        lidia_size_t i;

        x = 0;
        for(i=0; i<len; i++)
                x += a[i] * b[i];
}

int main()
{
  bigint_lattice L,B;
  math_matrix <bigint> SV;
  lattice_info li;
  bool gram, basis;
  lidia_size_t sv_len;
  user_SP usp = { double_scalar, xdouble_scalar, 
                  bigint_scalar, bigfloat_scalar};

  cin >> L;

  cout << "Lattice:" << endl;
  cout << L << endl;

  gram = L.check_gram();
  basis = L.check_basis();

  B.assign(L);

  L.lll(0.99, li, usp);

  cout << "The reduced lattice is:" << endl; 
  cout << L << endl;

  if(basis)
    cout << "The lattice was represented by a basis." << endl;
  else
    cout << "The lattice was represented by a generating system.\n" << endl;

  if(gram)
    cout << "The lattice was represented by a gram matrix." << endl;
  if(basis) {
    sv_len = B.shortest_vector(SV,50);
    cout << "\nThe length of the shortest vector is: " << sv_len << endl;
    if(!gram) {
      cout << "The shortest vector(s) is(are):" << endl;
      cout << SV;
    }
      cout << endl;
  }

  cout << "Some statistics:" << endl;
  cout << "Number of reduction steps:\t" << li.lll.reduction_steps << endl;
  cout << "Number of correction steps:\t" << li.lll.correction_steps << endl;
  cout << "Number of swaps:\t\t" << li.lll.swaps << endl;
  cout << "Reduction parameter was:\t" << li.lll.y << endl;

  return 0;
}

**************************************************

Lattice:

( 1212  911   450  288  116 )
( 938   709   278  254  108 )
( 1154  915   281  308  137 )
( 456   376   119  105  47  )
( 1529  1207  432  382  166 )

The reduced lattice is:	           Some statistics:

( -6  -4   4  5   6  )             Number of reduction steps:      56
( -2   4  -6  5  -2  )             Number of correction steps:     34
(  1  -3  -2  7  -2  )             Number of swaps:                42
(  3   2  -1  5   10 )             Reduction parameter was:        0.99
(  2   3   6  1  -4  )

The lattice was represented by a basis.

The length of the shortest vector is: 54
The shortest vector(s) is(are):

(  4   6 )
( -4   2 )
(  3  -1 )
( -2  -3 )
( -3  -2 )

**************************************************

Lattice:

( 13029  10136  5458  3711  3358 )
( 10136  7894   4254  2882  2616 )
( 5458   4254   2300  1543  1418 )
( 3711   2882   1543  1068  945  )
( 3358   2616   1418  945   878  )

The reduced lattice is:            Some statistics:

( 8  2   2   3    0  )             Number of reduction steps:      33
( 2  9   3   3    0  )             Number of correction steps:     20
( 2  3   11  5   -4  )             Number of swaps:                20    
( 3  3   5   12   1  )             Reduction parameter was:        0.99
( 0  0  -4   1    12 )

The lattice was represented by a basis.
The lattice was represented by a gram matrix.

The length of the shortest vector is: 18

**************************************************

Lattice:

( 1196  2316  661   929   882   117 )
( 1208  2460  810   1294  1187  154 )
( 1771  2398  741   1369  1075  126 )
( 1353  2373  845   1441  1389  184 )
( 2122  3507  1124  1937  1637  202 )

The reduced lattice is:            Some statistics:

( 0  0  0  -1   2  0 )             Number of reduction steps:      158
( 1  0  0   0   0  0 )             Number of correction steps:     90
( 0  1  0   0   0  0 )             Number of swaps:                140
( 0  0  1  -1  -1  0 )             Reduction parameter was:        0.99
( 0  0  1   0   2  0 )

The lattice was represented by a generating system.
\end{verbatim}

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

\AUTHOR
Werner Backes, Thorsten Lauer, Oliver van Sprang, Susanne Wetzel\\
(code fragments written by Jutta Bartholomes)

\end{lidia_man}
