/* Eamon Walsh     11/25/97     Period 3
 *
 * Mandelbrot Program with PVM
 * and zooming capability
 *
 * SLAVE PROGRAM
 */

#include <stdlib.h>
#include "/usr/pvm3/include/pvm3.h"   //PVM header file

const int PIXELS=600;     //Holds the size of the window
const int NPROCESS=20;    //Holds the number of PVM slaves
static float X1,X2,Y1,Y2; //Define the viewing rectangle


static void SetWindow(int me, float yarray[]) {
/* Sets the upper and lower Y coords of 
   the particular window handled by the slave */

   Y1 = yarray[me];
   Y2 = yarray[me+1];
}


static float ConvertX(int x) {
/* Converts from pixel coordinates to real coordinates */

   return X1 + ((float)x/PIXELS)*(X2-X1);
}


static float ConvertY(int y) {
/* Converts from pixel coordinates to real coordinates */

   return Y1 + ((float)y/(PIXELS/NPROCESS))*(Y2-Y1);
}
   

static void CalculateRow(int ypos, int data[] ) {
/* The mandelbrot algorithm.
   Color values are saved in an array. */

   float j,x1,y1,x,y,r,b;  
   int    n,i;

   j = ConvertY(ypos);
   for (i = 0; i<PIXELS; i++) {
 	 b = ConvertX(i);
         x = b;
         y = j;
         n = 0;
         r = 0;
         while (n<64 && r<4) {
            x1 = x*x - y*y + b;
            y1 = 2*x*y + j;
            r = x1*x1 + y1*y1;
            x = x1;
            y = y1;
            n++;
         }

	 //If the point escaped, save white
	 //Else save an indexed color value
         if (r < 4)
           { data[i] = 16; }
         else
           { data[i] = n/4;}
   }
}


int main() {
/* Sets up PVM, receives window data,
   Calculates color values for the mandelbrot
   set within a specific window, and returns the data. */

   int mytid,n,me,i,master,msgtype,
       tids[NPROCESS],data[PIXELS];
   float yarray[NPROCESS+1];

   mytid = pvm_mytid();

   //Receive data
   msgtype = 0;
     pvm_recv(-1,msgtype);
     pvm_upkint(tids,NPROCESS,1);       // Task ID's 
     pvm_upkfloat(&X1,1,1);		
     pvm_upkfloat(&X2,1,1);		// X coordinates
     pvm_upkfloat(yarray,NPROCESS+1,1); // Y coordinates

   for (i=0;i<NPROCESS;i++)
	if (mytid == tids[i]) {		// get my number
	   me = i;			// (0..NPROCESS-1)
	   break;
	}
   SetWindow(me,yarray);		// Set up the window
   msgtype = 5;
   master = pvm_parent();

   for (i=0;i<PIXELS/NPROCESS;i++) {	//Send back arrays of data
	CalculateRow(i,data);		//containing color index values
	pvm_initsend(PvmDataDefault);
	pvm_pkint(&me,1,1);		//also send my process number
	pvm_pkint(data,PIXELS,1);
	pvm_send(master,msgtype);
   }
   pvm_exit();
}
