/* Sequential Mandelbrot program This program computes and displays the Mandelbrot set. Usage: mandelbrot maxiter width height where "maxiter" denotes the maximum number of iterations at each point (default MAX_ITER) "width" denotes the width of the display window, in pixels (default X_RESN) "height" denotes the height of the display window, in pixels (default Y_RESN) and all three arguments are optional. Input: none, except the optional command-line arguments Output: a graphical display as described in Wilkinson & Allen, displayed using the X Window system, plus text output to standard output showing the above parameters, plus execution time in seconds Original code obtained from Web site for Wilkinson and Allen's text on parallel programming: http://www.cs.uncc.edu/~abw/parallel/par_prog/ Reformatted and revised by B. Massingill, Jan 2001 */ #include #include #include #include #include #include #include #include #include #define X_RESN 800 /* default window width */ #define Y_RESN 800 /* default window height */ #define MAX_ITER 100 /* default max iterations */ /* region to display */ #define REAL_MIN -2 #define IMAG_MIN -2 #define REAL_MAX 2 #define IMAG_MAX 2 typedef struct complextype { float real, imag; } Compl; /* ---- Main program ------------------------------------------------ */ int main (int argc, char *argv[]) { /* Variables for graphical display */ Window win; /* initialization for a window */ unsigned int width = 0, height = 0, /* window size */ x, y, /* window position */ border_width, /* border width in pixels */ disp_width, disp_height, /* size of screen */ screen; /* which screen */ char *window_name = "Mandelbrot Set", *disp_name = NULL; GC gc; unsigned long valuemask = 0; XGCValues values; Display *display; XSizeHints size_hints; /* variable from original code, apparently unused */ /* Pixmap bitmap; */ /* XPoint points[800]; */ /* FILE *fp, *fopen (); */ /* char str[100]; */ XSetWindowAttributes attr[1]; unsigned long white, black, /* white, black pixel values */ min_color, max_color, /* min, max values for color */ color; float scale_real, scale_imag; /* scaling factors to map region to window */ /* Mandelbrot variables */ int maxiter = 0; /* maximum iterations */ int i, j, k; Compl z, c; float lengthsq, temp; /* Miscellaneous variables */ char dummy; /* do a scanf into this variable at end as a way to pause before exit */ struct tms t; /* for computing execution time */ /* Process command-line arguments, if any */ /* Usage is: mandelbrot [maxiter] [width] [height] or mandelbrot -h to show usage message */ if ((argc > 1) && (strcmp(argv[1], "-h") == 0)) { fprintf (stderr, "Usage: mandelbrot [maxiter] [width] [height]\n"); exit (EXIT_FAILURE); } if (argc > 1) maxiter = atoi(argv[1]); if (argc > 2) width = atoi(argv[2]); if (argc > 3) height = atoi(argv[3]); maxiter = (maxiter > 0) ? maxiter : MAX_ITER; width = (width > 0) ? width : X_RESN; height = (height > 0) ? height : Y_RESN; /* Connect to Xserver */ if ( (display = XOpenDisplay (disp_name)) == NULL ) { fprintf (stderr, "drawon: cannot connect to X server %s\n", XDisplayName (disp_name) ); exit (EXIT_FAILURE); } /* Initialize for graphical display */ screen = DefaultScreen (display); disp_width = DisplayWidth (display, screen); disp_height = DisplayHeight (display, screen); x = 0; y = 0; /* window position */ border_width = 4; win = XCreateSimpleWindow (display, RootWindow (display, screen), x, y, width, height, border_width, BlackPixel (display, screen), WhitePixel (display, screen)); size_hints.flags = USPosition|USSize; size_hints.x = x; size_hints.y = y; size_hints.width = width; size_hints.height = height; size_hints.min_width = 300; size_hints.min_height = 300; XSetNormalHints (display, win, &size_hints); XStoreName(display, win, window_name); /* graphics context */ gc = XCreateGC (display, win, valuemask, &values); /* color values for white, black */ white = WhitePixel (display, screen); black = BlackPixel (display, screen); XSetBackground (display, gc, white); XSetForeground (display, gc, black); XSetLineAttributes (display, gc, 1, LineSolid, CapRound, JoinRound); attr[0].backing_store = Always; attr[0].backing_planes = 1; attr[0].backing_pixel = black; XChangeWindowAttributes(display, win, CWBackingStore | CWBackingPlanes | CWBackingPixel, attr); XMapWindow (display, win); XSync(display, 0); /* Get min and max for range of color values -- assumed to be defined by "white", "black" */ min_color = (white > black) ? black : white; max_color = (white > black) ? white : black; /* Compute scaling factors (to scale computational region to window */ scale_real = (float) (REAL_MAX - REAL_MIN) / (float) width; scale_imag = (float) (IMAG_MAX - IMAG_MIN) / (float) height; /* Calculate and draw points */ for(i=0; i < width; i++) for(j=0; j < height; j++) { z.real = z.imag = 0.0; /* scale display coordinates to actual region */ c.real = REAL_MIN + ((float) i * scale_real); c.imag = IMAG_MIN + ((float) j * scale_imag); k = 0; /* Calculate z0, z1, .... until divergence or max. iters */ do { temp = z.real*z.real - z.imag*z.imag + c.real; z.imag = 2.0*z.real*z.imag + c.imag; z.real = temp; lengthsq = z.real*z.real + z.imag*z.imag; k++; } while (lengthsq < 4.0 && k < maxiter); /* Scale color and display point */ color = ((k-1)*(max_color - min_color))/maxiter; XSetForeground (display, gc, color); XDrawPoint (display, win, gc, i, j); } XFlush (display); /* Calculate execution time for program and produce text output */ times(&t); fprintf (stdout, "maxiter = %d, width = %d, height = %d\n", maxiter, width, height); fprintf (stdout, "execution time in seconds = %g\n", (float) (t.tms_utime + t.tms_stime + t.tms_cutime + t.tms_cstime) / CLK_TCK); /* Wait for user response, then exit program */ fprintf (stderr, "Press enter to end program\n"); fscanf (stdin, "%c", &dummy); return EXIT_SUCCESS; }