//		MPI code in C++.
//		See [Gropp/Lusk/Skjellum, "Using MPI", p.33/41 etc.]
//		and  /opt/mpich/include/mpi2c++/comm.h  for details

#include "vec_func.h"
#include <iostream>                               // MPI
#include <mpi.h>
using namespace std;

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

	int myrank;
    MPI_Comm_rank(icomm, &myrank);

	// E5
	vector<double> x(10,3);
	if(myrank==0) {cout << endl << "E5" << endl;}
	vecdebug(x, icomm);
	
	// E6
	vector<double> y(10,1.0/3);
	double res = par_scalar(x,y,icomm);
	if(myrank==0)
	{
		cout << endl << endl << "E6" << endl;
		cout << "<x,y> = " << res << endl << endl;
	}
	
	// E7
	vector<double> a{myrank*10, myrank*10-1, myrank*10-2};
	if(myrank==0) {cout << "E7\n" << "original vector" << endl;}
	vecdebug(a, icomm);
	double min_val, max_val;
	min_max_exch(a, min_val, max_val, icomm);
	if(myrank==0) {cout << "min = " << min_val << "\tmax = " << max_val << endl << endl << "vector after changing min-max" << endl;}
	vecdebug(a, icomm);
	
	// E8
	int n = 20;
	vector<double> c(n);
	for(size_t i=0; i<n; ++i)
	{
		c[i] = myrank*100 +(i%5)*10+i;
	}
	vector<double> recv(n);
    MPI_Alltoall(c.data(), 5, MPI_DOUBLE, recv.data(), 5, MPI_DOUBLE, icomm);
    if(myrank==0) {cout << endl << "Ex 8\n" << "Alltoall" << endl;}
    vecdebug(recv, icomm);
    
    MPI_Alltoall(MPI_IN_PLACE, 0, MPI_DATATYPE_NULL, c.data(), 5, MPI_DOUBLE, icomm);
    if(myrank==0) {cout << endl << "Ex 8\n" << "Alltoall - IN_PLACE" << endl;}
    vecdebug(c, icomm);
	
	

    MPI_Finalize();

    return 0;
}


