Blame examples/pmandel_spawn.c

Packit 0848f5
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
Packit 0848f5
/*
Packit 0848f5
 *  (C) 2001 by Argonne National Laboratory.
Packit 0848f5
 *      See COPYRIGHT in top-level directory.
Packit 0848f5
 */
Packit 0848f5
#include <stdio.h>
Packit 0848f5
#include <stdlib.h>
Packit 0848f5
#include <math.h>
Packit 0848f5
#include <string.h>
Packit 0848f5
#ifdef HAVE_WINDOWS_H
Packit 0848f5
#include <process.h> /* getpid() */
Packit 0848f5
#include <winsock2.h>
Packit 0848f5
#else
Packit 0848f5
#include <unistd.h>
Packit 0848f5
#include <sys/types.h>
Packit 0848f5
#include <sys/socket.h>
Packit 0848f5
#include <sys/select.h>
Packit 0848f5
#include <netinet/in.h>
Packit 0848f5
#include <errno.h>
Packit 0848f5
#endif
Packit 0848f5
#include "mpi.h"
Packit 0848f5
Packit 0848f5
/* definitions */
Packit 0848f5
Packit 0848f5
#define PROMPT 1
Packit 0848f5
#define USE_PPM /* define to output a color image, otherwise output is a grayscale pgm image */
Packit 0848f5
Packit 0848f5
#ifndef MIN
Packit 0848f5
#define MIN(x, y)	(((x) < (y))?(x):(y))
Packit 0848f5
#endif
Packit 0848f5
#ifndef MAX
Packit 0848f5
#define MAX(x, y)	(((x) > (y))?(x):(y))
Packit 0848f5
#endif
Packit 0848f5
Packit 0848f5
#define DEFAULT_NUM_SLAVES 3 /* default number of children to spawn */
Packit 0848f5
#define DEFAULT_PORT 7470   /* default port to listen on */
Packit 0848f5
#define NOVALUE 99999       /* indicates a parameter is as of yet unspecified */
Packit 0848f5
#define MAX_ITERATIONS 10000 /* maximum 'depth' to look for mandelbrot value */
Packit 0848f5
#define INFINITE_LIMIT 4.0  /* evalue when fractal is considered diverging */
Packit 0848f5
#define MAX_X_VALUE 2.0     /* the highest x can go for the mandelbrot, usually 1.0 */
Packit 0848f5
#define MIN_X_VALUE -2.0    /* the lowest x can go for the mandelbrot, usually -1.0 */
Packit 0848f5
#define MAX_Y_VALUE 2.0     /* the highest y can go for the mandelbrot, usually 1.0 */
Packit 0848f5
#define MIN_Y_VALUE -2.0    /* the lowest y can go for the mandelbrot, usually -1.0 */
Packit 0848f5
#define IDEAL_ITERATIONS 100 /* my favorite 'depth' to default to */
Packit 0848f5
/* the ideal default x and y are currently the same as the max area */
Packit 0848f5
#define IDEAL_MAX_X_VALUE 1.0
Packit 0848f5
#define IDEAL_MIN_X_VALUE -1.0
Packit 0848f5
#define IDEAL_MAX_Y_VALUE 1.0
Packit 0848f5
#define IDEAL_MIN_Y_VALUE -1.0
Packit 0848f5
#define MAX_WIDTH 2048       /* maximum size of image, across, in pixels */
Packit 0848f5
#define MAX_HEIGHT 2048      /* maximum size of image, down, in pixels */
Packit 0848f5
#define IDEAL_WIDTH 768       /* my favorite size of image, across, in pixels */
Packit 0848f5
#define IDEAL_HEIGHT 768      /* my favorite size of image, down, in pixels */
Packit 0848f5
Packit 0848f5
#define RGBtocolor_t(r,g,b) ((color_t)(((unsigned char)(r)|((unsigned short)((unsigned char)(g))<<8))|(((unsigned long)(unsigned char)(b))<<16)))
Packit 0848f5
#define getR(r) ((int)((r) & 0xFF))
Packit 0848f5
#define getG(g) ((int)((g>>8) & 0xFF))
Packit 0848f5
#define getB(b) ((int)((b>>16) & 0xFF))
Packit 0848f5
Packit 0848f5
typedef int color_t;
Packit 0848f5
Packit 0848f5
typedef struct complex_t
Packit 0848f5
{
Packit 0848f5
  /* real + imaginary * sqrt(-1) i.e.   x + iy */
Packit 0848f5
  double real, imaginary;
Packit 0848f5
} complex_t;
Packit 0848f5
Packit 0848f5
/* prototypes */
Packit 0848f5
Packit 0848f5
void read_mand_args(int argc, char *argv[], int *o_max_iterations,
Packit 0848f5
		    int *o_pixels_across, int *o_pixels_down,
Packit 0848f5
		    double *o_x_min, double *o_x_max,
Packit 0848f5
		    double *o_y_min, double *o_y_max, int *o_julia,
Packit 0848f5
		    double *o_julia_real_x, double *o_julia_imaginary_y,
Packit 0848f5
		    double *o_divergent_limit, int *o_alternate,
Packit 0848f5
		    char *filename, int *num_colors, int *use_stdin,
Packit 0848f5
		    int *save_image, int *num_children);
Packit 0848f5
void check_mand_params(int *m_max_iterations,
Packit 0848f5
		       int *m_pixels_across, int *m_pixels_down,
Packit 0848f5
		       double *m_x_min, double *m_x_max,
Packit 0848f5
		       double *m_y_min, double *m_y_max,
Packit 0848f5
		       double *m_divergent_limit,
Packit 0848f5
		       int *m_num_children);
Packit 0848f5
void check_julia_params(double *julia_x_constant, double *julia_y_constant);
Packit 0848f5
int additive_mandelbrot_point(complex_t coord_point, 
Packit 0848f5
			    complex_t c_constant,
Packit 0848f5
			    int Max_iterations, double divergent_limit);
Packit 0848f5
int additive_mandelbrot_point(complex_t coord_point, 
Packit 0848f5
			    complex_t c_constant,
Packit 0848f5
			    int Max_iterations, double divergent_limit);
Packit 0848f5
int subtractive_mandelbrot_point(complex_t coord_point, 
Packit 0848f5
			    complex_t c_constant,
Packit 0848f5
			    int Max_iterations, double divergent_limit);
Packit 0848f5
complex_t exponential_complex(complex_t in_complex);
Packit 0848f5
complex_t multiply_complex(complex_t in_one_complex, complex_t in_two_complex);
Packit 0848f5
complex_t divide_complex(complex_t in_one_complex, complex_t in_two_complex);
Packit 0848f5
complex_t inverse_complex(complex_t in_complex);
Packit 0848f5
complex_t add_complex(complex_t in_one_complex, complex_t in_two_complex);
Packit 0848f5
complex_t subtract_complex(complex_t in_one_complex, complex_t in_two_complex);
Packit 0848f5
double absolute_complex(complex_t in_complex);
Packit 0848f5
void dumpimage(char *filename, int in_grid_array[], int in_pixels_across, int in_pixels_down,
Packit 0848f5
	  int in_max_pixel_value, char input_string[], int num_colors, color_t colors[]);
Packit 0848f5
int single_mandelbrot_point(complex_t coord_point, 
Packit 0848f5
			    complex_t c_constant,
Packit 0848f5
			    int Max_iterations, double divergent_limit);
