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

#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif

main(lidia_size_t argc, char **argv)
{
    cout << "This program computes the factorization of a polynomial over\n";
    cout << "a finite prime field using different algorithms.\n";
    cout << "Options :\n";
    cout << " -v   print additional information (such as timinigs)\n";

    lidia_size_t verbose = 0;

    argc--;
    argv++;
    single_factor < Fp_polynomial >::set_verbose_mode(0);

    while (argc > 0)
    {
	if (strcmp(argv[0], "-v") == 0)
	{
	    verbose = 1;
	    single_factor < Fp_polynomial >::set_verbose_mode(1);
	}
	else
	{
	    cout << "unknown option: " << argv[0] << "\n";
	    return 1;
	}
	argc--;
	argv++;
    }

    cout << "Please enter a monic polynomial (example: x^54 - 3*x^2 + 1 mod 5) :\n";
    Fp_polynomial f;
    cin >> f;
    const bigint & p = f.modulus();

    if (verbose)
    {
	cout << "degree of polynomial = " << f.degree()
	     << ", bitlength of modulus = " << p.bit_length()
	     << "\n\n";
    }

    factorization < Fp_polynomial > Berl, Canz, Fact;

    my_timer t;
    t.start("Berlekamp: ");
    berlekamp(Berl, f);
    t.stop();

    t.start("Cantor/Zassenhaus (Shoup/v.z.Gathen)");
    can_zass(Canz, f);
    t.stop();

    t.start("factor");
    factor(Fact, f);
    t.stop();

    Fp_polynomial ff;
    if (f.degree() > 0)
	ff = Berl.value();
    else
	ff = f;
    
    if (f != ff || Berl != Canz || Berl != Fact)
    {
	cout << "Incorrect factorization!!\n";
	cout << "Polynomial was: \n";
	cout << f << endl;
	cout << "Please report this bug.\n";
    }
    else
    {
	cout << "\nfactorization :\n";
	cout << Berl << "\n";
    }
}
