/* time to scatter a random matrix for a distributed memory multicomputer,
 * run this program using "mpirun -np x", with x=2,3,..,10. */

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "mpi.h"

#define size 2520  /*  size of the problem, divisible by 2,3,4,..,10 */

void random_matrix ( int n, int m, double *a );
/* generates a random n-by-m matrix */

void print_time ( int p, double time[p] );
/* prints the timing results in the array time of size p */

int main ( int argc, char *argv[] )
{
   int myid,k,p,s;
   double *wall_time,startwtime,endwtime,wtime;
   double *A = (double*)calloc(size*size,sizeof(double));
   double *my_A;

   MPI_Init(&argc,&argv);
   MPI_Comm_size(MPI_COMM_WORLD,&p);
   MPI_Comm_rank(MPI_COMM_WORLD,&myid);

   s = size/p;
   my_A = (double*)calloc(s*size,sizeof(double));

   srand(time(NULL));

   if(myid==0) /* manager allocates and initializes matrix and vector */
   {
      wall_time = (double*) calloc(p,sizeof(double));
      startwtime = MPI_Wtime();
      random_matrix(size,size,A);
   }
   else
      startwtime = MPI_Wtime();

   MPI_Scatter(A,s*size,MPI_DOUBLE,my_A,s*size,MPI_DOUBLE,0,MPI_COMM_WORLD);

   endwtime = MPI_Wtime();
   wtime = endwtime - startwtime;
   MPI_Gather(&wtime,1,MPI_DOUBLE,wall_time,1,MPI_DOUBLE,0,MPI_COMM_WORLD);
   if(myid==0) print_time(p,wall_time);

   MPI_Finalize();
   return 0;
}

void print_time ( int p, double time[p] )
{
   int i;

   printf("\nTotal wall time = %lf seconds on %d processors\n",time[0],p);
   for(i=1; i<p; i++)
      printf("Wall time on processor %d = %lf seconds.\n",i,time[i]);
}

void random_matrix ( int n, int m, double *a )
{
   int i,j;
   double *p;

   p = a;
   for(i=0; i<n; i++)
      for(j=0; j<m; j++)
         *(p++) = ((double) rand())/RAND_MAX;
}