Packit 0848f5
color_t getColor(double fraction, double intensity);
Packit 0848f5
int Make_color_array(int num_colors, color_t colors[]);
Packit 0848f5
void output_data(int *in_grid_array, int coord[4], int *out_grid_array, int width, int height);
Packit 0848f5
void PrintUsage(void);
Packit 0848f5
static int sock_write(int sock, void *buffer, int length);
Packit 0848f5
static int sock_read(int sock, void *buffer, int length);
Packit 0848f5
Packit 0848f5
#ifdef USE_PPM
Packit 0848f5
const char *default_filename = "pmandel.ppm";
Packit 0848f5
#else
Packit 0848f5
const char *default_filename = "pmandel.pgm";
Packit 0848f5
#endif
Packit 0848f5
Packit 0848f5
/* Solving the Mandelbrot set
Packit 0848f5
 
Packit 0848f5
   Set a maximum number of iterations to calculate before forcing a terminate
Packit 0848f5
   in the Mandelbrot loop.
Packit 0848f5
*/
Packit 0848f5
Packit 0848f5
/* Command-line parameters are all optional, and include:
Packit 0848f5
   -xmin # -xmax #      Limits for the x-axis for calculating and plotting
Packit 0848f5
   -ymin # -ymax #      Limits for the y-axis for calculating and plotting
Packit 0848f5
   -xscale # -yscale #  output pixel width and height
Packit 0848f5
   -depth #             Number of iterations before we give up on a given
Packit 0848f5
                        point and move on to calculate the next
Packit 0848f5
   -diverge #           Criteria for assuming the calculation has been
Packit 0848f5
                        "solved"-- for each point z, when
Packit 0848f5
                             abs(z=z^2+c) > diverge_value
Packit 0848f5
   -julia        Plot a Julia set instead of a Mandelbrot set
Packit 0848f5
   -jx # -jy #   The Julia point that defines the set
Packit 0848f5
   -alternate #    Plot an alternate Mandelbrot equation (varient 1 or 2 so far)
Packit 0848f5
*/
Packit 0848f5
Packit 0848f5
int myid;
Packit 0848f5
int use_stdin = 0;
Packit 0848f5
int sock;
Packit 0848f5
Packit 0848f5
void swap(int *i, int *j)
Packit 0848f5
{
Packit 0848f5
    int x;
Packit 0848f5
    x = *i;
Packit 0848f5
    *i = *j;
Packit 0848f5
    *j = x;
Packit 0848f5
}
Packit 0848f5
Packit 0848f5
typedef struct header_t
Packit 0848f5
{
Packit 0848f5
    int data[5];
Packit 0848f5
} header_t;
Packit 0848f5
Packit 0848f5
int main(int argc, char *argv[])
Packit 0848f5
{
Packit 0848f5
    complex_t coord_point, julia_constant;
Packit 0848f5
    double x_max, x_min, y_max, y_min, x_resolution, y_resolution;
Packit 0848f5
    double divergent_limit;
Packit 0848f5
    char file_message[160];
Packit 0848f5
    char filename[100];
Packit 0848f5
    int icount, imax_iterations;
Packit 0848f5
    int ipixels_across, ipixels_down;
Packit 0848f5
    int i, j, k, julia, alternate_equation;
Packit 0848f5
    int imin, imax, jmin, jmax;
Packit 0848f5
    int work[5];
Packit 0848f5
    header_t *result = NULL;
Packit 0848f5
    /* make an integer array of size [N x M] to hold answers. */
Packit 0848f5
    int *in_grid_array, *out_grid_array = NULL;
Packit 0848f5
    int numprocs;
Packit 0848f5
    int  namelen;
Packit 0848f5
    char processor_name[MPI_MAX_PROCESSOR_NAME];
Packit 0848f5
    int num_colors;
Packit 0848f5
    color_t *colors = NULL;
Packit 0848f5
    MPI_Status status;
Packit 0848f5
    int listener;
Packit 0848f5
    int save_image = 0;
Packit 0848f5
    int optval;
Packit 0848f5
    int num_children = DEFAULT_NUM_SLAVES;
Packit 0848f5
    int master = 1;
Packit 0848f5
    MPI_Comm parent, *child_comm = NULL;
Packit 0848f5
    MPI_Request *child_request = NULL;
Packit 0848f5
    int error_code, error;
Packit 0848f5
    char error_str[MPI_MAX_ERROR_STRING];
Packit 0848f5
    int length;
Packit 0848f5
    int index;
Packit 0848f5
    int pid;
Packit 0848f5
Packit 0848f5
    MPI_Init(&argc, &argv);
Packit 0848f5
    MPI_Comm_size(MPI_COMM_WORLD, &numprocs);
Packit 0848f5
    MPI_Comm_rank(MPI_COMM_WORLD, &myid);
Packit 0848f5
    MPI_Comm_get_parent(&parent);
Packit 0848f5
    MPI_Get_processor_name(processor_name, &namelen);
Packit 0848f5
Packit 0848f5
    pid = getpid();
Packit 0848f5
Packit 0848f5
    if (parent == MPI_COMM_NULL)
Packit 0848f5
    {
Packit 0848f5
	if (numprocs > 1)
Packit 0848f5
	{
Packit 0848f5
	    printf("Error: only one process allowed for the master.\n");
Packit 0848f5
	    PrintUsage();
Packit 0848f5
	    error_code = MPI_Abort(MPI_COMM_WORLD, -1);
Packit 0848f5
	    exit(error_code);
Packit 0848f5
	}
Packit 0848f5
Packit 0848f5
	printf("Welcome to the Mandelbrot/Julia set explorer.\n");
Packit 0848f5
Packit 0848f5
	master = 1;
Packit 0848f5
Packit 0848f5
	/* Get inputs-- region to view (must be within x/ymin to x/ymax, make sure
Packit 0848f5
	xmax>xmin and ymax>ymin) and resolution (number of pixels along an edge,
Packit 0848f5
	N x M, i.e. 256x256)
Packit 0848f5
	*/
Packit 0848f5
Packit 0848f5
	read_mand_args(argc, argv, &imax_iterations, &ipixels_across, &ipixels_down,
Packit 0848f5
	    &x_min, &x_max, &y_min, &y_max, &julia, &julia_constant.real,
Packit 0848f5
	    &julia_constant.imaginary, &divergent_limit,
Packit 0848f5
	    &alternate_equation, filename, &num_colors, &use_stdin, &save_image,
Packit 0848f5
	    &num_children);
Packit 0848f5
	check_mand_params(&imax_iterations, &ipixels_across, &ipixels_down,
Packit 0848f5
	    &x_min, &x_max, &y_min, &y_max, &divergent_limit, &num_children);
Packit 0848f5
Packit 0848f5
	if (julia == 1) /* we're doing a julia figure */
Packit 0848f5
	    check_julia_params(&julia_constant.real, &julia_constant.imaginary);
Packit 0848f5
Packit 0848f5
	/* spawn slaves */
Packit 0848f5
	child_comm = (MPI_Comm*)malloc(num_children * sizeof(MPI_Comm));
Packit 0848f5
	child_request = (MPI_Request*)malloc(num_children * sizeof(MPI_Request));
Packit 0848f5
	result = (header_t*)malloc(num_children * sizeof(header_t));
Packit 0848f5
	if (child_comm == NULL || child_request == NULL || result == NULL)
Packit 0848f5
	{
Packit 0848f5
	    printf("Error: unable to allocate an array of %d communicators, requests and work objects for the slaves.\n", num_children);
Packit 0848f5
	    error_code = MPI_Abort(MPI_COMM_WORLD, -1);
Packit 0848f5
	    exit(error_code);
Packit 0848f5
	}
Packit 0848f5
	printf("Spawning %d slaves.\n", num_children);
Packit 0848f5
	for (i=0; i
Packit 0848f5
	{
Packit 0848f5
	    error = MPI_Comm_spawn(argv[0], MPI_ARGV_NULL, 1,
Packit 0848f5
		MPI_INFO_NULL, 0, MPI_COMM_WORLD, &child_comm[i], &error_code);
Packit 0848f5
	    if (error != MPI_SUCCESS)
Packit 0848f5
	    {
Packit 0848f5
		error_str[0] = '\0';
Packit 0848f5
		length = MPI_MAX_ERROR_STRING;
Packit 0848f5
		MPI_Error_string(error, error_str, &length);
Packit 0848f5
		printf("Error: MPI_Comm_spawn failed: %s\n", error_str);
Packit 0848f5
		error_code = MPI_Abort(MPI_COMM_WORLD, -1);
Packit 0848f5
		exit(error_code);
Packit 0848f5
	    }
Packit 0848f5
	}
Packit 0848f5
Packit 0848f5
	/* send out parameters */
Packit 0848f5
	for (i=0; i
Packit 0848f5
	{
Packit 0848f5
	    MPI_Send(&num_colors, 1, MPI_INT, 0, 0, child_comm[i]);
Packit 0848f5
	    MPI_Send(&imax_iterations, 1, MPI_INT, 0, 0, child_comm[i]);
Packit 0848f5
	    MPI_Send(&ipixels_across, 1, MPI_INT, 0, 0, child_comm[i]);
Packit 0848f5
	    MPI_Send(&ipixels_down, 1, MPI_INT, 0, 0, child_comm[i]);
Packit 0848f5
	    MPI_Send(&divergent_limit, 1, MPI_DOUBLE, 0, 0, child_comm[i]);
Packit 0848f5
	    MPI_Send(&julia, 1, MPI_INT, 0, 0, child_comm[i]);
Packit 0848f5
	    MPI_Send(&julia_constant.real, 1, MPI_DOUBLE, 0, 0, child_comm[i]);
Packit 0848f5
	    MPI_Send(&julia_constant.imaginary, 1, MPI_DOUBLE, 0, 0, child_comm[i]);
Packit 0848f5
	    MPI_Send(&alternate_equation, 1, MPI_INT, 0, 0, child_comm[i]);
Packit 0848f5
	}
Packit 0848f5
    }
Packit 0848f5
    else
Packit 0848f5
    {
Packit 0848f5
	master = 0;
Packit 0848f5
	MPI_Recv(&num_colors, 1, MPI_INT, 0, 0, parent, MPI_STATUS_IGNORE);
Packit 0848f5
	MPI_Recv(&imax_iterations, 1, MPI_INT, 0, 0, parent, MPI_STATUS_IGNORE);
Packit 0848f5
	MPI_Recv(&ipixels_across, 1, MPI_INT, 0, 0, parent, MPI_STATUS_IGNORE);
Packit 0848f5
	MPI_Recv(&ipixels_down, 1, MPI_INT, 0, 0, parent, MPI_STATUS_IGNORE);
Packit 0848f5
	MPI_Recv(&divergent_limit, 1, MPI_DOUBLE, 0, 0, parent, MPI_STATUS_IGNORE);
Packit 0848f5
	MPI_Recv(&julia, 1, MPI_INT, 0, 0, parent, MPI_STATUS_IGNORE);
Packit 0848f5
	MPI_Recv(&julia_constant.real, 1, MPI_DOUBLE, 0, 0, parent, MPI_STATUS_IGNORE);
Packit 0848f5
	MPI_Recv(&julia_constant.imaginary, 1, MPI_DOUBLE, 0, 0, parent, MPI_STATUS_IGNORE);
Packit 0848f5
	MPI_Recv(&alternate_equation, 1, MPI_INT, 0, 0, parent, MPI_STATUS_IGNORE);
Packit 0848f5
    }
Packit 0848f5
Packit 0848f5
    if (master)
Packit 0848f5
    {
Packit 0848f5
	colors = malloc((num_colors+1)* sizeof(color_t));
Packit 0848f5
	if (colors == NULL)
Packit 0848f5
	{
Packit 0848f5
	    MPI_Abort(MPI_COMM_WORLD, -1);
Packit 0848f5
	    exit(-1);
Packit 0848f5
	}
Packit 0848f5
	Make_color_array(num_colors, colors);
Packit 0848f5
	colors[num_colors] = 0; /* add one on the top to avoid edge errors */
Packit 0848f5
    }
Packit 0848f5
Packit 0848f5
    /* allocate memory */
Packit 0848f5
    if ( (in_grid_array = (int *)calloc(ipixels_across * ipixels_down, sizeof(int))) == NULL)
Packit 0848f5
    {
Packit 0848f5
	printf("Memory allocation failed for data array, aborting.\n");
Packit 0848f5
	MPI_Abort(MPI_COMM_WORLD, -1);
Packit 0848f5
	exit(-1);
Packit 0848f5
    }
Packit 0848f5
Packit 0848f5
    if (master)
Packit 0848f5
    {
Packit 0848f5
	int istep, jstep;
Packit 0848f5
	int i1[400], i2[400], j1[400], j2[400];
Packit 0848f5
	int ii, jj;
Packit 0848f5
	struct sockaddr_in addr;
Packit 0848f5
	int len;
Packit 0848f5
	char line[1024], *token;
Packit 0848f5
Packit 0848f5
	if ( (out_grid_array = (int *)calloc(ipixels_across * ipixels_down, sizeof(int))) == NULL)
Packit 0848f5
	{
Packit 0848f5
	    printf("Memory allocation failed for data array, aborting.\n");
Packit 0848f5
	    MPI_Abort(MPI_COMM_WORLD, -1);
Packit 0848f5
	    exit(-1);
Packit 0848f5
	}
Packit 0848f5
Packit 0848f5
	srand(getpid());
Packit 0848f5
Packit 0848f5
	if (!use_stdin)
Packit 0848f5
	{
Packit 0848f5
	    addr.sin_family = AF_INET;
Packit 0848f5
	    addr.sin_addr.s_addr = INADDR_ANY;
Packit 0848f5
	    addr.sin_port = htons(DEFAULT_PORT);
Packit 0848f5
Packit 0848f5
	    listener = socket(AF_INET, SOCK_STREAM, 0);
Packit 0848f5
	    if (listener == -1)
Packit 0848f5
	    {
Packit 0848f5
		printf("unable to create a listener socket.\n");
Packit 0848f5
		MPI_Abort(MPI_COMM_WORLD, -1);
Packit 0848f5
		exit(-1);
Packit 0848f5
	    }
Packit 0848f5
	    if (bind(listener, &addr, sizeof(addr)) == -1)
Packit 0848f5
	    {
Packit 0848f5
		addr.sin_port = 0;
Packit 0848f5
		if (bind(listener, &addr, sizeof(addr)) == -1)
Packit 0848f5
		{
Packit 0848f5
		    printf("unable to create a listener socket.\n");
Packit 0848f5
		    MPI_Abort(MPI_COMM_WORLD, -1);
Packit 0848f5
		    exit(-1);
Packit 0848f5
		}
Packit 0848f5
	    }
Packit 0848f5
	    if (listen(listener, 1) == -1)
Packit 0848f5
	    {
Packit 0848f5
		printf("unable to listen.\n");
Packit 0848f5
		MPI_Abort(MPI_COMM_WORLD, -1);
Packit 0848f5
		exit(-1);
Packit 0848f5
	    }
Packit 0848f5
	    len = sizeof(addr);
Packit 0848f5
	    getsockname(listener, &addr, &len;;
Packit 0848f5
	    
Packit 0848f5
	    printf("%s listening on port %d\n", processor_name, ntohs(addr.sin_port));
Packit 0848f5
	    fflush(stdout);
Packit 0848f5
Packit 0848f5
	    sock = accept(listener, NULL, NULL);
Packit 0848f5
	    if (sock == -1)
Packit 0848f5
	    {
Packit 0848f5
		printf("unable to accept a socket connection.\n");
Packit 0848f5
		MPI_Abort(MPI_COMM_WORLD, -1);
Packit 0848f5
		exit(-1);
Packit 0848f5
	    }
Packit 0848f5
	    printf("accepted connection from visualization program.\n");
Packit 0848f5
	    fflush(stdout);
Packit 0848f5
Packit 0848f5
#ifdef HAVE_WINDOWS_H
Packit 0848f5
	    optval = 1;
Packit 0848f5
	    setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char *)&optval, sizeof(optval));
Packit 0848f5
#endif
Packit 0848f5
Packit 0848f5
	    printf("sending image size to visualizer.\n");
Packit 0848f5
	    sock_write(sock, &ipixels_across, sizeof(int));
Packit 0848f5
	    sock_write(sock, &ipixels_down, sizeof(int));
Packit 0848f5
	    sock_write(sock, &num_colors, sizeof(int));
Packit 0848f5
	    sock_write(sock, &imax_iterations, sizeof(int));
Packit 0848f5
	}
Packit 0848f5
Packit 0848f5
	for (;;)
Packit 0848f5
	{
Packit 0848f5
	    /* get x_min, x_max, y_min, and y_max */
Packit 0848f5
	    if (use_stdin)
Packit 0848f5
	    {
Packit 0848f5
		printf("input xmin ymin xmax ymax max_iter, (0 0 0 0 0 to quit):\n");fflush(stdout);
Packit 0848f5
		fgets(line, 1024, stdin);
Packit 0848f5
		printf("read <%s> from stdin\n", line);fflush(stdout);
Packit 0848f5
		token = strtok(line, " \n");
Packit 0848f5
		x_min = atof(token);
Packit 0848f5
		token = strtok(NULL, " \n");
Packit 0848f5
		y_min = atof(token);
Packit 0848f5
		token = strtok(NULL, " \n");
Packit 0848f5
		x_max = atof(token);
Packit 0848f5
		token = strtok(NULL, " \n");
Packit 0848f5
		y_max = atof(token);
Packit 0848f5
		token = strtok(NULL, " \n");
Packit 0848f5
		imax_iterations = atoi(token);
Packit 0848f5
		/*sscanf(line, "%g %g %g %g", &x_min, &y_min, &x_max, &y_max);*/
Packit 0848f5
		/*scanf("%g %g %g %g", &x_min, &y_min, &x_max, &y_max);*/
Packit 0848f5
	    }
Packit 0848f5
	    else
Packit 0848f5
	    {
Packit 0848f5
		printf("reading xmin,ymin,xmax,ymax.\n");fflush(stdout);
Packit 0848f5
		sock_read(sock, &x_min, sizeof(double));
Packit 0848f5
		sock_read(sock, &y_min, sizeof(double));
Packit 0848f5
		sock_read(sock, &x_max, sizeof(double));
Packit 0848f5
		sock_read(sock, &y_max, sizeof(double));
Packit 0848f5
		sock_read(sock, &imax_iterations, sizeof(int));
Packit 0848f5
	    }
Packit 0848f5
	    printf("x0,y0 = (%f, %f) x1,y1 = (%f,%f) max_iter = %d\n", x_min, y_min, x_max, y_max, imax_iterations);fflush(stdout);
Packit 0848f5
Packit 0848f5
	    /*printf("sending the limits: (%f,%f)(%f,%f)\n", x_min, y_min, x_max, y_max);fflush(stdout);*/
Packit 0848f5
	    /* let everyone know the limits */
Packit 0848f5
	    for (i=0; i
Packit 0848f5
	    {
Packit 0848f5
		MPI_Send(&x_min, 1, MPI_DOUBLE, 0, 0, child_comm[i]);
Packit 0848f5
		MPI_Send(&x_max, 1, MPI_DOUBLE, 0, 0, child_comm[i]);
Packit 0848f5
		MPI_Send(&y_min, 1, MPI_DOUBLE, 0, 0, child_comm[i]);
Packit 0848f5
		MPI_Send(&y_max, 1, MPI_DOUBLE, 0, 0, child_comm[i]);
Packit 0848f5
		MPI_Send(&imax_iterations, 1, MPI_INT, 0, 0, child_comm[i]);
Packit 0848f5
	    }
Packit 0848f5
Packit 0848f5
	    /* check for the end condition */
Packit 0848f5
	    if (x_min == x_max && y_min == y_max)
Packit 0848f5
	    {
Packit 0848f5
		/*printf("root bailing.\n");fflush(stdout);*/
Packit 0848f5
		break;
Packit 0848f5
	    }
Packit 0848f5
Packit 0848f5
	    /* break the work up into 400 pieces */
Packit 0848f5
	    istep = ipixels_across / 20;
Packit 0848f5
	    jstep = ipixels_down / 20;
Packit 0848f5
	    if (istep < 1)
Packit 0848f5
		istep = 1;
Packit 0848f5
	    if (jstep < 1)
Packit 0848f5
		jstep = 1;
Packit 0848f5
	    k = 0;
Packit 0848f5
	    for (i=0; i<20; i++)
Packit 0848f5
	    {
Packit 0848f5
		for (j=0; j<20; j++)
Packit 0848f5
		{
Packit 0848f5
		    i1[k] = MIN(istep * i, ipixels_across - 1);
Packit 0848f5
		    i2[k] = MIN((istep * (i+1)) - 1, ipixels_across - 1);
Packit 0848f5
		    j1[k] = MIN(jstep * j, ipixels_down - 1);
Packit 0848f5
		    j2[k] = MIN((jstep * (j+1)) - 1, ipixels_down - 1);
Packit 0848f5
		    k++;
Packit 0848f5
		}
Packit 0848f5
	    }
Packit 0848f5
Packit 0848f5
	    /* shuffle the work */
Packit 0848f5
	    for (i=0; i<500; i++)
Packit 0848f5
	    {
Packit 0848f5
		ii = rand() % 400;
Packit 0848f5
		jj = rand() % 400;
Packit 0848f5
		swap(&i1[ii], &i1[jj]);
Packit 0848f5
		swap(&i2[ii], &i2[jj]);
Packit 0848f5
		swap(&j1[ii], &j1[jj]);
Packit 0848f5
		swap(&j2[ii], &j2[jj]);
Packit 0848f5
	    }
Packit 0848f5
Packit 0848f5
	    /* send a piece of work to each worker (there must be more work than workers) */
Packit 0848f5
	    k = 0;
Packit 0848f5
	    for (i=0; i
Packit 0848f5
	    {
Packit 0848f5
		work[0] = k+1;
Packit 0848f5
		work[1] = i1[k]; /* imin */
Packit 0848f5
		work[2] = i2[k]; /* imax */
Packit 0848f5
		work[3] = j1[k]; /* jmin */
Packit 0848f5
		work[4] = j2[k]; /* jmax */
Packit 0848f5
Packit 0848f5
		/*printf("sending work(%d) to %d\n", k+1, i);fflush(stdout);*/
Packit 0848f5
		MPI_Send(work, 5, MPI_INT, 0, 100, child_comm[i]);
Packit 0848f5
		MPI_Irecv(&result[i], 5, MPI_INT, 0, 200, child_comm[i], &child_request[i]);
Packit 0848f5
		k++;
Packit 0848f5
	    }
Packit 0848f5
	    /* receive the results and hand out more work until the image is complete */
Packit 0848f5
	    while (k<400)
Packit 0848f5
	    {
Packit 0848f5
		MPI_Waitany(num_children, child_request, &index, &status);
Packit 0848f5
		memcpy(work, &result[index], 5 * sizeof(int));
Packit 0848f5
		/*printf("master receiving data in k<400 loop.\n");fflush(stdout);*/
Packit 0848f5
		MPI_Recv(in_grid_array, (work[2] + 1 - work[1]) * (work[4] + 1 - work[3]), MPI_INT, 0, 201, child_comm[index], &status);
Packit 0848f5
		/* draw data */
Packit 0848f5
		output_data(in_grid_array, &work[1], out_grid_array, ipixels_across, ipixels_down);
Packit 0848f5
		work[0] = k+1;
Packit 0848f5
		work[1] = i1[k];
Packit 0848f5
		work[2] = i2[k];
Packit 0848f5
		work[3] = j1[k];
Packit 0848f5
		work[4] = j2[k];
Packit 0848f5
		/*printf("sending work(%d) to %d\n", k+1, index);fflush(stdout);*/
Packit 0848f5
		MPI_Send(work, 5, MPI_INT, 0, 100, child_comm[index]);
Packit 0848f5
		MPI_Irecv(&result[index], 5, MPI_INT, 0, 200, child_comm[index], &child_request[index]);
Packit 0848f5
		k++;
Packit 0848f5
	    }
Packit 0848f5
	    /* receive the last pieces of work */
Packit 0848f5
	    /* and tell everyone to stop */
Packit 0848f5
	    for (i=0; i
Packit 0848f5
	    {
Packit 0848f5
		MPI_Wait(&child_request[i], &status);
Packit 0848f5
		memcpy(work, &result[i], 5 * sizeof(int));
Packit 0848f5
		/*printf("master receiving data in tail loop.\n");fflush(stdout);*/
Packit 0848f5
		MPI_Recv(in_grid_array, (work[2] + 1 - work[1]) * (work[4] + 1 - work[3]), MPI_INT, 0, 201, child_comm[i], &status);
Packit 0848f5
		/* draw data */
Packit 0848f5
		output_data(in_grid_array, &work[1], out_grid_array, ipixels_across, ipixels_down);
Packit 0848f5
		work[0] = 0;
Packit 0848f5
		work[1] = 0;
Packit 0848f5
		work[2] = 0;
Packit 0848f5
		work[3] = 0;
Packit 0848f5
		work[4] = 0;
Packit 0848f5
		/*printf("sending %d to tell %d to stop\n", work[0], i);fflush(stdout);*/
Packit 0848f5
		MPI_Send(work, 5, MPI_INT, 0, 100, child_comm[i]);
Packit 0848f5
	    }
Packit 0848f5
Packit 0848f5
	    /* tell the visualizer the image is done */
Packit 0848f5
	    if (!use_stdin)
Packit 0848f5
	    {
Packit 0848f5
		work[0] = 0;
Packit 0848f5
		work[1] = 0;
Packit 0848f5
		work[2] = 0;
Packit 0848f5
		work[3] = 0;
Packit 0848f5
		sock_write(sock, work, 4 * sizeof(int));
Packit 0848f5
	    }
Packit 0848f5
	}
Packit 0848f5
    }
Packit 0848f5
    else
Packit 0848f5
    {
Packit 0848f5
	for (;;)
Packit 0848f5
	{
Packit 0848f5
	    /*printf("slave[%d] receiveing bounds.\n", pid);fflush(stdout);*/
Packit 0848f5
	    MPI_Recv(&x_min, 1, MPI_DOUBLE, 0, 0, parent, MPI_STATUS_IGNORE);
Packit 0848f5
	    MPI_Recv(&x_max, 1, MPI_DOUBLE, 0, 0, parent, MPI_STATUS_IGNORE);
Packit 0848f5
	    MPI_Recv(&y_min, 1, MPI_DOUBLE, 0, 0, parent, MPI_STATUS_IGNORE);
Packit 0848f5
	    MPI_Recv(&y_max, 1, MPI_DOUBLE, 0, 0, parent, MPI_STATUS_IGNORE);
Packit 0848f5
	    MPI_Recv(&imax_iterations, 1, MPI_INT, 0, 0, parent, MPI_STATUS_IGNORE);
Packit 0848f5
	    /*printf("slave[%d] received bounding box: (%f,%f)(%f,%f)\n", pid, x_min, y_min, x_max, y_max);fflush(stdout);*/
Packit 0848f5
Packit 0848f5
	    /* check for the end condition */
Packit 0848f5
	    if (x_min == x_max && y_min == y_max)
Packit 0848f5
	    {
Packit 0848f5
		/*printf("slave[%d] done.\n", pid);fflush(stdout);*/
Packit 0848f5
		break;
Packit 0848f5
	    }
Packit 0848f5
Packit 0848f5
	    x_resolution = (x_max-x_min)/ ((double)ipixels_across);
Packit 0848f5
	    y_resolution = (y_max-y_min)/ ((double)ipixels_down);
Packit 0848f5
Packit 0848f5
	    MPI_Recv(work, 5, MPI_INT, 0, 100, parent, &status);
Packit 0848f5
	    /*printf("slave[%d] received work: %d, (%d,%d)(%d,%d)\n", pid, work[0], work[1], work[2], work[3], work[4]);fflush(stdout);*/
Packit 0848f5
	    while (work[0] != 0)
Packit 0848f5
	    {
Packit 0848f5
		imin = work[1];
Packit 0848f5
		imax = work[2];
Packit 0848f5
		jmin = work[3];
Packit 0848f5
		jmax = work[4];
Packit 0848f5
Packit 0848f5
		k = 0;
Packit 0848f5
		for (j=jmin; j<=jmax; ++j)
Packit 0848f5
		{
Packit 0848f5
		    coord_point.imaginary = y_max - j*y_resolution; /* go top to bottom */
Packit 0848f5
Packit 0848f5
		    for (i=imin; i<=imax; ++i)
Packit 0848f5
		    {
Packit 0848f5
			/* Call Mandelbrot routine for each code, fill array with number of iterations. */
Packit 0848f5
Packit 0848f5
			coord_point.real = x_min + i*x_resolution; /* go left to right */
Packit 0848f5
			if (julia == 1)
Packit 0848f5
			{
Packit 0848f5
			    /* doing Julia set */
Packit 0848f5
			    /* julia eq:  z = z^2 + c, z_0 = grid coordinate, c = constant */
Packit 0848f5
			    icount = single_mandelbrot_point(coord_point, julia_constant, imax_iterations, divergent_limit);
Packit 0848f5
			}
Packit 0848f5
			else if (alternate_equation == 1)
Packit 0848f5
			{
Packit 0848f5
			    /* doing experimental form 1 */
Packit 0848f5
			    icount = subtractive_mandelbrot_point(coord_point, julia_constant, imax_iterations, divergent_limit);
Packit 0848f5
			}
Packit 0848f5
			else if (alternate_equation == 2)
Packit 0848f5
			{
Packit 0848f5
			    /* doing experimental form 2 */
Packit 0848f5
			    icount = additive_mandelbrot_point(coord_point, julia_constant, imax_iterations, divergent_limit);
Packit 0848f5
			}
Packit 0848f5
			else
Packit 0848f5
			{
Packit 0848f5
			    /* default to doing Mandelbrot set */
Packit 0848f5
			    /* mandelbrot eq: z = z^2 + c, z_0 = c, c = grid coordinate */
Packit 0848f5
			    icount = single_mandelbrot_point(coord_point, coord_point, imax_iterations, divergent_limit);
Packit 0848f5
			}
Packit 0848f5
			in_grid_array[k] = icount;
Packit 0848f5
			++k;
Packit 0848f5
		    }
Packit 0848f5
		}
Packit 0848f5
		/* send the result to the root */
Packit 0848f5
		/*printf("slave[%d] sending work %d back.\n", pid, work[0]);fflush(stdout);*/
Packit 0848f5
		MPI_Send(work, 5, MPI_INT, 0, 200, parent);
Packit 0848f5
		/*printf("slave[%d] sending work %d data.\n", pid, work[0]);fflush(stdout);*/
Packit 0848f5
		MPI_Send(in_grid_array, (work[2] + 1 - work[1]) * (work[4] + 1 - work[3]), MPI_INT, 0, 201, parent);
Packit 0848f5
		/* get the next piece of work */
Packit 0848f5
		/*printf("slave[%d] receiving new work.\n", pid);fflush(stdout);*/
Packit 0848f5
		MPI_Recv(work, 5, MPI_INT, 0, 100, parent, &status);
Packit 0848f5
		/*printf("slave[%d] received work: %d, (%d,%d)(%d,%d)\n", pid, work[0], work[1], work[2], work[3], work[4]);fflush(stdout);*/
Packit 0848f5
	    }
Packit 0848f5
	}
Packit 0848f5
    }
Packit 0848f5
Packit 0848f5
    if (master && save_image)
Packit 0848f5
    {
Packit 0848f5
	imax_iterations = 0;
Packit 0848f5
	for (i=0; i
Packit 0848f5
	{
Packit 0848f5
	    /* look for "brightest" pixel value, for image use */
Packit 0848f5
	    if (out_grid_array[i] > imax_iterations)
Packit 0848f5
		imax_iterations = out_grid_array[i];
Packit 0848f5
	}
Packit 0848f5
Packit 0848f5
	if (julia == 0)
Packit 0848f5
	    printf("Done calculating mandelbrot, now creating file\n");
Packit 0848f5
	else
Packit 0848f5
	    printf("Done calculating julia, now creating file\n");
Packit 0848f5
	fflush(stdout);
Packit 0848f5
Packit 0848f5
	/* Print out the array in some appropriate form. */
Packit 0848f5
	if (julia == 0)
Packit 0848f5
	{
Packit 0848f5
	    /* it's a mandelbrot */
Packit 0848f5
	    sprintf(file_message, "Mandelbrot over (%lf-%lf,%lf-%lf), size %d x %d",
Packit 0848f5
		x_min, x_max, y_min, y_max, ipixels_across, ipixels_down);
Packit 0848f5
	}
Packit 0848f5
	else
Packit 0848f5
	{
Packit 0848f5
	    /* it's a julia */
Packit 0848f5
	    sprintf(file_message, "Julia over (%lf-%lf,%lf-%lf), size %d x %d, center (%lf, %lf)",
Packit 0848f5
		x_min, x_max, y_min, y_max, ipixels_across, ipixels_down,
Packit 0848f5
		julia_constant.real, julia_constant.imaginary);
Packit 0848f5
	}
Packit 0848f5
Packit 0848f5
	dumpimage(filename, out_grid_array, ipixels_across, ipixels_down, imax_iterations, file_message, num_colors, colors);
Packit 0848f5
    }
Packit 0848f5
Packit 0848f5
    if (master)
Packit 0848f5
    {
Packit 0848f5
	for (i=0; i
Packit 0848f5
	{
Packit 0848f5
	    MPI_Comm_disconnect(&child_comm[i]);
Packit 0848f5
	}
Packit 0848f5
	free(child_comm);
Packit 0848f5
	free(child_request);
Packit 0848f5
	free(colors);
Packit 0848f5
    }
Packit 0848f5
Packit 0848f5
    MPI_Finalize();
Packit 0848f5
    return 0;
Packit 0848f5
}
Packit 0848f5
Packit 0848f5
void PrintUsage(void)
Packit 0848f5
{
Packit 0848f5
    printf("usage: mpiexec -n 1 pmandel [options]\n");
Packit 0848f5
    printf("options:\n -n # slaves\n -xmin # -xmax #\n -ymin # -ymax #\n -depth #\n -xscale # -yscale #\n -out filename\n -i\n");
Packit 0848f5
    printf("All options are optional.\n");
Packit 0848f5
    printf("-i will allow you to input the min/max parameters from stdin and output the resulting image to a ppm file.");
Packit 0848f5
    printf("  Otherwise the root process will listen for a separate visualizer program to connect to it.\n");
Packit 0848f5
    printf("The defaults are:\n xmin %f, xmax %f\n ymin %f, ymax %f\n depth %d\n xscale %d, yscale %d\n %s\n",
Packit 0848f5
	IDEAL_MIN_X_VALUE, IDEAL_MAX_X_VALUE, IDEAL_MIN_Y_VALUE, IDEAL_MAX_Y_VALUE, IDEAL_ITERATIONS,
Packit 0848f5
	IDEAL_WIDTH, IDEAL_HEIGHT, default_filename);
Packit 0848f5
    fflush(stdout);
Packit 0848f5
}
Packit 0848f5
Packit 0848f5
int sock_write(int sock, void *buffer, int length)
Packit 0848f5
{
Packit 0848f5
    int result;
Packit 0848f5
    int num_bytes;
Packit 0848f5
    /*char err[100];*/
Packit 0848f5
    int total = 0;
Packit 0848f5
    struct timeval t;
Packit 0848f5
    fd_set set;
Packit 0848f5
Packit 0848f5
    while (length)
Packit 0848f5
    {
Packit 0848f5
	num_bytes = send(sock, buffer, length, 0);
Packit 0848f5
	if (num_bytes == -1)
Packit 0848f5
	{
Packit 0848f5
#ifdef HAVE_WINDOWS_H
Packit 0848f5
	    result = WSAGetLastError();
Packit 0848f5
	    if (result == WSAEWOULDBLOCK)
Packit 0848f5
	    {
Packit 0848f5
		FD_ZERO(&set);
Packit 0848f5
		FD_SET(sock, &set);
Packit 0848f5
		t.tv_sec = 1;
Packit 0848f5
		t.tv_usec = 0;
Packit 0848f5
		select(1, &set, NULL, NULL, &t);
Packit 0848f5
		continue;
Packit 0848f5
	    }
Packit 0848f5
#else
Packit 0848f5
	    if (errno == EWOULDBLOCK)
Packit 0848f5
	    {
Packit 0848f5
		FD_ZERO(&set);
Packit 0848f5
		FD_SET(sock, &set);
Packit 0848f5
		t.tv_sec = 1;
Packit 0848f5
		t.tv_usec = 0;
Packit 0848f5
		select(1, &set, NULL, NULL, &t);
Packit 0848f5
		continue;
Packit 0848f5
	    }
Packit 0848f5
#endif
Packit 0848f5
	    return total;
Packit 0848f5
	}
Packit 0848f5
	length -= num_bytes;
Packit 0848f5
	buffer = (char*)buffer + num_bytes;
Packit 0848f5
	total += num_bytes;
Packit 0848f5
    }
Packit 0848f5
    return total;
Packit 0848f5
    /*return send(sock, buffer, length, 0);*/
Packit 0848f5
}
Packit 0848f5
Packit 0848f5
int sock_read(int sock, void *buffer, int length)
Packit 0848f5
{
Packit 0848f5
    int result;
Packit 0848f5
    int num_bytes;
Packit 0848f5
    /*char err[100];*/
Packit 0848f5
    int total = 0;
Packit 0848f5
    struct timeval t;
Packit 0848f5
    fd_set set;
Packit 0848f5
Packit 0848f5
    while (length)
Packit 0848f5
    {
Packit 0848f5
	num_bytes = recv(sock, buffer, length, 0);
Packit 0848f5
	if (num_bytes == -1)
Packit 0848f5
	{
Packit 0848f5
#ifdef HAVE_WINDOWS_H
Packit 0848f5
	    result = WSAGetLastError();
Packit 0848f5
	    if (result == WSAEWOULDBLOCK)
Packit 0848f5
	    {
Packit 0848f5
		FD_ZERO(&set);
Packit 0848f5
		FD_SET(sock, &set);
Packit 0848f5
		t.tv_sec = 1;
Packit 0848f5
		t.tv_usec = 0;
Packit 0848f5
		select(1, &set, NULL, NULL, &t);
Packit 0848f5
		continue;
Packit 0848f5
	    }
Packit 0848f5
#else
Packit 0848f5
	    if (errno == EWOULDBLOCK)
Packit 0848f5
	    {
Packit 0848f5
		FD_ZERO(&set);
Packit 0848f5
		FD_SET(sock, &set);
Packit 0848f5
		t.tv_sec = 1;
Packit 0848f5
		t.tv_usec = 0;
Packit 0848f5
		select(1, &set, NULL, NULL, &t);
Packit 0848f5
		continue;
Packit 0848f5
	    }
Packit 0848f5
#endif
Packit 0848f5
	    return total;
Packit 0848f5
	}
Packit 0848f5
	length -= num_bytes;
Packit 0848f5
	buffer = (char*)buffer + num_bytes;
Packit 0848f5
	total += num_bytes;
Packit 0848f5
    }
Packit 0848f5
    return total;
Packit 0848f5
    /*return recv(sock, buffer, length, 0);*/
Packit 0848f5
}
Packit 0848f5
Packit 0848f5
color_t getColor(double fraction, double intensity)
Packit 0848f5
{
Packit 0848f5
    /* fraction is a part of the rainbow (0.0 - 1.0) = (Red-Yellow-Green-Cyan-Blue-Magenta-Red)
Packit 0848f5
    intensity (0.0 - 1.0) 0 = black, 1 = full color, 2 = white
Packit 0848f5
    */
Packit 0848f5
    double red, green, blue;
Packit 0848f5
    int r,g,b;
Packit 0848f5
    double dtemp;
Packit 0848f5
Packit 0848f5
    fraction = fabs(modf(fraction, &dtemp));
Packit 0848f5
Packit 0848f5
    if (intensity > 2.0)
Packit 0848f5
	intensity = 2.0;
Packit 0848f5
    if (intensity < 0.0)
Packit 0848f5
	intensity = 0.0;
Packit 0848f5
Packit 0848f5
    dtemp = 1.0/6.0;
Packit 0848f5
Packit 0848f5
    if (fraction < 1.0/6.0)
Packit 0848f5
    {
Packit 0848f5
	red = 1.0;
Packit 0848f5
	green = fraction / dtemp;
Packit 0848f5
	blue = 0.0;
Packit 0848f5
    }
Packit 0848f5
    else
Packit 0848f5
    {
Packit 0848f5
	if (fraction < 1.0/3.0)
Packit 0848f5
	{
Packit 0848f5
	    red = 1.0 - ((fraction - dtemp) / dtemp);
Packit 0848f5
	    green = 1.0;
Packit 0848f5
	    blue = 0.0;
Packit 0848f5
	}
Packit 0848f5
	else
Packit 0848f5
	{
Packit 0848f5
	    if (fraction < 0.5)
Packit 0848f5
	    {
Packit 0848f5
		red = 0.0;
Packit 0848f5
		green = 1.0;
Packit 0848f5
		blue = (fraction - (dtemp*2.0)) / dtemp;
Packit 0848f5
	    }
Packit 0848f5
	    else
Packit 0848f5
	    {
Packit 0848f5
		if (fraction < 2.0/3.0)
Packit 0848f5
		{
Packit 0848f5
		    red = 0.0;
Packit 0848f5
		    green = 1.0 - ((fraction - (dtemp*3.0)) / dtemp);
Packit 0848f5
		    blue = 1.0;
Packit 0848f5
		}
Packit 0848f5
		else
Packit 0848f5
		{
Packit 0848f5
		    if (fraction < 5.0/6.0)
Packit 0848f5
		    {
Packit 0848f5
			red = (fraction - (dtemp*4.0)) / dtemp;
Packit 0848f5
			green = 0.0;
Packit 0848f5
			blue = 1.0;
Packit 0848f5
		    }
Packit 0848f5
		    else
Packit 0848f5
		    {
Packit 0848f5
			red = 1.0;
Packit 0848f5
			green = 0.0;
Packit 0848f5
			blue = 1.0 - ((fraction - (dtemp*5.0)) / dtemp);
Packit 0848f5
		    }
Packit 0848f5
		}
Packit 0848f5
	    }
Packit 0848f5
	}
Packit 0848f5
    }
Packit 0848f5
Packit 0848f5
    if (intensity > 1)
Packit 0848f5
    {
Packit 0848f5
	intensity = intensity - 1.0;
Packit 0848f5
	red = red + ((1.0 - red) * intensity);
Packit 0848f5
	green = green + ((1.0 - green) * intensity);
Packit 0848f5
	blue = blue + ((1.0 - blue) * intensity);
Packit 0848f5
    }
Packit 0848f5
    else
Packit 0848f5
    {
Packit 0848f5
	red = red * intensity;
Packit 0848f5
	green = green * intensity;
Packit 0848f5
	blue = blue * intensity;
Packit 0848f5
    }
Packit 0848f5
Packit 0848f5
    r = (int)(red * 255.0);
Packit 0848f5
    g = (int)(green * 255.0);
Packit 0848f5
    b = (int)(blue * 255.0);
Packit 0848f5
Packit 0848f5
    return RGBtocolor_t(r,g,b);
Packit 0848f5
}
Packit 0848f5
Packit 0848f5
int Make_color_array(int num_colors, color_t colors[])
Packit 0848f5
{
Packit 0848f5
    double fraction, intensity;
Packit 0848f5
    int i;
Packit 0848f5
Packit 0848f5
    intensity = 1.0;
Packit 0848f5
    for (i=0; i
Packit 0848f5
    {
Packit 0848f5
	fraction = (double)i / (double)num_colors;
Packit 0848f5
	colors[i] = getColor(fraction, intensity);
Packit 0848f5
    }
Packit 0848f5
    return 0;
Packit 0848f5
}
Packit 0848f5
Packit 0848f5
void getRGB(color_t color, int *r, int *g, int *b)
Packit 0848f5
{
Packit 0848f5
    *r = getR(color);
Packit 0848f5
    *g = getG(color);
Packit 0848f5
    *b = getB(color);
Packit 0848f5
}
Packit 0848f5
Packit 0848f5
void read_mand_args(int argc, char *argv[], int *o_max_iterations,
Packit 0848f5
		    int *o_pixels_across, int *o_pixels_down,
Packit 0848f5
		    double *o_x_min, double *o_x_max,
Packit 0848f5
		    double *o_y_min, double *o_y_max, int *o_julia,
Packit 0848f5
		    double *o_julia_real_x, double *o_julia_imaginary_y,
Packit 0848f5
		    double *o_divergent_limit, int *o_alternate,
Packit 0848f5
		    char *filename, int *o_num_colors, int *use_stdin,
Packit 0848f5
		    int *save_image, int *num_children)
Packit 0848f5
{	
Packit 0848f5
    int i;
Packit 0848f5
Packit 0848f5
    *o_julia_real_x = NOVALUE;
Packit 0848f5
    *o_julia_imaginary_y = NOVALUE;
Packit 0848f5
Packit 0848f5
    /* set defaults */
Packit 0848f5
    *o_max_iterations = IDEAL_ITERATIONS;
Packit 0848f5
    *o_pixels_across = IDEAL_WIDTH;
Packit 0848f5
    *o_pixels_down = IDEAL_HEIGHT;
Packit 0848f5
    *o_x_min = IDEAL_MIN_X_VALUE;
Packit 0848f5
    *o_x_max = IDEAL_MAX_X_VALUE;
Packit 0848f5
    *o_y_min = IDEAL_MIN_Y_VALUE;
Packit 0848f5
    *o_y_max = IDEAL_MAX_Y_VALUE;
Packit 0848f5
    *o_divergent_limit = INFINITE_LIMIT;
Packit 0848f5
    strcpy(filename, default_filename);
Packit 0848f5
    *o_num_colors = IDEAL_ITERATIONS;
Packit 0848f5
    *use_stdin = 0; /* default is to listen for a controller */
Packit 0848f5
    *save_image = NOVALUE;
Packit 0848f5
Packit 0848f5
    *o_julia = 0; /* default is "generate Mandelbrot" */
Packit 0848f5
    *o_alternate = 0; /* default is still "generate Mandelbrot" */
Packit 0848f5
    *o_divergent_limit = INFINITE_LIMIT; /* default total range is assumed
Packit 0848f5
					 if not explicitly overwritten */
Packit 0848f5
Packit 0848f5
    *num_children = DEFAULT_NUM_SLAVES;
Packit 0848f5
Packit 0848f5
    /* We just cycle through all given parameters, matching what we can.
Packit 0848f5
    Note that we force casting, because we expect that a nonsensical
Packit 0848f5
    value is better than a poorly formatted one (fewer crashes), and
Packit 0848f5
    we'll later sort out the good from the bad
Packit 0848f5
    */
Packit 0848f5
Packit 0848f5
    for (i = 0; i < argc; ++i) /* grab command line arguments */
Packit 0848f5
	if (strcmp(argv[i], "-xmin\0") == 0 && argv[i+1] != NULL) 
Packit 0848f5
	    sscanf(argv[i+1], "%lf", &*o_x_min);
Packit 0848f5
	else if (strcmp(argv[i], "-xmax\0") == 0 && argv[i+1] != NULL) 
Packit 0848f5
	    sscanf(argv[i+1], "%lf", &*o_x_max);
Packit 0848f5
	else if (strcmp(argv[i], "-ymin\0") == 0 && argv[i+1] != NULL) 
Packit 0848f5
	    sscanf(argv[i+1], "%lf", &*o_y_min);
Packit 0848f5
	else if (strcmp(argv[i], "-ymax\0") == 0 && argv[i+1] != NULL) 
Packit 0848f5
	    sscanf(argv[i+1], "%lf", &*o_y_max);
Packit 0848f5
	else if (strcmp(argv[i], "-depth\0") == 0 && argv[i+1] != NULL) 
Packit 0848f5
	    sscanf(argv[i+1], "%d", &*o_max_iterations);
Packit 0848f5
	else if (strcmp(argv[i], "-xscale\0") == 0 && argv[i+1] != NULL) 
Packit 0848f5
	    sscanf(argv[i+1], "%d", &*o_pixels_across);
Packit 0848f5
	else if (strcmp(argv[i], "-yscale\0") == 0 && argv[i+1] != NULL) 
Packit 0848f5
	    sscanf(argv[i+1], "%d", &*o_pixels_down);
Packit 0848f5
	else if (strcmp(argv[i], "-diverge\0") == 0 && argv[i+1] != NULL) 
Packit 0848f5
	    sscanf(argv[i+1], "%lf", &*o_divergent_limit);
Packit 0848f5
	else if (strcmp(argv[i], "-jx\0") == 0 && argv[i+1] != NULL) 
Packit 0848f5
	    sscanf(argv[i+1], "%lf", &*o_julia_real_x);
Packit 0848f5
	else if (strcmp(argv[i], "-jy\0") == 0 && argv[i+1] != NULL) 
Packit 0848f5
	    sscanf(argv[i+1], "%lf", &*o_julia_imaginary_y);
Packit 0848f5
	else if (strcmp(argv[i], "-alternate\0") == 0 && argv[i+1] != NULL)
Packit 0848f5
	    sscanf(argv[i+1], "%d", &*o_alternate);
Packit 0848f5
	else if (strcmp(argv[i], "-julia\0") == 0)
Packit 0848f5
	    *o_julia = 1;
Packit 0848f5
	else if (strcmp(argv[i], "-out\0") == 0 && argv[i+1] != NULL)
Packit 0848f5
	    strcpy(filename, argv[i+1]);
Packit 0848f5
	else if (strcmp(argv[i], "-colors\0") == 0 && argv[i+1] != NULL)
Packit 0848f5
	    sscanf(argv[i+1], "%d", &*o_num_colors);
Packit 0848f5
	else if (strcmp(argv[i], "-i\0") == 0)
Packit 0848f5
	    *use_stdin = 1;
Packit 0848f5
	else if (strcmp(argv[i], "-save\0") == 0)
Packit 0848f5
	    *save_image = 1;
Packit 0848f5
	else if (strcmp(argv[i], "-nosave\0") == 0)
Packit 0848f5
	    *save_image = 0;
Packit 0848f5
	else if (strcmp(argv[i], "-n\0") == 0)
Packit 0848f5
	    sscanf(argv[i+1], "%d", &*num_children);
Packit 0848f5
	else if ((strcmp(argv[i], "-help\0") == 0) || (strcmp(argv[i], "-?") == 0))
Packit 0848f5
	{
Packit 0848f5
	    PrintUsage();
Packit 0848f5
	    MPI_Finalize();
Packit 0848f5
	    exit(0);
Packit 0848f5
	}
Packit 0848f5
Packit 0848f5
	if (*save_image == NOVALUE)
Packit 0848f5
	{
Packit 0848f5
	    if (*use_stdin == 1)
Packit 0848f5
		*save_image = 1;
Packit 0848f5
	    else
Packit 0848f5
		*save_image = 0;
Packit 0848f5
	}
Packit 0848f5
#if DEBUG2
Packit 0848f5
	if (myid == 0)
Packit 0848f5
	{
Packit 0848f5
	    printf("Doing %d iterations over (%.2lf:%.2lf,%.2lf:%.2lf) on a %d x %d grid\n",
Packit 0848f5
		*o_max_iterations, *o_x_min,*o_x_max,*o_y_min,*o_y_max,
Packit 0848f5
		*o_pixels_across, *o_pixels_down);
Packit 0848f5
	}
Packit 0848f5
#endif
Packit 0848f5
}
Packit 0848f5
Packit 0848f5
void check_mand_params(int *m_max_iterations,
Packit 0848f5
		       int *m_pixels_across, int *m_pixels_down,
Packit 0848f5
		       double *m_x_min, double *m_x_max,
Packit 0848f5
		       double *m_y_min, double *m_y_max,
Packit 0848f5
		       double *m_divergent_limit,
Packit 0848f5
		       int *m_num_children)
Packit 0848f5
{
Packit 0848f5
    /* Get first batch of limits */
Packit 0848f5
#if PROMPT
Packit 0848f5
    if (*m_x_min == NOVALUE || *m_x_max == NOVALUE)
Packit 0848f5
    {
Packit 0848f5
	/* grab unspecified limits */
Packit 0848f5
	printf("Enter lower and higher limits on x (within -1 to 1): ");
Packit 0848f5
	scanf("%lf %lf", &*m_x_min, &*m_x_max);
Packit 0848f5
    }
Packit 0848f5
Packit 0848f5
    if (*m_y_min == NOVALUE || *m_y_max == NOVALUE)
Packit 0848f5
    {
Packit 0848f5
	/* grab unspecified limits */
Packit 0848f5
	printf("Enter lower and higher limits on y (within -1 to 1): ");
Packit 0848f5
	scanf("%lf %lf", &*m_y_min, &*m_y_max);
Packit 0848f5
    }
Packit 0848f5
#endif
Packit 0848f5
Packit 0848f5
    /* Verify limits are reasonable */
Packit 0848f5
Packit 0848f5
    if (*m_x_min < MIN_X_VALUE || *m_x_min > *m_x_max)
Packit 0848f5
    {
Packit 0848f5
	printf("Chosen lower x limit is too low, resetting to %lf\n",MIN_X_VALUE);
Packit 0848f5
	*m_x_min = MIN_X_VALUE;
Packit 0848f5
    }
Packit 0848f5
    if (*m_x_max > MAX_X_VALUE || *m_x_max <= *m_x_min)
Packit 0848f5
    {
Packit 0848f5
	printf("Chosen upper x limit is too high, resetting to %lf\n",MAX_X_VALUE);
Packit 0848f5
	*m_x_max = MAX_X_VALUE;
Packit 0848f5
    }
Packit 0848f5
    if (*m_y_min < MIN_Y_VALUE || *m_y_min > *m_y_max)
Packit 0848f5
    {
Packit 0848f5
	printf("Chosen lower y limit is too low, resetting to %lf\n",MIN_Y_VALUE);
Packit 0848f5
	*m_y_min = MIN_Y_VALUE;
Packit 0848f5
    }
Packit 0848f5
    if (*m_y_max > MAX_Y_VALUE || *m_y_max <= *m_y_min)
Packit 0848f5
    {
Packit 0848f5
	printf("Chosen upper y limit is too high, resetting to %lf\n",MAX_Y_VALUE);
Packit 0848f5
	*m_y_max = MAX_Y_VALUE;
Packit 0848f5
    }
Packit 0848f5
Packit 0848f5
    /* Get second set of limits */
Packit 0848f5
#if PROMPT
Packit 0848f5
Packit 0848f5
    if (*m_max_iterations == NOVALUE)
Packit 0848f5
    {
Packit 0848f5
	/* grab unspecified limit */
Packit 0848f5
	printf("Enter max interations to do: ");
Packit 0848f5
	scanf("%d",&*m_max_iterations);
Packit 0848f5
    }
Packit 0848f5
#endif
Packit 0848f5
Packit 0848f5
    /* Verify second set of limits */
Packit 0848f5
Packit 0848f5
    if (*m_max_iterations > MAX_ITERATIONS || *m_max_iterations < 0)
Packit 0848f5
    {
Packit 0848f5
	printf("Warning, unreasonable number of iterations, setting to %d\n", MAX_ITERATIONS);
Packit 0848f5
	*m_max_iterations = MAX_ITERATIONS;
Packit 0848f5
    }
Packit 0848f5
Packit 0848f5
    /* Get third set of limits */
Packit 0848f5
#if PROMPT
Packit 0848f5
    if (*m_pixels_across == NOVALUE || *m_pixels_down == NOVALUE)
Packit 0848f5
    {
Packit 0848f5
	/* grab unspecified limits */
Packit 0848f5
	printf("Enter pixel size (horizonal by vertical, i.e. 256 256): ");
Packit 0848f5
	scanf(" %d %d", &*m_pixels_across, &*m_pixels_down);
Packit 0848f5
    }
Packit 0848f5
#endif
Packit 0848f5
Packit 0848f5
    /* Verify third set of limits */
Packit 0848f5
Packit 0848f5
    if (*m_pixels_across > MAX_WIDTH)
Packit 0848f5
    {
Packit 0848f5
	printf("Warning, image requested is too wide, setting to %d pixel width\n", MAX_WIDTH);
Packit 0848f5
	*m_pixels_across = MAX_WIDTH;
Packit 0848f5
    }
Packit 0848f5
    if (*m_pixels_down > MAX_HEIGHT)
Packit 0848f5
    {
Packit 0848f5
	printf("Warning, image requested is too tall, setting to %d pixel height\n", MAX_HEIGHT);
Packit 0848f5
	*m_pixels_down = MAX_HEIGHT;
Packit 0848f5
    }
Packit 0848f5
Packit 0848f5
    if (*m_num_children < 1)
Packit 0848f5
    {
Packit 0848f5
	printf("Error, invalid number of slaves (%d), setting to %d\n", *m_num_children, DEFAULT_NUM_SLAVES);
Packit 0848f5
	*m_num_children = DEFAULT_NUM_SLAVES;
Packit 0848f5
    }
Packit 0848f5
    if (*m_num_children > 400)
Packit 0848f5
    {
Packit 0848f5
	printf("Error, number of slaves (%d) exceeds the maximum, setting to 400.\n", *m_num_children);
Packit 0848f5
	*m_num_children = 400;
Packit 0848f5
    }
Packit 0848f5
Packit 0848f5
#if DEBUG2
Packit 0848f5
    printf("%d iterations over (%.2lf:%.2lf,%.2lf:%.2lf), %d x %d grid, diverge value %lf\n",
Packit 0848f5
	*m_max_iterations, *m_x_min,*m_x_max,*m_y_min,*m_y_max,
Packit 0848f5
	*m_pixels_across, *m_pixels_down, *m_divergent_limit);
Packit 0848f5
#endif
Packit 0848f5
}
Packit 0848f5
Packit 0848f5
void check_julia_params(double *julia_x_constant, double *julia_y_constant)
Packit 0848f5
{	
Packit 0848f5
Packit 0848f5
    /* Hey, we're not stupid-- if they must Prompt, we will also be Noisy */
Packit 0848f5
#if PROMPT
Packit 0848f5
    if (*julia_x_constant == NOVALUE || *julia_y_constant == NOVALUE)
Packit 0848f5
    {
Packit 0848f5
	/* grab unspecified limits */
Packit 0848f5
	printf("Enter Coordinates for Julia expansion: ");
Packit 0848f5
	scanf("%lf %lf", &*julia_x_constant, &*julia_y_constant);
Packit 0848f5
    }
Packit 0848f5
#endif
Packit 0848f5
Packit 0848f5
#if DEBUG2
Packit 0848f5
    /* In theory, any point can be investigated, although it's not much point
Packit 0848f5
    if it's outside of the area viewed.  But, hey, that's not our problem */
Packit 0848f5
    printf("Exploring julia set around (%lf, %lf)\n", *julia_x_constant, *julia_y_constant);
Packit 0848f5
#endif
Packit 0848f5
}
Packit 0848f5
Packit 0848f5
/* This is a Mandelbrot variant, solving the code for the equation:
Packit 0848f5
z = z(1-z)
Packit 0848f5
*/
Packit 0848f5
Packit 0848f5
/* This routine takes a complex coordinate point (x+iy) and a value stating
Packit 0848f5
what the upper limit to the number of iterations is.  It eventually
Packit 0848f5
returns an integer of how many counts the code iterated for within
Packit 0848f5
the given point/region until the exit condition ( abs(x+iy) > limit) was met.
Packit 0848f5
This value is returned as an integer.
Packit 0848f5
*/
Packit 0848f5
Packit 0848f5
int subtractive_mandelbrot_point(complex_t coord_point, 
Packit 0848f5
				 complex_t c_constant,
Packit 0848f5
				 int Max_iterations, double divergent_limit)
Packit 0848f5
{
Packit 0848f5
    complex_t z_point, a_point; /* we need 2 pts to use in our calculation */
Packit 0848f5
    int num_iterations;  /* a counter to track the number of iterations done */
Packit 0848f5
Packit 0848f5
    num_iterations = 0; /* zero our counter */
Packit 0848f5
    z_point = coord_point; /* initialize to the given start coordinate */
Packit 0848f5
Packit 0848f5
    /* loop while the absolute value of the complex coordinate is < our limit
Packit 0848f5
    (for a mandelbrot) or until we've done our specified maximum number of
Packit 0848f5
    iterations (both julia and mandelbrot) */
Packit 0848f5
Packit 0848f5
    while (absolute_complex(z_point) < divergent_limit &&
Packit 0848f5
	num_iterations < Max_iterations)
Packit 0848f5
    {
Packit 0848f5
	/* z = z(1-z) */
Packit 0848f5
	a_point.real = 1.0; a_point.imaginary = 0.0; /* make "1" */
Packit 0848f5
	a_point = subtract_complex(a_point,z_point);
Packit 0848f5
	z_point = multiply_complex(z_point,a_point);
Packit 0848f5
Packit 0848f5
	++num_iterations;
Packit 0848f5
    } /* done iterating for one point */
Packit 0848f5
Packit 0848f5
    return num_iterations;
Packit 0848f5
}
Packit 0848f5
Packit 0848f5
/* This is a Mandelbrot variant, solving the code for the equation:
Packit 0848f5
z = z(z+c)
Packit 0848f5
*/
Packit 0848f5
Packit 0848f5
/* This routine takes a complex coordinate point (x+iy) and a value stating
Packit 0848f5
what the upper limit to the number of iterations is.  It eventually
Packit 0848f5
returns an integer of how many counts the code iterated for within
Packit 0848f5
the given point/region until the exit condition ( abs(x+iy) > limit) was met.
Packit 0848f5
This value is returned as an integer.
Packit 0848f5
*/
Packit 0848f5
Packit 0848f5
int additive_mandelbrot_point(complex_t coord_point, 
Packit 0848f5
			      complex_t c_constant,
Packit 0848f5
			      int Max_iterations, double divergent_limit)
Packit 0848f5
{
Packit 0848f5
    complex_t z_point, a_point; /* we need 2 pts to use in our calculation */
Packit 0848f5
    int num_iterations;  /* a counter to track the number of iterations done */
Packit 0848f5
Packit 0848f5
    num_iterations = 0; /* zero our counter */
Packit 0848f5
    z_point = coord_point; /* initialize to the given start coordinate */
Packit 0848f5
Packit 0848f5
    /* loop while the absolute value of the complex coordinate is < our limit
Packit 0848f5
    (for a mandelbrot) or until we've done our specified maximum number of
Packit 0848f5
    iterations (both julia and mandelbrot) */
Packit 0848f5
Packit 0848f5
    while (absolute_complex(z_point) < divergent_limit &&
Packit 0848f5
	num_iterations < Max_iterations)
Packit 0848f5
    {
Packit 0848f5
	/* z = z(z+C) */
Packit 0848f5
	a_point = add_complex(z_point,coord_point);
Packit 0848f5
	z_point = multiply_complex(z_point,a_point);
Packit 0848f5
Packit 0848f5
	++num_iterations;
Packit 0848f5
    } /* done iterating for one point */
Packit 0848f5
Packit 0848f5
    return num_iterations;
Packit 0848f5
}
Packit 0848f5
Packit 0848f5
/* This is a Mandelbrot variant, solving the code for the equation:
Packit 0848f5
z = z(z+1)
Packit 0848f5
*/
Packit 0848f5
Packit 0848f5
/* This routine takes a complex coordinate point (x+iy) and a value stating
Packit 0848f5
what the upper limit to the number of iterations is.  It eventually
Packit 0848f5
returns an integer of how many counts the code iterated for within
Packit 0848f5
the given point/region until the exit condition ( abs(x+iy) > limit) was met.
Packit 0848f5
This value is returned as an integer.
Packit 0848f5
*/
Packit 0848f5
Packit 0848f5
int exponential_mandelbrot_point(complex_t coord_point, 
Packit 0848f5
				 complex_t c_constant,
Packit 0848f5
				 int Max_iterations, double divergent_limit)
Packit 0848f5
{
Packit 0848f5
    complex_t z_point, a_point; /* we need 2 pts to use in our calculation */
Packit 0848f5
    int num_iterations;  /* a counter to track the number of iterations done */
Packit 0848f5
Packit 0848f5
    num_iterations = 0; /* zero our counter */
Packit 0848f5
    z_point = coord_point; /* initialize to the given start coordinate */
Packit 0848f5
Packit 0848f5
    /* loop while the absolute value of the complex coordinate is < our limit
Packit 0848f5
    (for a mandelbrot) or until we've done our specified maximum number of
Packit 0848f5
    iterations (both julia and mandelbrot) */
Packit 0848f5
Packit 0848f5
    while (absolute_complex(z_point) < divergent_limit &&
Packit 0848f5
	num_iterations < Max_iterations)
Packit 0848f5
    {
Packit 0848f5
	/* z = z(1-z) */
Packit 0848f5
	a_point.real = 1.0; a_point.imaginary = 0.0; /* make "1" */
Packit 0848f5
	a_point = subtract_complex(a_point,z_point);
Packit 0848f5
	z_point = multiply_complex(z_point,a_point);
Packit 0848f5
Packit 0848f5
	++num_iterations;
Packit 0848f5
    } /* done iterating for one point */
Packit 0848f5
Packit 0848f5
    return num_iterations;
Packit 0848f5
}
Packit 0848f5
Packit 0848f5
void complex_points_to_image(complex_t in_julia_coord_set[],
Packit 0848f5
			     int in_julia_set_size,
Packit 0848f5
			     int i_pixels_across,int i_pixels_down,
Packit 0848f5
			     int *out_image_final, int *out_max_colors)
Packit 0848f5
{
Packit 0848f5
    int i, i_temp_quantize;
Packit 0848f5
    double x_resolution_element, y_resolution_element, temp_quantize;
Packit 0848f5
    double x_max, x_min, y_max, y_min;
Packit 0848f5
Packit 0848f5
    /* Convert the complex points into an image--
Packit 0848f5
Packit 0848f5
    first, find the min and max for each axis. */
Packit 0848f5
Packit 0848f5
    x_min = in_julia_coord_set[0].real;
Packit 0848f5
    x_max = x_min;
Packit 0848f5
    y_min = in_julia_coord_set[0].imaginary;
Packit 0848f5
    y_max = y_min;
Packit 0848f5
Packit 0848f5
    for (i=0;i
Packit 0848f5
    {
Packit 0848f5
	if (in_julia_coord_set[i].real < x_min)
Packit 0848f5
	    x_min = in_julia_coord_set[i].real;
Packit 0848f5
	if (in_julia_coord_set[i].real > x_max)
Packit 0848f5
	    x_max = in_julia_coord_set[i].real;
Packit 0848f5
	if (in_julia_coord_set[i].imaginary < y_min)
Packit 0848f5
	    y_min = in_julia_coord_set[i].imaginary;
Packit 0848f5
	if (in_julia_coord_set[i].imaginary > y_max)
Packit 0848f5
	    y_max = in_julia_coord_set[i].imaginary;
Packit 0848f5
    }
Packit 0848f5
Packit 0848f5
    /* convert to fit image grid size: */
Packit 0848f5
Packit 0848f5
    x_resolution_element =  (x_max - x_min)/(double)i_pixels_across;
Packit 0848f5
    y_resolution_element =  (y_max - y_min)/(double)i_pixels_down;
Packit 0848f5
Packit 0848f5
#ifdef DEBUG
Packit 0848f5
    printf("%lf %lf\n",x_resolution_element, y_resolution_element);
Packit 0848f5
#endif
Packit 0848f5
Packit 0848f5
Packit 0848f5
    /* now we can put each point into a grid space, and up the count of
Packit 0848f5
    said grid.  Since calloc initialized it to zero, this is safe */
Packit 0848f5
    /* A point x,y goes to grid region i,j, where
Packit 0848f5
    xi =  (x-xmin)/x_resolution   (position relative to far left)
Packit 0848f5
    yj =  (ymax-y)/y_resolution   (position relative to top)
Packit 0848f5
    This gets mapped to our 1-d array as  xi + yj*i_pixels_across,
Packit 0848f5
    taken as an integer (rounding down) and checking array limits
Packit 0848f5
    */
Packit 0848f5
Packit 0848f5
    for (i=0; i
Packit 0848f5
    {
Packit 0848f5
	temp_quantize =
Packit 0848f5
	    (in_julia_coord_set[i].real - x_min)/x_resolution_element +
Packit 0848f5
	    (y_max -  in_julia_coord_set[i].imaginary)/y_resolution_element *
Packit 0848f5
	    (double)i_pixels_across;
Packit 0848f5
	i_temp_quantize = (int)temp_quantize;
Packit 0848f5
	if (i_temp_quantize > i_pixels_across*i_pixels_down)
Packit 0848f5
	    i_temp_quantize = i_pixels_across*i_pixels_down;
Packit 0848f5
Packit 0848f5
#ifdef DEBUG
Packit 0848f5
	printf("%d %lf %lf %lf %lf %lf %lf %lf\n",
Packit 0848f5
	    i_temp_quantize, temp_quantize, x_min, x_resolution_element,
Packit 0848f5
	    in_julia_coord_set[i].real, y_max, y_resolution_element,
Packit 0848f5
	    in_julia_coord_set[i].imaginary);
Packit 0848f5
#endif
Packit 0848f5
Packit 0848f5
	++out_image_final[i_temp_quantize];
Packit 0848f5
    }
Packit 0848f5
Packit 0848f5
    /* find the highest value (most occupied bin) */
Packit 0848f5
    *out_max_colors = 0;
Packit 0848f5
    for (i=0;i
Packit 0848f5
    {
Packit 0848f5
	if (out_image_final[i] > *out_max_colors)
Packit 0848f5
	{
Packit 0848f5
	    *out_max_colors = out_image_final[i];
Packit 0848f5
	}
Packit 0848f5
    }
Packit 0848f5
}
Packit 0848f5
Packit 0848f5
complex_t exponential_complex(complex_t in_complex)
Packit 0848f5
{
Packit 0848f5
    complex_t out_complex;
Packit 0848f5
    double e_to_x;
Packit 0848f5
    /* taking the exponential,   e^(x+iy) = e^xe^iy = e^x(cos(y)+isin(y) */
Packit 0848f5
    e_to_x = exp(in_complex.real);
Packit 0848f5
    out_complex.real = e_to_x * cos(in_complex.imaginary);
Packit 0848f5
    out_complex.imaginary = e_to_x * sin(in_complex.imaginary);
Packit 0848f5
    return out_complex;
Packit 0848f5
}
Packit 0848f5
Packit 0848f5
complex_t multiply_complex(complex_t in_one_complex, complex_t in_two_complex)
Packit 0848f5
{
Packit 0848f5
    complex_t out_complex;
Packit 0848f5
    /* multiplying complex variables-- (x+iy) * (a+ib) = xa - yb + i(xb + ya) */
Packit 0848f5
    out_complex.real = in_one_complex.real * in_two_complex.real -
Packit 0848f5
	in_one_complex.imaginary * in_two_complex.imaginary;
Packit 0848f5
    out_complex.imaginary = in_one_complex.real * in_two_complex.imaginary +
Packit 0848f5
	in_one_complex.imaginary * in_two_complex.real;
Packit 0848f5
    return out_complex;
Packit 0848f5
}
Packit 0848f5
Packit 0848f5
complex_t divide_complex(complex_t in_one_complex, complex_t in_two_complex)
Packit 0848f5
{
Packit 0848f5
    complex_t out_complex;
Packit 0848f5
    double divider;
Packit 0848f5
    /* dividing complex variables-- (x+iy)/(a+ib) = (xa - yb)/(a^2+b^2)
Packit 0848f5
    + i (y*a-x*b)/(a^2+b^2) */
Packit 0848f5
    divider = (in_two_complex.real*in_two_complex.real -
Packit 0848f5
	in_two_complex.imaginary*in_two_complex.imaginary);
Packit 0848f5
    out_complex.real = (in_one_complex.real * in_two_complex.real -
Packit 0848f5
	in_one_complex.imaginary * in_two_complex.imaginary) / divider;
Packit 0848f5
    out_complex.imaginary = (in_one_complex.imaginary * in_two_complex.real -
Packit 0848f5
	in_one_complex.real * in_two_complex.imaginary) / divider;
Packit 0848f5
    return out_complex;
Packit 0848f5
}
Packit 0848f5
Packit 0848f5
complex_t inverse_complex(complex_t in_complex)
Packit 0848f5
{
Packit 0848f5
    complex_t out_complex;
Packit 0848f5
    double divider;
Packit 0848f5
    /* inverting a complex variable: 1/(x+iy) */
Packit 0848f5
    divider = (in_complex.real*in_complex.real -
Packit 0848f5
	in_complex.imaginary*in_complex.imaginary);
Packit 0848f5
    out_complex.real = (in_complex.real - in_complex.imaginary) / divider;
Packit 0848f5
    out_complex.imaginary = (in_complex.real - in_complex.imaginary) / divider;
Packit 0848f5
    return out_complex;
Packit 0848f5
}
Packit 0848f5
Packit 0848f5
complex_t add_complex(complex_t in_one_complex, complex_t in_two_complex)
Packit 0848f5
{
Packit 0848f5
    complex_t out_complex;
Packit 0848f5
    /* adding complex variables-- do by component */
Packit 0848f5
    out_complex.real = in_one_complex.real + in_two_complex.real;
Packit 0848f5
    out_complex.imaginary = in_one_complex.imaginary + in_two_complex.imaginary;
Packit 0848f5
    return out_complex;
Packit 0848f5
}
Packit 0848f5
Packit 0848f5
complex_t subtract_complex(complex_t in_one_complex, complex_t in_two_complex)
Packit 0848f5
{
Packit 0848f5
    complex_t out_complex;
Packit 0848f5
    /* subtracting complex variables-- do by component */
Packit 0848f5
    out_complex.real = in_one_complex.real - in_two_complex.real;
Packit 0848f5
    out_complex.imaginary = in_one_complex.imaginary - in_two_complex.imaginary;
Packit 0848f5
    return out_complex;
Packit 0848f5
}
Packit 0848f5
Packit 0848f5
double absolute_complex(complex_t in_complex)
Packit 0848f5
{
Packit 0848f5
    double out_double;
Packit 0848f5
    /* absolute value is (for x+yi)  sqrt( x^2 + y^2) */
Packit 0848f5
    out_double = sqrt(in_complex.real*in_complex.real + in_complex.imaginary*in_complex.imaginary);
Packit 0848f5
    return out_double;
Packit 0848f5
}
Packit 0848f5
Packit 0848f5
/* This routine takes a complex coordinate point (x+iy) and a value stating
Packit 0848f5
what the upper limit to the number of iterations is.  It eventually
Packit 0848f5
returns an integer of how many counts the code iterated for within
Packit 0848f5
the given point/region until the exit condition ( abs(x+iy) > limit) was met.
Packit 0848f5
This value is returned as an integer.
Packit 0848f5
*/
Packit 0848f5
Packit 0848f5
int single_mandelbrot_point(complex_t coord_point, 
Packit 0848f5
			    complex_t c_constant,
Packit 0848f5
			    int Max_iterations, double divergent_limit)
Packit 0848f5
{
Packit 0848f5
    complex_t z_point;  /* we need a point to use in our calculation */
Packit 0848f5
    int num_iterations;  /* a counter to track the number of iterations done */
Packit 0848f5
Packit 0848f5
    num_iterations = 0; /* zero our counter */
Packit 0848f5
    z_point = coord_point; /* initialize to the given start coordinate */
Packit 0848f5
Packit 0848f5
    /* loop while the absolute value of the complex coordinate is < our limit
Packit 0848f5
    (for a mandelbrot) or until we've done our specified maximum number of
Packit 0848f5
    iterations (both julia and mandelbrot) */
Packit 0848f5
Packit 0848f5
    while (absolute_complex(z_point) < divergent_limit &&
Packit 0848f5
	num_iterations < Max_iterations)
Packit 0848f5
    {
Packit 0848f5
	/* z = z*z + c */
Packit 0848f5
	z_point = multiply_complex(z_point,z_point);
Packit 0848f5
	z_point = add_complex(z_point,c_constant);
Packit 0848f5
Packit 0848f5
	++num_iterations;
Packit 0848f5
    } /* done iterating for one point */
Packit 0848f5
Packit 0848f5
    return num_iterations;
Packit 0848f5
}
Packit 0848f5
Packit 0848f5
void output_data(int *in_grid_array, int coord[4], int *out_grid_array, int width, int height)
Packit 0848f5
{
Packit 0848f5
    int i, j, k;
Packit 0848f5
    k = 0;
Packit 0848f5
    for (j=coord[2]; j<=coord[3]; j++)
Packit 0848f5
    {
Packit 0848f5
	for (i=coord[0]; i<=coord[1]; i++)
Packit 0848f5
	{
Packit 0848f5
	    out_grid_array[(j * height) + i] = in_grid_array[k];
Packit 0848f5
	    k++;
Packit 0848f5
	}
Packit 0848f5
    }
Packit 0848f5
    if (!use_stdin)
Packit 0848f5
    {
Packit 0848f5
	sock_write(sock, coord, 4 * sizeof(int));
Packit 0848f5
	sock_write(sock, in_grid_array, ((coord[1] + 1 - coord[0]) * (coord[3] + 1 - coord[2])) * sizeof(int));
Packit 0848f5
	/* send the data to the visualizer */
Packit 0848f5
    }
Packit 0848f5
}
Packit 0848f5
Packit 0848f5
/* Writes out a linear integer array of grayscale pixel values to a
Packit 0848f5
pgm-format file (with header).  The exact format details are given
Packit 0848f5
at the end of this routine in case you don't have the man pages
Packit 0848f5
installed locally.  Essentially, it's a 2-dimensional integer array
Packit 0848f5
of pixel grayscale values.  Very easy to manipulate externally.
Packit 0848f5
*/
Packit 0848f5
Packit 0848f5
/* You need the following inputs:
Packit 0848f5
A linear integer array with the actual pixel values (read in as
Packit 0848f5
consecutive rows),
Packit 0848f5
The width and height of the grid, and
Packit 0848f5
The maximum pixel value (to set greyscale range).  We are assuming
Packit 0848f5
that the lowest value is "0".
Packit 0848f5
*/
Packit 0848f5
Packit 0848f5
void dumpimage(char *filename, int in_grid_array[], int in_pixels_across, int in_pixels_down,
Packit 0848f5
	       int in_max_pixel_value, char input_string[], int num_colors, color_t colors[])
Packit 0848f5
{
Packit 0848f5
    FILE *ifp;
Packit 0848f5
    int i, j, k;
Packit 0848f5
#ifdef USE_PPM
Packit 0848f5
    int r, g, b;
Packit 0848f5
#endif
Packit 0848f5
Packit 0848f5
    printf("%s\nwidth: %d\nheight: %d\ncolors: %d\nstr: %s\n",
Packit 0848f5
	filename, in_pixels_across, in_pixels_down, num_colors, input_string);
Packit 0848f5
    fflush(stdout);
Packit 0848f5
Packit 0848f5
    if ( (ifp=fopen(filename, "w")) == NULL)
Packit 0848f5
    {
Packit 0848f5
	printf("Error, could not open output file\n");
Packit 0848f5
	MPI_Abort(MPI_COMM_WORLD, -1);
Packit 0848f5
	exit(-1);
Packit 0848f5
    }
Packit 0848f5
Packit 0848f5
#ifdef USE_PPM
Packit 0848f5
    fprintf(ifp, "P3\n");  /* specifies type of file, in this case ppm */
Packit 0848f5
    fprintf(ifp, "# %s\n", input_string);  /* an arbitrary file identifier */
Packit 0848f5
    /* now give the file size in pixels by pixels */
Packit 0848f5
    fprintf(ifp, "%d %d\n", in_pixels_across, in_pixels_down);
Packit 0848f5
    /* give the max r,g,b level */
Packit 0848f5
    fprintf(ifp, "255\n");
Packit 0848f5
Packit 0848f5
    k=0; /* counter for the linear array of the final image */
Packit 0848f5
    /* assumes first point is upper left corner (element 0 of array) */
Packit 0848f5
Packit 0848f5
    if (in_max_pixel_value < 1)
Packit 0848f5
    {
Packit 0848f5
	for (j=0; j
Packit 0848f5
	{
Packit 0848f5
	    for (i=0; i
Packit 0848f5
	    {
Packit 0848f5
		fprintf(ifp, "0 0 0 ");
Packit 0848f5
	    }
Packit 0848f5
	    fprintf(ifp, "\n"); /* done writing one row, begin next line */
Packit 0848f5
	}
Packit 0848f5
    }
Packit 0848f5
    else
Packit 0848f5
    {
Packit 0848f5
	for (j=0; j
Packit 0848f5
	{
Packit 0848f5
	    for (i=0; i
Packit 0848f5
	    {
Packit 0848f5
		getRGB(colors[(in_grid_array[k] * num_colors) / in_max_pixel_value], &r, &g, &b);
Packit 0848f5
		fprintf(ifp, "%d %d %d ", r, g, b); /* +1 since 0 = first color */
Packit 0848f5
		++k;
Packit 0848f5
	    }
Packit 0848f5
	    fprintf(ifp, "\n"); /* done writing one row, begin next line */
Packit 0848f5
	}
Packit 0848f5
    }
Packit 0848f5
#else
Packit 0848f5
    fprintf(ifp, "P2\n");  /* specifies type of file, in this case pgm */
Packit 0848f5
    fprintf(ifp, "# %s\n", input_string);  /* an arbitrary file identifier */
Packit 0848f5
    /* now give the file size in pixels by pixels */
Packit 0848f5
    fprintf(ifp, "%d %d\n", in_pixels_across, in_pixels_down);
Packit 0848f5
    /* gives max number of grayscale levels */
Packit 0848f5
    fprintf(ifp, "%d\n", in_max_pixel_value+1); /* plus 1 because 0=first color */
Packit 0848f5
Packit 0848f5
    k=0; /* counter for the linear array of the final image */
Packit 0848f5
    /* assumes first point is upper left corner (element 0 of array) */
Packit 0848f5
Packit 0848f5
    for (j=0;j
Packit 0848f5
    {
Packit 0848f5
	for (i=0;i
Packit 0848f5
	{
Packit 0848f5
	    fprintf(ifp, "%d ", in_grid_array[k]+1); /* +1 since 0 = first color */
Packit 0848f5
	    ++k;
Packit 0848f5
	}
Packit 0848f5
	fprintf(ifp, "\n"); /* done writing one row, begin next line */
Packit 0848f5
    }
Packit 0848f5
#endif
Packit 0848f5
Packit 0848f5
    fclose(ifp);
Packit 0848f5
}
Packit 0848f5
Packit 0848f5
Packit 0848f5
Packit 0848f5
/*
Packit 0848f5
The portable graymap format is a lowest  common  denominator
Packit 0848f5
grayscale file format.  The definition is as follows:
Packit 0848f5
Packit 0848f5
- A "magic number" for identifying the  file  type.   A  pgm
Packit 0848f5
file's magic number is the two characters "P2".
Packit 0848f5
Packit 0848f5
- Whitespace (blanks, TABs, CRs, LFs).
Packit 0848f5
Packit 0848f5
- A width, formatted as ASCII characters in decimal.
Packit 0848f5
Packit 0848f5
- Whitespace.
Packit 0848f5
- A height, again in ASCII decimal.
Packit 0848f5
Packit 0848f5
- Whitespace.
Packit 0848f5
Packit 0848f5
- The maximum gray value, again in ASCII decimal.
Packit 0848f5
Packit 0848f5
- Whitespace.
Packit 0848f5
Packit 0848f5
- Width * height gray values, each in ASCII decimal, between
Packit 0848f5
0  and  the  specified  maximum  value,  separated by whi-
Packit 0848f5
tespace, starting at the top-left corner of  the  graymap,
Packit 0848f5
proceding  in  normal English reading order.  A value of 0
Packit 0848f5
means black, and the maximum value means white.
Packit 0848f5
Packit 0848f5
- Characters from a "#" to the next end-of-line are  ignored
Packit 0848f5
(comments).
Packit 0848f5
Packit 0848f5
- No line should be longer than 70 characters.
Packit 0848f5
Packit 0848f5
Here is an example of a small graymap in this format:
Packit 0848f5
Packit 0848f5
P2
Packit 0848f5
# feep.pgm
Packit 0848f5
24 7
Packit 0848f5
15
Packit 0848f5
0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
Packit 0848f5
0  3  3  3  3  0  0  7  7  7  7  0  0 11 11 11 11  0  0 15 15 15 15  0
Packit 0848f5
0  3  0  0  0  0  0  7  0  0  0  0  0 11  0  0  0  0  0 15  0  0 15  0
Packit 0848f5
0  3  3  3  0  0  0  7  7  7  0  0  0 11 11 11  0  0  0 15 15 15 15  0
Packit 0848f5
0  3  0  0  0  0  0  7  0  0  0  0  0 11  0  0  0  0  0 15  0  0  0  0
Packit 0848f5
0  3  0  0  0  0  0  7  7  7  7  0  0 11 11 11 11  0  0 15  0  0  0  0
Packit 0848f5
0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
Packit 0848f5
*/