#!/usr/bin/perl
use strict;

my %options = (
	minx => -2.0,
	maxx => 2.0,
	miny => -2.0,
	maxy => 2.0,
	width => 480,
	height => 480,
	iters => 20,
	o => "mandelbrot.ppm",
);
{
	#lazy getopt;
	my %ARGV = @ARGV;
	foreach my $key (keys %ARGV) {
		$options{$key} = $ARGV{$key};
	}
}

$options{xrange} = $options{maxx} - $options{minx};
$options{yrange} = $options{maxy} - $options{miny};

open(FILE,">",$options{o}) or die "Could not open $options{o}";
print FILE <<EOM;
P3
# A mandelbrot fractal
$options{width} $options{height}
255
EOM

for my $y (0..($options{height}-1)) {
	my $ry = $options{yrange} * (1.0*$y / $options{height}) + $options{miny};
	for my $x (0..($options{width}-1)) {
		my $rx = $options{xrange} * (1.0*$x / $options{width}) + $options{minx};
		my ($r,$g,$b) = colormap(mandeliter($rx,$ry,$options{iters}), $options{iters});
		print FILE "$r $g $b  ";
	}
	print FILE $/;
}

close(FILE);

sub colormap {
	my ($iters,$maxiters) = @_;
	my $r = int (255 * $iters / $maxiters);
	my $g = 255 - int (255 * $iters / $maxiters);
	my $b = int (255 * $iters / $maxiters);
	return ($r,$r,$r);
}
sub mandeliter {
	my ($cx,$cy,$iters) = @_;
	#warn "$cx $cy";
	my ($zx,$zy) = (0,0);
	my ($nzx,$nzy) = (0,0);
	my $zn = 0;	
	while ($iters > 0 && $zx * $zx + $zy * $zy < 2.0) {
		# ((a,b)*(c,d) = ((a*c - b*d), (b*c + a*d))
		# (a, b) + (c, d) = (a + c, b + d)
		# z*z + c
		$nzx = $zx * $zx - $zy * $zy + $cx;
		$nzy = $zy * $zx + $zx * $zy + $cy;
		($zx,$zy) = ($nzx, $nzy);
		$iters--;
	}
	return $iters;
}
