/* L-15 MCS 572 Monday 13 February 2006 : pipeline for one sum.
 * This program sums the first p+1 numbers, using a pipeline.
 * Compile this program as "mpicc -o pipe_one_sum pipe_one_sum.c",
 * and then run on p processors by "mpirun -np p pipe_one_sum". */

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

#define tag 100  /* tag for sending a number */

int main ( int argc, char *argv[] )
{
   int i,p,*n,j;
   MPI_Status status;

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

   if(i==0) /* manager generates p+1 numbers and starts the pipeline */
   {
      n = (int*)calloc(p+1,sizeof(int));
      for(j=0; j<p+1; j++) n[j] = j+1;
      n[1] += n[0];      /* replace n[1] by n[0]+n[1] */
      printf("Manager sends %d numbers to the pipe...\n",p);
      fflush(stdout);
      MPI_Send(&n[1],p,MPI_INT,1,tag,MPI_COMM_WORLD);
      MPI_Recv(&n[0],1,MPI_INT,p-1,tag,MPI_COMM_WORLD,&status);
      printf("Manager received sum %d.\n",n[0]);
   }
   else     /* worker i receives p-i+1 numbers */
   {
      n = (int*)calloc(p-i+1,sizeof(int));
      MPI_Recv(&n[0],p-i+1,MPI_INT,i-1,tag,MPI_COMM_WORLD,&status);
      printf("Processor %d receives %d numbers from node %d.\n",i,p-i+1,i-1);
      fflush(stdout);
      n[1] += n[0];     /* replace n[1] by n[0]+n[1] */
      if(i < p-1)
         MPI_Send(&n[1],p-i,MPI_INT,i+1,tag,MPI_COMM_WORLD);
      else
         MPI_Send(&n[1],1,MPI_INT,0,tag,MPI_COMM_WORLD);
   }

   MPI_Finalize();
   return 0;
}
