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

#define LENGTH 30000000

int main(int argc, char** argv) {
   float *a, *b, *r, *a_loc, *b_loc, *r_loc;
   long    i, i_loc, proc, n_loc;
   double start, end;
   int my_rank, p;
   MPI_Status status;


   MPI_Init(&argc,&argv);

   MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);
   MPI_Comm_size(MPI_COMM_WORLD, &p);

   n_loc = LENGTH / p ;                
   
   if ( my_rank==0 ) {
      a = (float*)malloc(LENGTH * sizeof(float) );
      b = (float*)malloc(LENGTH * sizeof(float) );
      r = (float*)malloc(LENGTH * sizeof(float) );

      a_loc = a;
      b_loc = b;
      r_loc = r;

      for(i=0; i<LENGTH; i++) {
         a[i] = rand();
         b[i] = rand();
      }
      for(proc=1; proc < p; proc++) {
         MPI_Send( &(a[n_loc*proc]), n_loc, MPI_FLOAT, proc, 1, MPI_COMM_WORLD );
	 MPI_Send( &(b[n_loc*proc]), n_loc, MPI_FLOAT, proc, 2, MPI_COMM_WORLD ); 
      }
   } else {
      a_loc = (float*)malloc(n_loc * sizeof(float) );
      b_loc = (float*)malloc(n_loc * sizeof(float) );
      r_loc = (float*)malloc(n_loc * sizeof(float) );

      MPI_Recv( a_loc, n_loc, MPI_FLOAT, 0, 1, MPI_COMM_WORLD, &status);
      MPI_Recv( b_loc, n_loc, MPI_FLOAT, 0, 2, MPI_COMM_WORLD, &status);
   }

   start = MPI_Wtime();

   for(i=0; i<n_loc; i++) {
      r_loc[i] = a_loc[i] + b_loc[i];
   }

   end = MPI_Wtime();

   if ( my_rank!=0 ) {
      MPI_Send( r_loc, n_loc, MPI_FLOAT, 0, 1, MPI_COMM_WORLD ); 
   } else {
      for(proc=1; proc < p; proc++) {
         MPI_Recv( &(r[n_loc*proc]), n_loc, MPI_FLOAT, proc, 1, MPI_COMM_WORLD, &status);
      }
   }

   printf("process %d: elapsed time %f\n", my_rank, end-start);

   MPI_Finalize();
}

