Blame examples/pmandel_spawn.c

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