//
// LiDIA - a library for computational number theory
//   Copyright (c) 1994, 1995 by the LiDIA Group
//
// File        : lattice_modules.h
// Author      : Werner Backes (WB), Thorsten Lauer (TL)
// Last change : WB/TL, May 09 1996, initial version, previously
//                      class bigint_lattice_gensys/basis
//               WB/TL, Jul 27 1996, 
//                      redesign of class structure introducing 
//                      lattice_modules, initial version
//               WB/TL, Aug 06 1996, 
//                      added template parameter to use more
//                      variations of the modules
//                      - class modules<E,A,Variation>
//                        -> implementation that are equal for
//                           both basis and gensys
//                      - class basis_modules<E,A,Variation>
//                        -> derived from modules implementing
//                           the basis parts
//                      - class gensys_modules<E,A,Variation>
//                        -> derived from modules implementing
//                           the gensys parts
//
//
//

#ifndef __lattice_modules_h__
#define __lattice_modules_h__

//
// Special include format for compatibility with MAC's
//
#if defined(HAVE_MAC_DIRS) || defined(__MWERKS__)
#include <LiDIA:lattice_defs.h>
#include <LiDIA:p_vector.h>
#else
#include <LiDIA/lattice_defs.h>
#include <LiDIA/p_vector.h>
#endif

const int Normal=0;
const int VariationI=1;
const int VariationII=2;

const sdigit Magic_Precision_Factor = 2;

//
// class prec_modules<E, A>
// ~~~~~~~~~~~~~~~~~~~~~~~~
//
// a class  which cares about needed precision
// for both the template type E and the approximate type A
//
template <class E, class A>
class prec_modules
{
  protected : 
    cl(i);
    cl(j);
    sdigit tempsdt;
  public :
    prec_modules() { };
    ~prec_modules() { };

    void prec_startup(dense_alg<E>&);
    void prec_update(dense_alg<E>&);
    void prec_exact(const dense_alg<E>&);
    void prec_approx(const dense_alg<E>&);
    void prec_correct(const dense_alg<E>&);
    void prec_restore(const dense_alg<E>&);
};

//
// class base_modules<E, A, int>
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// a class  which implements parts of the lll -
// algorithm for both basis and gensys
//
template <class E, class A, const int V>
class base_modules:public prec_modules<E,A>
{
  protected :
    sdigit   bi_bit_len;
    sdigit   bit_diff;
    bigint   mant;
    sdigit   expo;
    bigint   tempbin;    // working on mantissa
    bigfloat tempbfl;    
   
  public :
    base_modules():prec_modules<E,A>() { };
    ~base_modules() { };

    bool A_convert_value_E_bound(dense_alg<E>&, E&, const A&, const A&); 
    void E_convert_value_A(dense_alg<E>&, A&, const E&); 
};

//
// class basis_modules<E, A, int>
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// a class  which implements specialized modules of the lll -
// algorithm for basis lattices
//
template <class E, class A, const int V>
class basis_modules:public base_modules<E, A, V>
{
  protected :
    bool is_zero;
    void *tempP;     // swapping rows

  public :
    basis_modules():base_modules<E,A,V>() { };
    ~basis_modules() { };

    bool E_convert_vector_A(dense_alg<E>&, A**, const lidia_size_t);
    void E_convert_lattice_A(dense_alg<E>&, A**);
};
//
// class gensys_modules<E, A, int>
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// a class  which implements specialized modules of the lll -
// algorithm for gensys lattices
//
template <class E, class A, const int V>
class gensys_modules:public base_modules<E, A, V>
{
  protected :
    bool is_zero;
    void *tempP;     // swapping rows

  public :
    gensys_modules():base_modules<E,A,V>() { };
    ~gensys_modules() { };

    bool E_convert_vector_A(dense_alg<E>&, A**, const lidia_size_t);
    void E_convert_lattice_A(dense_alg<E>&, A**);
};

#ifndef NO_LATTICE_INLINE
#include <LiDIA/lattice_modules.c>
#endif

#endif
