//
// LiDIA - a library for computational number theory
//   Copyright (c) 1994, 1995 by the LiDIA Group
//
// File        : gf_pol_appl.c
// Author      : Thomas Pfahler (TPf)
// Last change : TPf, Sep 29, 1996, initial version
//

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

main()
{
    cout<<"Simple demonstration of the class polynomial< gf_p_element >\n";
    cout<<"(an implementation of polynomials over finite fields)\n\n";
    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 polynomials: ";
	cin>>d;
    }

    bigint p = A.characteristic();
    cout<<"multiplication of two polynomials modulo another polynomial\n";
    cout<<"finite field:\n";
    cout<<"  - characteristic "<<p<<" ("<<p.bit_length()<<" bits)\n";
    cout<<"  - degree "<<A.degree()<<" over prime field\n";
    cout<<"degree of the polynomials = "<<d<<"\n\n";

    cout<<"generating random polynomials..."<<flush;
    polynomial< gf_p_element > f, g, h, r1, r2, r3;
    gf_p_element one;
    one.assign_one(B);
    f = randomize(B, d);
    f[d] = one;
    gf_poly_modulus F(f);
    g = randomize(B, d-1);
    h = randomize(B, d-1);
    cout<<" done.\n";
    
    cout<<"classical algorithm..."<<flush;
    plain_multiply(r1, g, h);
    plain_remainder(r1, r1, f);
    cout<<" done.\n";

    cout<<"Kronecker substitution algorithm..."<<flush;
    multiply(r2, g, h);
    remainder(r2, r2, f);
    cout<<" done.\n";

    cout<<"multiplication with gf_poly_modulus..."<<flush;
    multiply(r3, g, h, F);
    cout<<" done.\n";

   // compare the results...
   
   if (r1 != r2)
	cout << "r1 != r2!!\n";
   else if (r1 != r3)
	cout << "r1 != r3!!\n";
   else
	cout << "results are OK.\n";

}
