#if defined(HAVE_MAC_DIRS) || defined(__MWERKS__)
#include <LiDIA:gf_polynomial.h>
#include <LiDIA:factorization.h>
#include <LiDIA:Fp_polynomial_util.h>
#else
#include <LiDIA/gf_polynomial.h>
#include <LiDIA/factorization.h>
#include <LiDIA/Fp_polynomial_util.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 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 < gf_polynomial >::set_verbose_mode(0);

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

    cout<<"Please enter the finite field in form of \"(p,n)\", where p is the\n";
    cout<<"characteristic and n the degree of the finite field : ";
    galois_field A;
    cin >> A;

    cout<<"Generating a gf_p_base for this field... "<<flush;
    gf_p_base B(A);
    cout<<" done.\n";

    lidia_size_t d = 0;
    
    while(d < 1)
    {
        cout<<"Please enter the degree of the polynomial: ";
        cin>>d;
    }
    cout<<"generating a random monic polynomial..."<<flush;
    gf_polynomial f;
    f = randomize(B, d);
//    f[d].assign_one(B);
    cout<<" done.\n";
    cout<<"f = "<<f<<endl<<endl;

    factorization < gf_polynomial > Berl, Canz, Fact;

    my_timer t;
    cout<<"Berlekamp algorithm:"<<endl;
    t.start("  Total Berlekamp :");
    berlekamp(Berl, f);
    t.stop();

    cout<<"Cantor/Zassenhaus algorithm:"<<endl;
    t.start("  Total Cantor/Zassenhaus :");
    can_zass(Canz, f);
    t.stop();

    cout<<"Factor algorithm:"<<endl;
    t.start("  Total Factor :");
    factor(Fact, f);
    t.stop();

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