#include <stdio.h>
#include <stdlib.h> /* for generating the random input */
#include <math.h>
#include "pvm3.h"

#define SLAVENAME "somslave"
#define MAX_SLAVES 120
#define NR_OF_INPUTS 100
#define NR_OF_LOOPS 100

main()
{
    int mytid;                  /* my task id */
    int tids[MAX_SLAVES];	/* slave task ids */
    int n, nproc, numt, i, j, who, z, c;
    int xlocation[MAX_SLAVES];
    int winner;
    float input[NR_OF_INPUTS], distance[MAX_SLAVES];
    float min, interval;
    float prop[10000];
    struct timeval tik, tok;

for (c=1; c<13; c++) {

    mytid = pvm_mytid(); /* enroll in pvm */

    gettimeofday(&tik, (struct timezone*)0); /* start the clock */

    nproc = 10*c;           /* Set number of slaves to start */
    if( nproc > MAX_SLAVES ) nproc = MAX_SLAVES;
    printf("Starting %d worker tasks ... " , nproc);

    numt=pvm_spawn(SLAVENAME, (char**)0, 0, "", nproc, tids); 
    if( numt < nproc ){
       printf("\n 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(1);
    }
    printf("SUCCESSFUL\n");

    /* initialize_data( data, n ); */
    n = NR_OF_INPUTS;
    for( i=0 ; i<n ; i++ ) { input[i] = rand()/RAND_MAX; }

    /* Broadcast input data to slave tasks */
    pvm_initsend(PvmDataDefault);
    pvm_pkint(&nproc, 1, 1);
    pvm_pkint(tids, nproc, 1);
    pvm_pkint(&n, 1, 1);
    pvm_pkfloat(input, n, 1);
    pvm_mcast(tids, nproc, 1);

    for (z=0; z<NR_OF_LOOPS; z++) {

      /* Wait for the slaves to finish the calculations */
      for( i=0 ; i<nproc ; i++ ){
         pvm_recv( -1, 2 );     /* messagetype=2 */
         pvm_upkint(   &who, 1, 1 );
         pvm_upkint(   &xlocation[who], 1, 1 );
         pvm_upkfloat( &distance[who], 1, 1 );
         pvm_upkfloat( prop, 10000, 1 );

         //printf(" I got %f from %d subsection %d.\n", distance[who], who, xlocation[who]);
      }

      /* calculate the winner */
      min = 1000000;
      for( i=0; i<nproc; i++) 
         if (min > distance[i]) {
           winner = i;
           min = distance[i];
         }
    
      /* broadcast the winner's location */
      pvm_initsend(PvmDataDefault);
      pvm_pkint( &xlocation[winner], 1, 1);
      pvm_pkint( &winner, 1, 1);
      pvm_mcast( tids, nproc, 3);

      /* wait till all tasks are ready again */
      for( i=0 ; i<nproc ; i++ ){
         pvm_recv( -1, 4 );     /* messagetype=4 */
         pvm_upkint( &who, 1, 1 );
      }
    }

    gettimeofday(&tok, (struct timezone*)0);
    interval = (tok.tv_sec-tik.tv_sec)*1000000+(tok.tv_usec-tik.tv_usec);
//    for (i=0; i<nproc; i++)  
//      printf("node %d has minimum distance %f in %i.\n",i,distance[i],xlocation[i]);
//    printf("The winning neuron is located at (%d,%d).\n",winner, xlocation[winner]);
//    printf("The weights were updated.\n");
    printf("Time needed: %f\n", interval);

    /* Program Finished exit PVM before stopping */
    pvm_exit();

}

}

