/*************************************************************
* Test of PVMFSEND AND PVMFRECEIVE Function Subroutine Calls *
*************************************************************/
/* Program cRTest */
#include <stdio.h>
#include <math.h>
#include <time.h>
#include <stdlib.h>
#include <mpp/pvm3.h>
#define NPEmax 4
#define N 5

int MsgTag,MyTID,MasTID,MyPE,MsgPE,Master;
int Info,BufID,SendTID;int NBytes;int NPEs;int NM;
float D[N];      /* local array */
float Dmax;   /* local max change */
float DMmax[NPEmax];  /*  Master copies of local max changes. */
float Result;    /*  Result received by Master */
float DGmax;     /* global max change */
float MaxVal();

main()
{int i,ip;

/* Code:   Copies of This code are run by all processors. */
/* Code:   Enroll into PVM */
/* Code:   Obtain initial PVM data. */
/* Code:   Job Script preSpawns Master and Nproc-1 slaves */

   MyTID = pvm_mytid();   /* get This PE's Task ID (TID) */
   MyPE = pvm_get_PE(pvm_mytid());  /* get PE's PE ID */
   NPEs = pvm_gsize(0);  /* get group size of all, denote by 0 */

   printf("MyPE,MyTID,NPEs=%d %d %d\n",MyPE,MyTID,NPEs);
   if(NPEs != NPEmax) printf("BAD: Unequal Declared and Execution PE sizes\n");

   Master = 0;
   MasTID = pvm_gettid(0,Master);  /* get TID of Master */
   printf("MyPE,MyTID,Master,MasTID=%d %d %d %d\n",MyPE,MyTID,Master,MasTID);

   printf("MyPE,D[0:%1d]= %d ",N,MyPE);
   for(i=0;i<N;++i) {
      D[i]=(NPEs-MyPE)*i*0.1;
   printf(" %10.4f ",D[i]);
   } /* endfor */
   printf("\n");

   NM=N;Dmax=MaxVal(&NM,D); /* call maximum value procedure with N and D */
      
   printf("MyPE,LocalMax(D)= %d %10.4f\n", MyPE,Dmax);

   DMmax[0]=Dmax;
   MsgTag=2;
   if(MyPE>0) {
  /* CAREFUL of Sending Shared/Global Data, But Sending MyPE is OK Here: */
      BufID = pvm_initsend(PvmDataDefault);  /* initialize send buffer */
    /* CAUTION:  T3D uses 8 Byte Integers! But in Cray C long = int */
      Info = pvm_pkint(&MyPE,1,1);
      Info = pvm_pkfloat(&Dmax,1,1);
      Info = pvm_send(MasTID,MsgTag);
      }  /* Endif */
   else {
      for(ip=1;ip<NPEs;++ip) {
         BufID = pvm_recv(-1,MsgTag);
         Info = pvm_bufinfo(BufID,&NBytes,&MsgTag,&SendTID); /* Get SenderID */
         Info = pvm_upkint(&MsgPE,1,1);
         Info = pvm_upkfloat(&Result,1,1);
          /* print auxiliary data on sender including sender's TID */
        printf("Slave:%13d; returned: %10.4f @NBytes:%13d for All Messages\n",
           SendTID,Result,NBytes);
         printf("ip,MsgPE= %d %d\n",ip,MsgPE);/* print received PE#s */
          /* print received results */
         printf("MsgPE,Result(D)= %d %10.4f\n", MsgPE,Result);
         DMmax[ip]=Result;
         }  /* Enddo */
      }  /* Endifelse */
      if(MyPE == Master) {
          DGmax=MaxVal(&NPEs,DMmax);   /* Get Global Max of Local Maxs */
      printf("MyPE,GlobalMax(D)= %13d %10.4f\n",MyPE,DGmax);
      }  /* Endif */
/* CAUTION:  Must  Use Barrier So Master Can Finish Global Max, Before Slaves */
/* Code:      Leave with their Message Buffers! */
      Info = pvm_barrier(0,-1);  /* Use 0 for all in C, instead of PVMALL in F*/
/* Code:   Exit PVM */
   Info = pvm_exit();
   exit(Info);
} /* end main program*/

/*  MaximumValue Procedure  */
float MaxVal(NA,DA)
   int NA;
   float DA[];
{
   int j;
   float temp;
   temp=DA[0];
   for(j=1;j<NA;++j) {
      if(DA[j]>temp) {
         temp=DA[j];
      }
   }
   return(temp);
} /* end MaxVal function */

