#!/usr/bin/perl

use GD;
require "../cgi-lib.pl";
ReadParse(*in);

#$pmax = 1000000;
$pmax = 500000;
$primes = primes($pmax);
@plist = sort { $a <=> $b; } (keys %{$primes});

$max = 3000;
($x,$y) = ($max/2,$max/2);
$angle = 0;
$increment = $in{inc} || 90;
$i = 1;

$img = new GD::Image($max,$max,1);
$img->fill(10,5,color(255,255,255));

$streak = 0;
while($i < $pmax) {
    my($nx,$ny);
    $nx = sprintf("%d",$x);
    $ny = sprintf("%d",$y);
    if($nx < $max && $ny < $max && $nx >=0 && $ny >= 0) {
	$grid[$nx][$ny] = $i;
    }
    $x = $x + cos(rad($angle));
    $y = $y - sin(rad($angle));
    #print "Setting $i at $x,$y\n";
    if($primes->{$i}) {
	if($in{streak}) {
	    $angle += $streak**2;
	} elsif($in{factors}) {
	    #no angle adjustment
	} else {
	    $angle += $increment;
	}
	while($angle >= 360) { $angle -= 360; }
	$streak = 0;
    } else {
	$streak++;
	if($in{factors}) {
	    my $fact = prime_factors($i,$primes,\@plist);
	    $angle += $i * (1-1/$fact);
	}
	#print "($i Not prime)\n";
    }
    $i++;
}
#$img->string(gdTinyFont,10,10,$i,color(0,0,0));
for($y=0;$y<$max;$y++) {
    for($x=0;$x<$max;$x++) {
	#if($grid[$x][$y]) { print sprintf("%2d",$i); }
	#if($grid[$x][$y]) { $img->setPixel($x,$y,color(255,0,0)); }
	if($grid[$x][$y]) {
	    $img->setPixel($x,$y,get_rgb($grid[$x][$y]));
	    if($grid[$x][$y] > $max_disp) { $max_disp = $grid[$x][$y]; }
	    unless($grid[$x][$y] % 50000) {
		#$img->string(gdTinyFont,$x+2,$y+2,$grid[$x][$y],color(0,0,0));
	    }
	    if($grid[$x][$y] >= $i-1) {
		#$img->string(gdTinyFont,$x+2,$y+2,$grid[$x][$y],color(0,0,0));
	    }
	}
    }
}
#$img->string(gdTinyFont,10,20,$max_disp,color(0,0,0));
#$img->string(gdTinyFont,10,30,$maxstreak,color(0,0,0));
#$img->string(gdTinyFont,10,40,$topstreak,color(0,0,0));

print "Content-Type: image/png\n\n";
if(-t STDOUT) {
    print "Done\n";
} else {
    print $img->png;
}

sub rad {
    return $_[0] * 3.1415926535897932384626433 / 180;
}

sub prime_factors {
    my($n,$primes,$plist,$ii) = @_;
    if($primes->{$n} || $n == 1) { return 1; }
    if($pfactors{$n}) { return $pfactors{$n}; }
    my($nfact) = 0;
    for(my $i = $ii;$plist->[$i]**2<=$n;$i++) {
	unless($n % $plist->[$i]) {
	    $nfact = prime_factors($n/$plist->[$i],$primes,$plist,$i);
	    last;
	}
    }
    my($r) = 1+$nfact;
    $pfactors{$n} = $r;
    if(-t STDOUT) {
	print "  $n -> Adding $r\n";
    }
    return $r;
}

sub prime_factors2 {
    my($n,$primes,$plist) = @_;
    if($primes->{$n} || $n == 1) { return 1; }
    my($fcount) = 0;
    for(my $i=0;$plist->[$i]*2 <= $n;$i++) {
	unless($n % $plist->[$i]) {
	    my($n2) = $n;
	    while(!($n2 % $plist->[$i])) {
		$fcount++;
		$n2 /= $plist->[$i];
	    }
	    #$fcount += ($n / $plist->[$i]);
#	    if(-t STDOUT) {
#		print "  $n -> Adding $plist->[$i]\n";
#	    }
	}
    }
#    if($n < 100) {
#	$gy += 10;
#	$img->string(gdTinyFont,10,$gy,"$n => $fcount",color(0,0,0));
#    }
#    if(-t STDOUT) {
#	print "Returning $fcount for $n\n";
#    }
    return $fcount;
}

sub get_rgb {
    my($val) = @_;
    $val = int(($val/1000) % 768);
    my($r,$g,$b);
    if($val <= 255) {
	$r = $val;
	$b = 255-$val;
	$g = 0;
    } elsif($val <= 511) {
	$g = $val-256;
	$r = 255-($val-256);
	$b = 0;
    } else {
	$b = $val-512;
	$g = 255-($val-512);
	$r = 0;
    }
    return color($r,$g,$b);
}

sub primes {
    my($n) = @_;
    my($primef) = 'primes.txt';
    my($c) = 0;
    my($i,$j,%primes,%notprimes);
    if(open(PRIMEF,$primef)) {
	while(<PRIMEF>) {
	    if(/^N:(\d+)/) {
		$c = $1;
	    } elsif(/(\d+)/) {
		$primes{$1} = 1;
	    }
	}
	close PRIMEF;
    }
    if($c < $n) {
	for($i=2;$i<=$n;$i++) {
	    if(!$notprimes{$i}) {
		$primes{$i} = 1;
		for($j=($i**2);$j<=$n;$j+=$i) {
		    $notprimes{$j} = 1;
		}
	    }
	}
	if(open(PRIMEF,"> $primef")) {
	    print PRIMEF "N:$n\n";
	    foreach my $p (keys %primes) {
		print PRIMEF "$p\n";
	    }
	    close PRIMEF;
	}
    }
    return \%primes;
}

sub color {
    my($r,$g,$b) = @_;
    if(!defined($pal{"$r\_$g\_$b"})) {
        $pal{"$r\_$g\_$b"} = $img->colorAllocate($r,$g,$b);
    }
    return $pal{"$r\_$g\_$b"};
}
