/* calcpi - upravena verzia: bezi aj bez PVM, 
   ak sa zada command-line parameter 0 */

/******************************************************************************
*                           PVM TEMPLATE CODES
* FILE: calcpi.c
* OTHER FILES: dboard.c, make.calcpi.<arch>.c
* DESCRIPTION:  PVM pi calculation example program.  C Version.
*    This program calculates pi using a "dartboard" algorithm.  See
*    Fox et al.(1988) Solving Problems on Concurrent Processors, vol.1
*    page 207.  All processes contribute to the calculation, with the
*    master averaging the values for pi. In this example, a single code
*    acts as both master and worker.  Execution is handled by conditional
*    statements which check if the process is the master or not.
* PVM VERSION: 3.x
* AUTHOR: Roslyn Leibensperger
* LAST REVISED: 5/31/94 RYL 
******************************************************************************/

#include <stdlib.h>
#include <stdio.h>
#include "pvm3.h"    	/* PVM version 3.0 include file */

#define darts 50000   	/* number of throws at dartboard */
#define rounds 20    	/* number of times "darts" is iterated */
#define max_procs 16  	/* maximum number of spawned processes */

main(int argc, char *argv[]) { 
double homepi,       	/* value of pi calculated by current process */
       avepi,        	/* average pi value for all iterations */
       pisum,        	/* sum of pi values received from other processes */
       pi,           	/* average of pi after "darts" is thrown */
       pirecv,       	/* pi received from other process */
       dboard();      
int mytid,           	/* PVM task id of process - also used as seed number */
    parent_tid,	     	/* PVM task id for parent/master process */
    tids[max_procs], 	/* array to PVM task ids for spawned processes */
    nworkers,	     	/* number of workers processes */
    mtype,           	/* PVM message type */
    rcode,           	/* PVM return code */
    i, n;

nworkers=max_procs+1;
if(argc>1) nworkers=atoi(argv[1]); 

if(nworkers>0)
{
mytid = pvm_mytid();
printf("calcpi PVM task id = %8x\n",mytid);
parent_tid = pvm_parent();
if (parent_tid == PvmNoParent) {
  if(nworkers>max_procs){
    printf ("How many tasks would you like to start(max= %d)? ", max_procs);
    scanf("%d", &nworkers);
    if (nworkers > max_procs) {
        printf("Sorry - too many tasks specified.  Try again.\n");
	exit(0);
        }
  			}
    rcode = pvm_spawn("calcpi", NULL, PvmTaskDefault, "", nworkers, tids);
    printf("Number of calcpi processes spawned = %3d\n", rcode);
    nworkers = rcode;
    }

srandom (mytid);
}
avepi = 0;
for (i = 0; i < rounds; i++) {
     homepi = dboard(darts);

if(nworkers>0)
{
     mtype = i;	/* set message type equal to this round */
     if (parent_tid != PvmNoParent) {
  	  rcode = pvm_initsend(PvmDataDefault); 
	  rcode = pvm_pkdouble(&homepi, 1, 1);
          rcode = pvm_send(parent_tid, mtype);
          }
     else {
	  pisum = 0;
          for (n = 0; n < nworkers; n++) {
	       rcode = pvm_recv(-1, mtype);
	       if (rcode < 0) 
		   printf("Receive failure on round &3d\n", mtype);
 	       rcode = pvm_upkdouble(&pirecv, 1, 1);
               pisum = pisum + pirecv;
               }
          pi = (pisum + homepi)/(nworkers + 1);
          avepi = ((avepi * i) + pi)/(i + 1); 
          printf("   After %7d throws, average value of pi = %10.8f\n",
                 (darts * (i + 1)),avepi,pi);
          }    
} else {
       avepi = ((avepi * i) + homepi)/(i + 1); 
          printf("   After %7d throws, average value of pi = %10.8f\n",
                 (darts * (i + 1)),avepi,homepi);
       }
    } 
if(nworkers>0) rcode = pvm_exit();
}

