#include <sys/time.h>
#include "libscl.h"
using namespace scl;
using namespace std;

int main(int argc, char** argp, char** envp)
{
  INT_32BIT seed = 12345;

  timeval time_start, time_stop;
  REAL time_elapsed;
  int rv;

  typedef vector<REAL>::size_type rv_int;

  const INTEGER n = 10000000;

  REAL sum;

  cout << starbox("/Memory allocation//")<<'\n';
  cout << "n = " << n << '\n';
  cout.flush();

  rv = gettimeofday(&time_start,NULL);
  if (rv != 0) error("Error, gettimeofday failed");

  realmat arm(n,1);
  realmat brm(n,1);
  vector<REAL> arv(n);
  vector<REAL> brv(n);
  REAL* a;
  REAL* b;
  try {
    a = new REAL[n];
    b = new REAL[n];
  }
  catch(const bad_alloc&) {
    cerr << "Error allocation memory" << '\n';
    return 1;
  }
  catch (...) {
    cerr << "Unknown exception caught" << '\n';
    return 1;
  }

  rv = gettimeofday(&time_stop,NULL);
  if (rv != 0) error("Error, gettimeofday failed");
  time_elapsed = time_stop.tv_sec - time_start.tv_sec;
  time_elapsed += (time_stop.tv_usec - time_start.tv_usec)/1.0e+6;
  cout<<"time = " << time_elapsed << '\n';
  cout.flush();

  cout << starbox("/Initialization//")<<'\n';
  cout.flush();

  rv = gettimeofday(&time_start,NULL);
  if (rv != 0) error("Error, gettimeofday failed");

  for (INTEGER i=1; i<=n; ++i) {
    arm[i] = unsk(seed);
    brm[i] = unsk(seed);
    rv_int j = i-1;
    arv[j] = arm[i];
    brv[j] = brm[i];
    int k = i-1;
    a[k] = arm[i];
    b[k] = brm[i];
  }

  rv = gettimeofday(&time_stop,NULL);
  if (rv != 0) error("Error, gettimeofday failed");
  time_elapsed = time_stop.tv_sec - time_start.tv_sec;
  time_elapsed += (time_stop.tv_usec - time_start.tv_usec)/1.0e+6;
  cout<<"time = " << time_elapsed << '\n';
  cout.flush();

  cout << starbox("/Inner products//")<<'\n';
  cout.flush();

  rv = gettimeofday(&time_start,NULL);
  if (rv != 0) error("Error, gettimeofday failed");

  sum = (T(arm)*brm)[1];

  rv = gettimeofday(&time_stop,NULL);
  if (rv != 0) error("Error, gettimeofday failed");
  time_elapsed = time_stop.tv_sec - time_start.tv_sec;
  time_elapsed += (time_stop.tv_usec - time_start.tv_usec)/1.0e+6;
  cout<<"1 of 6, sum = " << sum << ", time = " << time_elapsed << '\n';
  cout.flush();

  rv = gettimeofday(&time_start,NULL);
  if (rv != 0) error("Error, gettimeofday failed");

  sum = 0.0;
  for (INTEGER i=1; i<=n; ++i) {
    sum += arm[i]*brm[i];
  }

  rv = gettimeofday(&time_stop,NULL);
  if (rv != 0) error("Error, gettimeofday failed");
  time_elapsed = time_stop.tv_sec - time_start.tv_sec;
  time_elapsed += (time_stop.tv_usec - time_start.tv_usec)/1.0e+6;
  cout<<"2 of 6, sum = " << sum << ", time = " << time_elapsed << '\n';
  cout.flush();

  rv = gettimeofday(&time_start,NULL);
  if (rv != 0) error("Error, gettimeofday failed");

  sum = 0.0;
  for (INTEGER i=0; i<n; ++i) {
    sum += arv[i]*brv[i];
  }

  rv = gettimeofday(&time_stop,NULL);
  if (rv != 0) error("Error, gettimeofday failed");
  time_elapsed = time_stop.tv_sec - time_start.tv_sec;
  time_elapsed += (time_stop.tv_usec - time_start.tv_usec)/1.0e+6;
  cout<<"3 of 6, sum = " << sum << ", time = " << time_elapsed << '\n';
  cout.flush();

  rv = gettimeofday(&time_start,NULL);
  if (rv != 0) error("Error, gettimeofday failed");

  sum = 0.0;
  for (INTEGER i=0; i<n; ++i) {
    sum += a[i]*b[i];
  }

  rv = gettimeofday(&time_stop,NULL);
  if (rv != 0) error("Error, gettimeofday failed");
  time_elapsed = time_stop.tv_sec - time_start.tv_sec;
  time_elapsed += (time_stop.tv_usec - time_start.tv_usec)/1.0e+6;
  cout<<"4 of 6, sum = " << sum << ", time = " << time_elapsed << '\n';
  cout.flush();

  rv = gettimeofday(&time_start,NULL);
  if (rv != 0) error("Error, gettimeofday failed");

  REAL* a_iter = a;
  REAL* b_iter = b;
  REAL* a_end = a + n;
  sum = 0.0;
  while(a_iter<a_end) {
   sum += (*a_iter++)*(*b_iter++);
  }

  rv = gettimeofday(&time_stop,NULL);
  if (rv != 0) error("Error, gettimeofday failed");
  time_elapsed = time_stop.tv_sec - time_start.tv_sec;
  time_elapsed += (time_stop.tv_usec - time_start.tv_usec)/1.0e+6;
  cout<<"5 of 6, sum = " << sum << ", time = " << time_elapsed << '\n';
  cout.flush();

  vector<REAL>::const_iterator arv_iter = arv.begin();
  vector<REAL>::const_iterator brv_iter = brv.begin();
  vector<REAL>::const_iterator arv_end = arv.end();  

  rv = gettimeofday(&time_start,NULL);
  if (rv != 0) error("Error, gettimeofday failed");

  sum = 0.0;
  while(arv_iter<arv_end) {
   sum += (*arv_iter++)*(*brv_iter++);
  }

  rv = gettimeofday(&time_stop,NULL);
  if (rv != 0) error("Error, gettimeofday failed");
  time_elapsed = time_stop.tv_sec - time_start.tv_sec;
  time_elapsed += (time_stop.tv_usec - time_start.tv_usec)/1.0e+6;
  cout<<"6 of 6, sum = " << sum << ", time = " << time_elapsed << '\n';
  cout.flush();

  return 0;
}
