#undef SEEK_SET
#undef SEEK_END
#undef SEEK_CUR
#include <mpi.h>
#include <iostream>
using namespace std;
/************************************************************************************
* copyright © 2013 Soheil Hooshdaran												*
*  The purpose of this program is to multiply the two arrays 'A(n*m)' and  'B(m*p)' *
*  and store the results 															*
*  into the array 'c'																*
************************************************************************************/
int i, j, k;   		 //Loop indices
int A[3], B[3], C;   //Arrays to be created
int n=10, m=30, p=20;//Used as the dimensions of the arrays

void genArrays(int m ,int n, int p)
{     
     int row, col;  //indicces for rows  and columns   
/********generating array A***********/
	 for(row=0;row<n;++row)
          A[row]= 2*row;
     	
/********generating array B***********/
     for(row=0;row<m;++row)
         B[row]= row;   
   }

int main( int argc, char*argv[])
{
/***************Executed on all processors**************/
	
	 int    width=0;   		 //Row size in bytes
	 int  	sent=0;    		 //Holds the number of sent rows
	 int    itag=1;    		 //Holds the data tag for point-to-point massage passings 
	 int 	iRank; 			 //The rank of a processor
	 int    row=0;   			   //used to traverse the rows of the array
	 
	 MPI_Init(&argc, &argv);
	 
	 int	iWorldSize;
	 MPI_Comm_size( MPI_COMM_WORLD, &iWorldSize);
	
	 MPI_Comm_rank( MPI_COMM_WORLD, &iRank);	
/***************Executed on all processors**************/
  if(iRank==0)   //The processor is the master processor	
  {
	  cout << "**************Root processor*************" << endl;
	 //cout << "Please enter the number of rows of the first array:" <<  endl;
	 //cin >> n;
	
	 //cout << "Please enter the number of columns of the first array:" <<  endl;
	 //cin >> m;
	
	 //cout << "Please enter the number of columns of the second array:" <<  endl;
	 //cin >> p;
	 
       
   genArrays(10, 30, 20);
   
   for(row=0;row<m;++row)
	   cout << A[row];     	

     for(row=0;row<m;++row)
       cout << B[row] << endl;     
/**************Boadcast array 'B and other variables'***************/ 
   
   i=1;
  
       
	    while(i<iWorldSize)
	    {
			cout << "executing send for the " << i << "th time" <<  endl;
		   MPI_Send(&A[i], n/iWorldSize * m, MPI_INT, i, itag, MPI_COMM_WORLD);
		   cout << "executed send for the " << i << "th time" <<  endl;
		   
		   i++;
	   }//end while
   }//END IF processor is the root
   else{//rank <> 0, the processor is a slave 
   int sum=0;
   int count;
     cout << "my rank is " << iRank << endl;
	  MPI_Status status;   
	  
         
         cout << "\nAfter receiving broacasted scalar variables,\nm= " << m 
               << "\nn= " << n <<"\np= " << p << endl;
      cout << "*******************" << endl;
	  
	  int *buffer = new int[m*(n/iWorldSize)];
      cout << "\n\n\n**********Executing receive*******" << endl;
      MPI_Recv(&buffer, n/iWorldSize*m, MPI_INT, MPI_ANY_SOURCE, MPI_ANY_TAG
                                           , MPI_COMM_WORLD, &status);
      MPI_Get_count(&status, MPI_INT, &count);
      cout << " received " << count << " elements from processor " 
            << status.MPI_SOURCE << endl;
      if(status.MPI_SOURCE == 0)   
        for(i=0;i<(n/iWorldSize);++i)
          {
			  
             sum += A[i] * B[1];
           C = sum;
           cout << "computed element (" << i << ", " << j << ") of the product array" <<  endl;
          }
          
       }//END ELSE rank<>0
    MPI_Finalize();
      
   return 0;
} 
