#if defined(HAVE_MAC_DIRS) || defined(__MWERKS__)

#include <LiDIA:Fp_polynomial.h>
#include <LiDIA:Fp_polynomial_util.h>
#include <LiDIA:poly_modulus.h>
#include <LiDIA:poly_multiplier.h>

#else

#include <LiDIA/Fp_polynomial.h>
#include <LiDIA/Fp_polynomial_util.h>
#include <LiDIA/poly_modulus.h>
#include <LiDIA/poly_multiplier.h>

#endif


void randomize_bitlength(bigint& x, lidia_size_t num_bits)
{
// x = "random number" with precisely num_bits bits.
    x.assign_zero();

    bigint tmp;
    tmp.assign_one();
    shift_left(tmp, tmp, num_bits);	//tmp = 2^num_bits;

    do
    {
	x = randomize(tmp);
    }
    while ( x.bit_length() != num_bits );

    return;
}



main()
{
   int n, k;

   n = 200;
   k = 200;

   bigint p, t1, t2;

   // p is computed as a random k-bit number.
   // It is not prime, but who cares.

   randomize_bitlength(t1, k);
   t2.assign_one();
   shift_left(t2, t2, k);
   add(p, t1, t2);

   cout<<"multiplication of two polynomials modulo another polynomial over Z/pZ\n";
   cout<<"  degree of the polynomials = "<<n<<endl;
   cout<<"  modulus p = "<<p<<" (about "<<k<<" bits)"<<endl;


   Fp_polynomial f, g, h, r1, r2, r3, r4;

   randomize(g, p, n-1);    // g = random polynomial of degree < n
   randomize(h, p, n-1);    // h =             "   "
   randomize(f, p, n-1);    // f =             "   "
   f.set_coefficient(n);  // Sets coefficient of X^n to 1


   // For doing arithmetic mod f quickly, one must pre-compute
   // some information.

   poly_modulus F(f);

   cout<<"\nclassical algorithm :"<<flush;
   plain_mul(r1, g, h);  // this uses classical arithmetic
   plain_rem(r1, r1, f);

   cout<<"\nFFT algorithm :"<<flush;
   multiply_mod(r3, g, h, f);  // uses FFT

   cout<<"\nmultiplication with poly_modulus :"<<flush;
   multiply(r2, g, h, F);  // this uses poly_modulus

   cout<<"\nmultiplication with poly_modulus, poly_multiplier :"<<flush;
   poly_multiplier H(h,F);
   multiply(r4, g, H, F);	//this uses poly_modulus and poly_multiplier

   cout<<endl;

   // compare the results...

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

}
