/**************************************************/
/*  PVM Example Program                           */
/*  Multicast with Arrays        master2.c        */
/*                                                */
/**************************************************/

#include <stdio.h>
#include "/usr/pvm3/include/pvm3.h"
#define SLAVENAME "slave2"
#define MAXTASKS 10
#define MAXCOL 8

// Prints out contents of an array
print_array(float data[MAXTASKS][MAXCOL])
{int i, j;
 for (i=0; i<MAXTASKS; i++)
   { printf("%d: ",i);
     for(j=0; j<MAXCOL; j++)
        { printf(" %5.2f ", data[i][j]); }
     printf("\n");
   }
}

main()
{
    int n, nproc, numt, i, j, who, msgtype, nhost, narch;
    int mytid;                  /* my task id */
    int tids[MAXTASKS];                   /* slave task ids */
    int avail[MAXTASKS];           /* availailable slaves  */
    float  data [MAXTASKS][MAXCOL];                    /* array of reals  */
    float  result [MAXTASKS];                    /* array of reals  */
    struct pvmhostinfo *hostp[MAXTASKS]; /* pointers to host information */
    srand(137);             // Seed pseudorandom number generator with value

    /* enroll in pvm */
    mytid = pvm_mytid();

    /* Set number of slaves to start */
    /* Can not do stdin from spawned task */
    if( pvm_parent() == PvmNoParent ){
       puts("How many slave programs (1-MAXTASKS)?");
       scanf("%d", &nproc);
    }
    else{
       pvm_config( &nhost, &narch, hostp );
       nproc = nhost;
       if( nproc > MAXTASKS ) nproc = MAXTASKS ;
    }

    /* start up slave tasks */
    numt=pvm_spawn(SLAVENAME, (char**)0, 0, "", nproc, tids);
    if( numt < nproc ){
       printf("Trouble spawning slaves. Aborting. Error codes are:\n");
       for( i=numt ; i<nproc ; i++ ) {
          printf("TID %d %d\n",i,tids[i]); }
       for( i=0 ; i<numt ; i++ ){
          pvm_kill( tids[i] );
       }
       pvm_exit();
       exit();
    }
   /* Begin User Program */
    n = MAXTASKS;
    /* initialize_data( data, n ); */
    for( i=0 ; i<n ; i++ ){
       for (j= 0; j < MAXCOL-1 ; j++)
         {
           data[i][j] =  rand() % 100; // Initialize array with random numbers

         }
         data[i][MAXCOL-1]=0;  // Set last column to zero to hold sum
    }
   printf("Init done:\n");
   print_array(data);

    /* Broadcast initial data to slave tasks */
       msgtype = 0;   		// Arbitrarily set the message type to send
       pvm_initsend(PvmDataDefault);                   // Get ready to send message buffer 
       pvm_pkint(&nproc, 1, 1);                  // Pack number of slave processors
       pvm_pkint(tids, nproc, 1);                // Pack array of task IDs
       pvm_pkint(&n, 1, 1);                      // Pack number of tasks
       pvm_pkfloat(data, MAXTASKS*MAXCOL, 1);  // Pack array data to send
       pvm_mcast(tids, nproc, msgtype);        // Multicast message to all processors

    /* Wait for results from slaves */
    msgtype = 5;   		// Arbitrarily set the message type to receive
    for( i=0 ; i<nproc ; i++ ){
       pvm_recv( -1, msgtype );                  // Wait for message of right type
       pvm_upkint( &who, 1, 1 );                       // Find out who sent message
       pvm_upkfloat( &result[who], 1, 1 );                    // Put answer in Result array

       // Display results
       printf("I got %f from %d which is tid %d\n",result[who],who, tids[who]);

       data[who ][MAXCOL-1] = result[who];                    // Copy row sum to 2-D array
    }
    printf("\n\nFinal:\n");  // Output results
    print_array(data);

    /* Program Finished - exit PVM before stopping */
    pvm_exit();
}
