//
// LiDIA - a library for computational number theory
//   Copyright (c) 1995 by the LiDIA Group
//
// File        : lattice_basis.h 
// Author      : Werner Backes (WB), Thorsten Lauer (TL) 
// Last change : WB/TL, Feb 10 1995, initial version
//             : WB/TL, Dez 21 1995, second template version
//             : WB/TL, Jan 08 1996, stabilized template version
//             : WB/TL, Feb 29 1996, some information/function extensions
//
//

#ifndef _lattice_basis_h
#define _lattice_basis_h

#ifndef HEADBANGER

#if defined(HAVE_MAC_DIRS) || defined(__MWERKS__)
#include <LiDIA:lattice_gensys.h>
#else
#include <LiDIA/lattice_gensys.h>
#endif

class lattice_basis: public lattice_gensys
{
  public :

//
// Constructors / Destructor
//

    lattice_basis(lidia_size_t n, lidia_size_t m):lattice_gensys(n, m) { };
    lattice_basis(lidia_size_t n, lidia_size_t m, const double** ado):lattice_gensys(n, m, ado) { };
    lattice_basis(lidia_size_t n, lidia_size_t m, const bigint** abi):lattice_gensys(n, m, abi) { };
    lattice_basis(lidia_size_t n, lidia_size_t m, const bigfloat** abf):lattice_gensys(n, m, abf) { };
    lattice_basis(const lattice_basis& L):lattice_gensys(L) { };
    lattice_basis(const math_matrix< bigint >& M):lattice_gensys(M) { };
    lattice_basis(const math_matrix< bigfloat >& M):lattice_gensys(M) { };
    virtual ~lattice_basis() { };

//
// Conversion
//

    void extract_basis(const lattice_gensys&, lidia_size_t&);
    bool make_basis(const lattice_gensys&, lidia_size_t&);

//
// Algorithms
//
    void lll();
    void lll(const lattice_basis&);
    inline friend lattice_basis lll(const lattice_basis& L)
    {
      lattice_basis TL(L);
      TL.lll();
      return (TL);
    }
    
    void lll_trans(lattice_basis&);
    inline friend lattice_basis lll_trans(const lattice_basis& L,
                                          lattice_basis& T)
    {
      lattice_basis LT(L);
      LT.lll_trans(T);
      return (LT);
    }

    void gram_schmidt_orth(lattice_basis&, lattice_basis&);

    bool lll_check(double);
    bool lll_check(sdigit, sdigit); 
    
    double lll_check_search();
    void lll_check_search(sdigit&, sdigit&);

    friend void lll(math_matrix< bigint >&, const math_matrix< bigint >&);
    friend void lll_trans(math_matrix< bigint >&, math_matrix< bigint >&);

    friend void lll(math_matrix< bigfloat >&, const math_matrix< bigfloat >&);
    friend void lll_trans(math_matrix< bigint >&, math_matrix< bigfloat >&);
    friend void lll_trans(math_matrix< bigfloat >&, math_matrix< bigfloat >&);
};

#endif  // HEADBANGER

#endif

