//
// LiDIA - a library for computational number theory
//   Copyright (c) 1994, 1995 by the LiDIA Group
//
// File        : quadratic_order_appl.c
// Author      : Michael Jacobson, Jr. (MJ)
// Last change : MJ, September 24, 1996, initial version
//

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

main()
{
  quadratic_order QO1,QO2;
  bigint D;
  int vb;

  cout << "Enter verbosity: " << flush;;
  cin >> vb;

  quadratic_order::verbose(vb);

  cout << "Uninitialized quadratic order is zero? " << QO1.is_zero() << "\n" << flush;

  do {
    cout << "Enter a quadratic discriminant: " << flush;
    cin >> D;
  } while (!QO1.assign(D));

  cout << QO1 << "\n" << flush;

  cout << "imaginary? " << QO1.is_imaginary() << "\n" << flush;
  cout << "real? " << QO1.is_real() << "\n" << flush;
  cout << "disriminant = " << QO1.discriminant() << "\n\n" << flush;

  cout << "computing class group...\n" << flush;
  QO1.class_group();
  cout << QO1 << "\n\n" << flush;
  
  cout << "testing LD, ULI, LLI, etc...\n" << flush;
  cout << "L(3) (p < 10000, truncated prod) = " << QO1.estimate_L(3,10000) << "\n" << flush;
  cout << "L(2) (p < 10000, truncated prod) = " << QO1.estimate_L(2,10000) << "\n" << flush;
  cout << "L(1) (p < 10000, truncated prod) = " << QO1.estimate_L(1,10000) << "\n" << flush;
  cout << "L(1) (p < 10000, Bach) = " << QO1.estimate_L1(5000) << "\n" << flush;
  cout << "approx. error = " << QO1.estimate_L1_error(5000) << "\n" << flush;
  cout << "L(1) = " << QO1.Lfunction() << "\n" << flush;
  cout << "LLI = " << QO1.LLI() << "\n" << flush;
  cout << "ULI = " << QO1.ULI() << "\n" << flush;
  cout << "LD(1) = " << QO1.LDfunction() << "\n" << flush;
  cout << "LLI_D = " << QO1.LLI_D() << "\n" << flush;
  cout << "ULI_D = " << QO1.ULI_D() << "\n" << flush;
  cout << "C(D) = " << QO1.Cfunction() << "\n" << flush;

  cout << "testing factor_discriminant...\n" << flush;
  cout << QO1.discriminant() << " = " << QO1.factor_discriminant() << "\n\n" << flush;

  cout << "testing factor_h...\n" << flush;
  cout << QO1.class_number() << " = " << QO1.factor_h() << "\n\n" << flush;

  cout << "CL = " << QO1.class_group() << "\n" << flush;
  cout << "generators = " << QO1.generators() << "\n" << flush;
  cout << "exponent = " << QO1.exponent() << "\n" << flush;
  cout << "2-rank = " << QO1.p_rank(bigint(2)) << "\n" << flush;
  cout << "3-rank = " << QO1.p_rank(bigint(3)) << "\n\n" << flush;

  cout << "QO1:\n" << flush;
  cout << QO1 << "\n\n" << flush;

  quadratic_order QO3(D);
  if (QO3.is_real()) {
    cout << "Testing regulator...\n" << flush;
    cout << "R = " << QO3.regulator() << "\n\n" << flush;
  }
  QO3.assign(D);
  cout << "Testing class_number...\n" << flush;
  cout << "h = " << QO3.class_number() << "\n\n" << flush;

  cout << "testing maximize..." << "\n" << flush;
  cout << "QO1.conductor() = " << QO1.conductor() << "\n" << flush;
  cout << "maximal? " << QO1.is_maximal() << "\n" << flush;
  QO2 = QO1.maximize();
  cout << "maximal order: ";
  cout << QO2 << "\n" << flush;
  cout << "equal? " << QO1.is_equal(QO2) << "\n" << flush;
  cout << "equal (operator)? " << (QO1 == QO2) << "\n" << flush;
  cout << "proper subset? " << (QO1 < QO2) << "   " << (QO1 > QO2) << "\n" << flush;
  cout << "subset? " << (QO1 <= QO2) << "   " << (QO1 >= QO2) << "\n\n" << flush;

  cout << "Copying QO2...\n" << flush;
  QO2 = quadratic_order(-3299);
  cout << "QO2:\n" << flush;
  cout << QO2 << "\n" << flush;
  cout << "equal? " << QO1.is_equal(QO2) << "\n" << flush;
  cout << "equal (operator)? " << (QO1 == QO2) << "\n" << flush;
  cout << "proper subset? " << (QO1 < QO2) << "   " << (QO1 > QO2) << "\n" << flush;
  cout << "subset? " << (QO1 <= QO2) << "   " << (QO1 >= QO2) << "\n\n" << flush;
}
