/*
 * Copyright (C) 1994 George Leonidas Coulouris
 *
 * Program	name  : PosterBrot
 * Description    : Generates Mandelbrot posters
 * Last modified  : 9 June 94
 */

#include <stdio.h>
#include <stdlib.h>

#ifdef USEFPU

extern __asm __regargs int
	IterateC(register __fp0 double cx, register __fp1 double cy);

#else

#include <math.h>

int
	IterateC(double cx, double cy);

#endif

unsigned short int
	iterations;

const char
	*pb_ver = "$VER: PosterBrot 1.6 (9.6.94)";

int main(int argc, char **argv)
{
char
	tempname[256];

unsigned short int
 	x,				/* pixel indices */
	y,

	x_page,			/* page indices */
	y_page,

	page_width,			/* image dimensions */
	page_height,

	width,			/* poster dimensions */
	height;

double
	xmin,				/* real range */
	xmax,

	ymin,				/* imaginary range */
	ymax,

	dx,				/* pixel increments */
	dy,

	x_offset,			/* page increments */
	y_offset;

FILE *outfile;

setbuf(stdout,NULL);

					/* banner */
printf("PosterBrot 1.6 (9 June 94)\n");
printf("Copyright (C) 1994 George Leonidas Coulouris\n\n");

					/* check argument count */
if (argc != 2)
	{
	printf("usage: PosterBrot <basename>\n\n");
	return 0;
	}

					/* get poster info */
printf("Mandelbrot attributes:\n\n");

printf("\txmin : ");
scanf("%lf",&xmin);

printf("\txmax : ");
scanf("%lf",&xmax);

printf("\tymin : ");
scanf("%lf",&ymin);

printf("\tymax : ");
scanf("%lf",&ymax);

printf("\tMaximum iterations/pixel : ");
scanf("%hu",&iterations);

printf("\n\nPoster attributes:\n\n");

printf("\tWidth  (pages) : ");
scanf("%hu",&width);

printf("\tHeight (pages) : ");
scanf("%hu",&height);

printf("\n\nPage attributes:\n\n");

printf("\tWidth  (pixels) : ");
scanf("%hu",&page_width);

printf("\tHeight (pixels) : ");
scanf("%hu",&page_height);

printf("\n");

					/* check arguments */
if ( ( xmin >= xmax ) || ( ymin >= ymax ) )
	{
	printf("Bad coordinates.\n\n");
	return 1;
	}

if ( iterations == 0 )
	{
	printf("Bad iterations.\n\n");
	return 1;
	}

if ( ( width > 99 ) || ( height > 99 ) || ( width == 0 ) || ( height == 0 ) )
	{
	printf("Bad poster size.\n\n");
	return 1;
	}

if ( ( page_width == 0 ) || ( page_height == 0 ) )
	{
	printf("Bad page size.\n\n");
	return 1;
	}

dx = (xmax - xmin) / ( page_width * width );
dy = (ymax - ymin) / ( page_height * height );

x_offset = (xmax - xmin) / width;
y_offset = (ymax - ymin) / height;

for( y_page = 0; y_page < height; y_page++ )
	for( x_page = 0; x_page < width; x_page++ )
		{
		printf("\nCalculating image %d,%d...\n",x_page,y_page);

					/* generate file name */

		sprintf(tempname,"%1.8s.%.2d.%.2d",argv[1],x_page, y_page);

		outfile = fopen(tempname,"wb");

					/* write pgm header */
		fprintf(outfile,"P5\n");
		fprintf(outfile,"%d\n",page_width);
		fprintf(outfile,"%d\n",page_height);
		fprintf(outfile,"%d\n",255);

					/* generate image */
		for( y = 0; y < page_height; y++)
			{
			printf("(Line %hu)\r",y);
			for( x = 0; x < page_width; x++)
				fputc( IterateC(
					xmin + x * dx + x_page * x_offset,
					ymax - y * dy - y_page * y_offset ),
					outfile);
			}
		fclose(outfile);
		printf(" Image complete.\n");
		}
printf("\nOperation complete.\n");
return 0;
}

#ifndef USEFPU

int IterateC(double cx, double cy)
{
unsigned short int
	i = 0;			/* Iteration index */

double
	oldzx = 0.0,
	oldzy = 0.0,
	zx,
	zy,
	r;

while ( i++ < iterations )
	{
	zx = oldzx * oldzx - oldzy * oldzy + cx;
	zy = 2.0 * oldzx * oldzy + cy;

	oldzx = zx;
	oldzy = zy;

	r = zx * zx + zy * zy;

	if (r > 4.0) return (unsigned char)( 510.0 / sqrt(r) );
	}
return 255;
}

#endif
