/*
 * Open Systems Laboratory
 * http://www.lam-mpi.org/tutorials/
 * Indiana University
 *
 * MPI Tutorial
 * Lab 2: The cannonical ring program
 *
 * Mail questions regarding tutorial material to lam at lam dash mpi dot org
 */

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


int 
main(int argc, char *argv[])
{
  int num; 
  int rank, size, tag, next, from;
  MPI_Status status;

  /* Start up MPI */

  MPI_Init(&argc, &argv);
  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
  MPI_Comm_size(MPI_COMM_WORLD, &size);

  /* Arbitrarily choose 201 to be our tag.  Calculate the rank of the
     next process in the ring.  Use the modulus operator so that the
     last process "wraps around" to rank zero. */

  tag = 201;
  next = (rank + 1) % size;
  from = (rank - 1 + size) % size;

  /* If we are the "console" process, get a integer from the user to
     specify how many times we want to go around the ring */

  if (rank == 0) {
    printf("Enter the number of times around the ring: ");
    scanf("%d", &num);

    printf("Process %d sending %d to %d\n", rank, num, next);

    /* Send the number to the next process in the ring */

  }

  /* Pass the message around the ring.  The exit mechanism works as
     follows: the message (a positive integer) is passed around the
     ring.  Each time is passes rank 0, it is decremented.  When each
     processes receives the 0 message, it passes it on to the next
     process and then quits.  By passing the 0 first, every process
     gets the 0 message and can quit normally. */

  do {

    /* Receive the number */

    printf("Process %d received %d\n", rank, num);

    if (rank == 0) {
      num--;
      printf("Process 0 decremented num\n");
    }

    printf("Process %d sending %d to %d\n", rank, num, next);

    /* Send the number on to the next process */

  } while (num > 0);
  printf("Process %d exiting\n", rank);

  /* The last process does one extra send to process 0, which needs to
     be received before the program can exit */

  if (rank == 0) {
    /* Receive the number */
  }

  /* Quit */

  MPI_Finalize();
  return 0;
}