// tsncom33.cc
// Nick Macks (macks@fnal.gov), Summer 2002

// LinearAlgebra: ColumnVector*RowVector multiplication

#include "LinearAlgebra/ColumnVector.h"
#include "LinearAlgebra/Matrix.h"

using namespace std;

// Function declarations
void Identification();
void GetDimension(int&);
void Describe(const int&);
void BuildCVector(ColumnVector&, const int&);
void BuildRVector(RowVector&, const int&);
void Show(const ColumnVector&, const RowVector&);
void GetCalcs(int&);
void GetRuns(int&);
void Calculate(ColumnVector&, RowVector&, const int&, const int&, const int&);


// Package ID
void Identification()
{
  cout << "Using LinearAlgebra\n";
} 

// Ask for the desired dimension
void GetDimension(int& dimension)
{
  cout << "Enter the desired dimension(1-6): ";
  cin >> dimension;

  while ( (dimension < 1) || (dimension > 6) )
  {
    cout << "Enter an integer between 1 and 6: ";
    cin >> dimension;
  }
}

// Describe how the vectors were defined
void Describe(const int& dimension)
{
  cout << "Vectors were defined 'ColumnVector (" << dimension << ")' and\n";
  cout << "'RowVector (" << dimension << ")'\n";
}

// Build the ColumnVector
void BuildCVector(ColumnVector& vector, const int& dimension)
{
  for (int i=0; i<dimension; ++i)
  {
    vector(i) = 2 + 2*i;
  }
}

// Build the RowVector
void BuildRVector(RowVector& vector, const int& dimension)
{
   for (int i=0; i<dimension; ++i)
   {
     vector(i) = 2 +2*i;
   }
}

// Show the vectors
void Show(const ColumnVector& cvector, const RowVector& rvector)
{
  cout << "Using ColumnVector=\n" << cvector << "\n";
  cout << "Using RowVector=\n" << rvector << "\n";
}

// Get the number of multiplications
void GetCalcs(int& N)
{
  cout << "How many multiplications? ";
  cin >> N;
}

// Get the number of runs
void GetRuns(int& run)
{
  cout << "How many runs? ";
  cin >> run;
  cout << "\n";
}

// Multiply the two vectors
void Calculate(ColumnVector& cvector, RowVector& rvector,
               const int& dimension, const int& N, const int& run)
{
  // Define a counter
  int counter = 0;

  // Define a matrix to hold the result
  Matrix product (dimension, dimension);

  // Loop "run" times
  for (int r=0; r<run; ++r)
  {
    // Do the multiplications
    for (int i=0; i<N; ++i)
    {
      product += cvector * rvector;
      ++counter;
    }

    // Write the output
    cout << counter << " multiplications took place\n";
    cout << "Product =\n" << product << "\n";

    // Reset the counter
    counter = 0;
  }
}


int main()
{
  // What package are we using?
  Identification();

  // Get the dim(-ension)
  int dim = 0; GetDimension(dim);

  // Define a "dim-element" ColumnVector
  ColumnVector cv (dim);

  // Define a "dim-element" RowVector
  RowVector rv (dim);

  // Describe how the vectors were defined
  Describe (dim);

  // Build the "dim-element" ColumnVector
  BuildCVector(cv, dim);

  // Build the "dim-element" RowVector
  BuildRVector(rv, dim);

  // Show the actual vectors
  Show(cv, rv);

  // Multiplication parameters
  int mul = 0; GetCalcs(mul); // number of multiplications
  int run = 0; GetRuns(run);  // number of runs

  // Multiply the vectors
  Calculate(cv, rv, dim, mul, run);

  return 0;
}
