#include <LiDIA/bigint_lattice.h>
#include <LiDIA/timer.h>

main()
{
  bigint_lattice A, B, C, G, Old, T;
  bigint values;
  lidia_size_t dim;
  lattice_info li;
  double y;
  timer t;
  srandom(time(0));
  cout << "Intervall for entries : ";
  cin >> values;
  cout << "Intervall for dimension : ";
  cin >> dim;
  cout << "y (0.5 < y <= 1) : ";
  cin >> y;
  cout <<"generating lattice A ..." << endl;
  A.resize(dim+(random()%dim), dim+(random()%dim));
  A.randomize(values);
  cout << "A: " << A << endl;
  if (random()%2)
    {
      A.set_red_orientation_columns();
      cout << "Reducing over columns ..." << endl;
    }
  else
    {
      A.set_red_orientation_rows();
      cout << "Reducing over rows ..." << endl;
    }
  cout << "Dimension of A : " << A.get_no_of_rows() << " x " 
       << A.get_no_of_columns() << endl;
  cout << "Checking A for basis : ";
  if (A.check_basis())
    cout << "ok" << endl;
  else
    cout << "failed" << endl;

  cout << "Checking A for gram : ";
  if (A.check_gram())
    cout << "ok" << endl;
  else
    cout << "failed" << endl;
  if (A.get_red_orientation())
    {
      cout << "Generating Gram matrix (A^T*A) ..." << endl;
      G.assign(A.trans()*A);
    }
  else
    {
      cout << "Generating Gram matrix (A*A^T) ..." << endl;
      G.assign(A*A.trans());
    }

  G.set_gram_flag();
  cout << "Checking G for basis : ";
  if (G.check_basis())
    cout << "ok" << endl;
  else
    cout << "failed" << endl;
  Old.assign(A);

  A.lll(T, y, li);
  G.lll(y, li);
  if (A.get_red_orientation())
    C.assign(Old*T);
  else
    C.assign(T*Old);
  if (A == C)
    cout << "1. test ok" << endl;
  else
    cout << "1. test failed" << endl;

  if (A.get_red_orientation())
    C.assign(A.trans()*A);
  else
    C.assign(A*A.trans());
  if (G == C)
    cout << "2. test ok" << endl;
  else
    cout << "2. test failed" << endl;
  if (G.check_gram())
    cout << "3. test ok" << endl;
  else
    cout << "3. test failed" << endl;;
  cout << "(chosen) : " << y << endl;
  if (A.get_red_orientation())
    A.set_no_of_columns(li.lll.rank);
  else
    A.set_no_of_rows(li.lll.rank);
  cout << "(lll_check_search) : " << A.lll_check_search() << endl;
  cout << "(lll_check) : " 
       << ((A.lll_check(y) == true) ? "OK" : "failed") << endl;
  cout << endl;
  return 0;

}
