/* test-ntl.cc
 * Daniel S. Roche, January 2009
 * http://www.cs.uwaterloo.ca/~droche/
 *
 * Test code for polynomial multiplication in NTL.
 * Two filenames should be given as arguments, for the input and output.
 * The input has five integers on the first line:
 * t: the number of test cases to follow
 * m: greater than the degree of the first polynomial in each pair
 * n: greater than the degree of the second polynomial in each pair
 * p: the modulus to use
 * k, w: Ignored integers
 * The last two paramaters are set to zero if none is given.
 * What follows are 2t lines each containing a polynomial 
 * (alternating sizes m and n),
 * formatted as [a0 a1 a2 ... am] where a0..am are the coefficients.
 * The output consists of t polynomials (the products), in the same format,
 * one per line.
 * Upon completion, the number of seconds used to perform the computation
 * is written to standard out.
 *
 * See LICENSE.txt for copyright and permissions.
 */

#include <iostream>
#include <fstream>
#include <cstdlib>
#include <cassert>
#include <ctime>
#include <NTL/lzz_pX.h>

using NTL::zz_pX;

int main(int argc, char** argv) {
   long t,m,n,i,p,w;
   int k;
   zz_pX *f, *g, *h;
   clock_t start, end;
   std::ifstream in;
   std::ofstream out;

   assert(argc == 3);
   in.open(argv[1]);
   assert (in.is_open());

   in >> t >> m >> n >> p >> k >> w;
   NTL::zz_p::init(p);

   f = new zz_pX[t];
   assert (f);
   g = new zz_pX[t];
   assert (g);
   h = new zz_pX[t];
   assert (h);

   // Read in the test data
   for (i=0; i<t; ++i) {
      in >> f[i] >> g[i];
      h[i].SetMaxLength( NTL::deg(f[i]) + NTL::deg(g[i]) + 1);
   }

   in.close();

   // Perform the multiplications
   start = clock();
   for(i=0; i<t; ++i) {
      NTL::mul(h[i], f[i], g[i]);
   }
   end = clock();

   // Write the results
   out.open(argv[2]);
   assert(out.is_open());
   for (i=0; i<t; ++i) {
      out << h[i] << std::endl;
   }
   out.close();

   std::cout << "========================================================================" << std::endl;
   std::cout << "Time for NTL: " <<
      ((double)(end-start))/CLOCKS_PER_SEC << std::endl;
   std::cout << "========================================================================" << std::endl;

   delete [] f;
   delete [] g;
   delete [] h;

   return 0;
}
