/*
* MANDEL.C
*
* Compute mandelbrot fractals and display the results on a textual
* device as characters of increasing darkness.
*
* The output is a 2-dimensional picture, which represents a part
* of the complex plane. The value at each point is calculated as follows:
*
* Let C be the complex coordinates of the point whose value we want to know.
* Set Z = C and then iterate Z = Z^2 + C.
*
* One of two things will happen: either Z will go zooming off to infinity
* or it will remain near the origin. If Z never goes to infinity,
* the value of C is within the Mandelbrot set.
*
* It can been shown that if the modulus of Z exceeds 2.0, it will
* definitely go off to infinity, so we stop when this happens, and the
* value of the function at point C is the number of iterations it took.
*
* To prevent infinite looping on points which are inside the Mandelbrot set,
* we impose a maximum iteration count, MAXITER. If we iterate this many times
* and are still within the boundary, the return value is MAXITER.
*
* Martin Guy, UKC, February 1989.
*/
/* constants */
#define SCR_SIZE_X 80 /* number of pixels across the screen */
#define SCR_SIZE_Y 39 /* number of pixels down the screen */
/* Define the region of the Mandelbrot set to be displayed. */
#define MIN_R -2.0
#define MIN_I -2.0
#define MAX_R 2.0
#define MAX_I 2.0
/* Maximum number of iterations before we assume that the point is
* inside the mandelbrot set */
#define MAXITER 9
/* forward declarations */
int iterate();
char iter_to_char();
main()
{
int x, y; /* Loop variables used to scan output image. */
/* Values are 0 .. MAX-1, (0,0) is top left. */
double cr, ci; /* x & y mapped onto complex plane */
double step_r, step_i; /* size of one pixel in complex */
int value;
/* precompute loop steps */
step_r = (MAX_R - MIN_R) / SCR_SIZE_X;
step_i = (MAX_I - MIN_I) / SCR_SIZE_Y;
/* We start at the top, so ci starts at MAX_I and counts down */
for (y = 0, ci = MAX_I; y < SCR_SIZE_Y; y++, ci -= step_i) {
for (x = 0, cr = MIN_R; x < SCR_SIZE_X; x++, cr += step_r) {
value = iterate(cr, ci);
putchar(iter_to_char(value));
}
putchar('\n');
}
exit(0);
}
/*
* iterate - perform the mandelbrot iteration from a given starting
* point, returning the number of iterations performed before |z| > 2,
* which will be in the range 0 .. MAXITER-1.
* If the starting value seems to be in the mandelbrot set, it returns MAXITER.
*/
int
iterate(cr, ci)
double cr, ci; /* Starting point, real and imaginary. */
{
int niter; /* Number of iterations we have done. */
double zr, zi; /* Iteration variable, real and imaginary. */
double zr2, zi2;/* Intermediate results of zr^2 and zi^2. */
zr = cr; zi = ci;
for (niter = 0; niter < MAXITER; niter++) {
/* Cache zr^2 and zi^2 'cos they're needed twice. */
zr2 = zr * zr;
zi2 = zi * zi;
/* If modulus of z is > 2, it's not in the set. */
if (zr2 + zi2 > 4.0) break;
/* z = z^2 + c
* The order of these two statements is important because
* otherwise "zi = ..." would get the new value of zr!
*/
zi = 2 * zr * zi + ci;
zr = zr2 - zi2 + cr;
}
return(niter);
}
/* Convert iteration count to the character to display for that count. */
char codetab[] = " .,:;|I*#";
#define NCODES 9
char
iter_to_char(value)
int value;
{
/* Points inside the set are distinct. */
if (value == MAXITER) return(' ');
/* Scale value into number of colours we have.
* Input values: 0..MAXITER-1
* Output values: 0..NCODES-1
* The following equation maps the same number of input values
* to each output value (+/- 1).
*/
value = (value * NCODES) / MAXITER;
/* and return the appropriate character */
return(codetab[value]);
}