// L-11 MCS 572 Fri 3 Feb 2012 : powers_serial.cpp
// Simple C++ program to raise every element of an array
// of n complex doubles to the power d.
// For timing purposes n, d, and the verbose level
// can be provided at the command line.

#include <cstdlib>
#include <cmath>
#include <complex>
#include <ctime>
#include <iostream>
#include <iomanip>

using namespace std;

typedef complex<double> dcmplx;

dcmplx random_dcmplx ( void );
// generates a random complex number
// on the complex unit circle

void write_numbers ( int n, dcmplx *x );
// writes the array of n doubles in x

void compute_powers ( int n, dcmplx *x,
                      dcmplx *y, int d );
// for arrays x and y of length n,
// on return y[i] equals x[i]**d

int main ( int argc, char *argv[] )
{
   int v = 1;    // verbose if > 0
   if(argc > 3) v = atoi(argv[3]);
   int dim;      // get the dimension
   if(argc > 1)
      dim = atoi(argv[1]);
   else
   {
      cout << "how many numbers ? ";
      cin >> dim;
   }
   // fix the seed for comparisons
   srand(20120203); //srand(time(0));
   dcmplx r[dim];
   for(int i=0; i<dim; i++)
      r[i] = random_dcmplx();
   if(v > 0) write_numbers(dim,r);

   int deg;      // get the degree
   if(argc > 1)
      deg = atoi(argv[2]);
   else
   {
      cout << "give the power : ";
      cin >> deg;
   }
   dcmplx s[dim];
   compute_powers(dim,r,s,deg);
   if(v > 0) write_numbers(dim,s);
   return 0;
}

dcmplx random_dcmplx ( void )
{
   int r = rand();
   double d = ((double) r)/RAND_MAX;
   double e = 2*M_PI*d;
   dcmplx c(cos(e),sin(e));
   return c;
}

void write_numbers ( int n, dcmplx *x )
{
   for(int i=0; i<n; i++)
      cout << scientific << setprecision(4)
           << "x[" << i << "] = ( " << x[i].real()
           << " , " << x[i].imag() << ")\n";
}

void compute_powers ( int n, dcmplx *x,
                      dcmplx *y, int d )
{
   for(int i=0; i < n; i++) // y[i] = pow(x[i],d);
   {                        // pow is too efficient
      dcmplx r(1.0,0.0);
      for(int j=0; j < d; j++) r = r*x[i];
      y[i] = r;
   }
}

