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

/* the number of values being computed */
#define N 1000

/* function to compute the square root of a value */
#define ERROR 1e-10
double square_root(double value) {
    double hi = 1.0;
    double lo = value;

    while (fabs(hi - lo) > ERROR) {
        hi = (hi + lo) / 2.0;
        lo = value / hi; 
    }   

    return hi; 
}

int main(int argc, char** argv) {
    int rank, size;

    /* initialize MPI */
    MPI_Init(&argc, &argv);

    /* get the rank (process id) and size (number of processes) */
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    MPI_Comm_size(MPI_COMM_WORLD, &size);

    /* we calculate a different set of square roots in each process */
    double my_values[N];
    for (int i = 0; i < N; i++) {
        my_values[i] = square_root(i);
    }   

    /* each process sends to next one in chain:
     * 0 to 1, 1 to 2, etc. last sends back to 0
     * so our recipient is one process greater, and sender is one less */
    int recipient = rank + 1;
    if (recipient == size) {
        recipient = 0;
    }   
    int sender = rank - 1;
    if (sender < 0) {
        sender = size - 1;
    }

    /* send to our recipient */
    MPI_Send(&my_values, N, MPI_DOUBLE, recipient, 0, MPI_COMM_WORLD);

    /* receive value from our sender */
    double other_values[N];
    MPI_Recv(&other_values, N, MPI_DOUBLE, sender, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);

    /* print out status message */
    printf("Process %d received %d values from process %d.\n", rank, N, sender);

    /* quit MPI */
    MPI_Finalize( );
    return 0;
}