#include <iostream>
#include <mpi.h> 
#include <vector>
#include "VecFuncs.h"
using namespace std;


int main(int argc, char** argv)
{
    MPI_Init(&argc, &argv);
    MPI_Comm icomm = MPI_COMM_WORLD;
    int myrank;
    MPI_Comm_rank(icomm, &myrank);

    int n = 20;
    vector<double> x(n);
    vector<double> y = x;
    for (int i = 0; i < n; ++i)
    {
        x[i] = myrank*100 + (i % 5)*10 + i;
        y[i] = 1.0/(x[i]);
    }
    if(myrank == 0) // so scalar product is well defined (avoid division by 0)
        y[0] = 0;
    
    //E5
    if (myrank == 0) cout << "E5" << endl;
    DebugVector(x, icomm);

    //E6 
    if (myrank == 0) cout << "E6" << endl;
    double scalar_product = par_scalar(x, y, icomm);

    if (myrank == 0)
    {
        cout << "<x,y> = " << scalar_product << endl << endl;
    }

    // E7
	if (myrank == 0) cout << "E7" << endl;
    double xmin, xmax;
    par_minmax(x, xmin, xmax, icomm);

	if (myrank == 0)
    {
        cout << "Global min: " << xmin << endl;
        cout << "Global max: " << xmax << endl << endl;
    }
    
    // E8
    if (myrank == 0) cout << "E8" << endl;
    vector<double> x_new(n);

    // All to all
    if (myrank == 0) cout << "All to all" << endl;
    MPI_Alltoall(x.data(), 5, MPI_DOUBLE, x_new.data(), 5, MPI_DOUBLE, icomm);
    DebugVector(x_new, icomm);
    
    if (myrank == 0) cout << "All to all (in place)" << endl;
    MPI_Alltoall(MPI_IN_PLACE, 0, MPI_DOUBLE, x.data(), 5, MPI_DOUBLE, icomm);

    DebugVector(x, icomm);


    MPI_Finalize();
    return 0;
}
