//  Example Slave Program
//  slave1.c

#include <stdio.h> 
#include "/usr/pvm3/include/pvm3.h"
#define MAXTASKS 10
#define MAXOPERATIONS 8

//-------------------------------------------------------------------------------------
// "complex" Number Class  
// Pretty Self-Explanatory

class complex
  { private:
      double Real,Imaginary;
    public:
      complex() { Real=0; Imaginary=0; }
      complex(double r,double i) { Real=r; Imaginary=i; }
      void Equals(double r,double i) { Real=r; Imaginary=i; }
      double R() { return Real; }
      double I() { return Imaginary; }
      complex operator + (complex);
      complex operator - (complex);
      complex operator * (complex);
//    complex operator / (complex);
      void operator += (complex);
      void operator -= (complex);
      void operator *= (complex);
//    void operator /= (complex);
      void sqr();
  };

complex complex::operator + (complex a)
  { complex X(R()+a.R(),I()+a.I());
    return X; 
  }
  
complex complex::operator - (complex a)
  { complex X(R()-a.R(),I()-a.I());
    return X;
  }

complex complex::operator * (complex a)
  { complex X(R()*a.R()-(I()*a.I()),R()*a.I()+I()*a.R());
    return X;
  }

//complex complex::operator / (complex a)
//  { complex X(R()/a.R()-(I()/a.I()),R()/a.I()+I()/a.R());
//    return X;
//  }

void complex::operator += (complex a)
  { Real=R()+a.R();
    Imaginary=I()+a.I();
  }  

void complex::operator -= (complex a)
  { Real=R()-a.R();
    Imaginary=I()-a.I();
  }

void complex::operator *= (complex a)
  { Real=R()*a.R()-I()*a.I();
    Imaginary=R()*a.I()+I()*a.R();
  }

void complex::sqr()
  { Real=R()*R()-I()*I();
    Imaginary=2*R()*I();
  }

const XWINDOW=500;
const YWINDOW=500;

double XMin=-2,XMax=2;           // Cartesian Coordinate Plane Frame of Reference
double YMin=-2,YMax=2;           // Coordinates

const Mandelbrot=0;              // For "Mandelbrot Mode"
const Julia=1;                   // For "Julia Mode"

const NoTarga=0;
const Targa=1;

int Mode=Mandelbrot;             // Initially in Mandelbrot Mode...
complex JuliaConstant(-0.12375,0.56508); // The Inital Julia Constant
int FileMode=NoTarga;

const Circle=0;
const Square=1;

int BoundMode=0;

int Iterations=30;               // The number of times iterated 

const BoundLow=-10;
const BoundHigh=10;

int bounded(double x,double y)   // Boolean Function to determine Divergence 
  { if (BoundMode==Circle)
      return (sqrt(x*x+y*y)<=BoundHigh);
      else 
        return ((x<=BoundHigh)&&(x>=BoundLow)&&(y<=BoundHigh)&&(y>=BoundLow)); 
  }

int iterate(double x,double y)   // The Iterate Procedure.  Returns number of iterations before
  { complex c(x,y),d(0,0);       // "Divergence"
    if (Mode==Mandelbrot) d.Equals(x,y); 
      else d=JuliaConstant;
    int b=0;
    while ((b<Iterations)&&(bounded(c.R(),c.I())))
      { c=c*c+d; b++; }
    return b;
  }

void main()
{  int mytid;       /* my task id */
   int tids[MAXTASKS];    /* task ids   */
   int n, me, i, nproc, master, msgtype,o;
   double result[50][500];

    /* enroll in pvm */
       mytid = pvm_mytid();               // Get my processor ID

    /* Receive data from master */
       msgtype = 0;
       pvm_recv( -1, msgtype );                  // Get ready to receive initial data
       pvm_upkint(&nproc, 1, 1);                 // Unpack number of slave processors
       pvm_upkint(tids, nproc, 1);               // Unpack array of processor IDs
       pvm_upkint(&n, 1, 1);                     // Unpack number of tasks

    /* Determine which slave I am (0 -- nproc-1) */
    for( i=0; i<nproc ; i++ )
       if( mytid == tids[i] ){ me = i; break; }  // Determine array position

    for(o=0;o<50;o++)
      { for(int m=0;m<500;m++)
          result[o][m]=(double)iterate(XMin+m*(XMax-XMin)/XWINDOW,YMin+(me*50+o)*(YMax-YMin)/YWINDOW);
   
      }
    /* Send result to master */
    pvm_initsend(PvmDataDefault);                    // Get ready to send data
    pvm_pkint(&me,1,1);                              // Pack which processor I am
    for(o=0;o<50;o++)
      { pvm_pkdouble(result[o],XWINDOW,1);   }              // Pack the resultant sum
     
    msgtype=5;                                       // Identify message type
    master=pvm_parent();                             // Find out where I came from
    pvm_send( master, msgtype );                     // Send message back to parent process

    /* Program finished. Exit PVM before stopping */
    pvm_exit();
}


