/* scat.c  check scatter and gather  */
#include "mpi.h"
#include <stdio.h>

int main(int argc, char *argv[])
{
  int proc, myid, numprocs;
  int count = 1;
  int master = 0;
  double esec = 0.0;
  int bufout[1000]; /* built by master for distribution */
  int bufin[1000];  /* slaves and master receive here */
  int gath[1000];   /* only master receives here from Gather */
  int i;

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

  if(myid == 0)
  {
    printf("scat.c  numprocs=%d \n", numprocs);
    printf("Scatter is blocking and must be executed by all.\n");
    printf("Scatter automatically indexes through bufout.\n");
    printf("all, including master, receive from scatter.\n");
    printf("Gather is blocking and must be executed by all.\n");
    printf("Gather automatically indexes through gath.\n");
    printf("only master receives from Gather.\n");
    printf("no order guaranteed for printf output.\n");
    for(i=0; i<numprocs; i++)
    {
      bufout[i] = 100+i;
      bufin[i] = 0;
      gath[i] = 0;
    }
  }
  /* all */
  MPI_Scatter(bufout, count, MPI_INT,
              bufin,  count, MPI_INT,
              master, MPI_COMM_WORLD);
  esec = MPI_Wtime();
  printf("recvd scat %d for proc=%d at %g sec\n", bufin[0], myid, esec); 
  bufin[0] = bufin[0]+10*myid;
  MPI_Gather(bufin, count, MPI_INT,
             gath,  count, MPI_INT,
             master, MPI_COMM_WORLD);
  esec = MPI_Wtime();
  printf("recvd gath %d %d for proc=%d at %g sec\n",
         gath[0], gath[1], myid, esec); 

  if(myid == 0)
  {
    printf("master gath vector \n");
    for(i=0; i<numprocs; i++)
    {
      printf("gath[%d]=%d \n", i, gath[i]);
    }
  }
  MPI_Finalize();
  return 0; 
}