The mandelbrot benchmark looked like it'd be an easy one to implement,
and lo and behold, it was! I haven't optimized this at all really, but
it seems to run fairly quickly anyhow.
-- Peter Baylies
=head1 NAME
examples/shootout/mandelbrot.pir - Print the Mandelbrot set
=head1 SYNOPSIS
% ./parrot examples/shootout/mandelbrot.pir 200 > out.pbm
=head1 DESCRIPTION
This outputs a pbm file of the Mandelbrot set. Defaults to 200x200.
Translated from C code by Greg Buchholz into PIR
by Peter Baylies <[EMAIL PROTECTED]>.
The C code is:
/* The Great Computer Language Shootout
http://shootout.alioth.debian.org/
contributed by Greg Buchholz
compile: gcc -O2 -o mandelbrot mandelbrot.c
run: mandelbrot 200 > out.pbm
*/
#include<stdio.h>
int main (int argc, char **argv)
{
int w, h, x, y, bit_num = 0;
char byte_acc = 0;
int i, iter = 50;
double limit = 2.0;
double Zr, Zi, Cr, Ci, Tr, Ti;
w = atoi(argv[1]);
h = w;
printf("P4\n%d %d\n",w,h);
for(y=0;y<h;y++)
{
for(x=0;x<w;x++)
{
Zr = 0.0; Zi = 0.0;
Cr = (2*(double)x/w - 1.5); Ci=(2*(double)y/h - 1);
for (i=0;i<iter;i++)
{
Tr = Zr*Zr - Zi*Zi + Cr;
Ti = 2*Zr*Zi + Ci;
Zr = Tr; Zi = Ti;
if (Zr*Zr+Zi*Zi > limit*limit)
break;
}
if(Zr*Zr+Zi*Zi > limit*limit)
byte_acc = (byte_acc << 1) | 0x00;
else
byte_acc = (byte_acc << 1) | 0x01;
bit_num++;
if(bit_num == 8)
{
putc(byte_acc,stdout);
byte_acc = 0;
bit_num = 0;
}
else if(x == w-1)
{
byte_acc = byte_acc << (8-w%8);
putc(byte_acc,stdout);
byte_acc = 0;
bit_num = 0;
}
}
}
return(0);
}
=cut
.sub 'main' :main
.param pmc argv
# int w, h, x, y, bit_num = 0;
# char byte_acc = 0;
# int i, iter = 50;
# double limit = 2.0;
# double Zr, Zi, Cr, Ci, Tr, Ti;
.local int w, h, x, y, bit_num, byte_acc, i, iter
.local num limit, Zr, Zi, Cr, Ci, Tr, Ti
.sym int argc
bit_num = 0
byte_acc = 0
iter = 50
limit = 2.0
# slight optimization here -- nothing a decent C compiler wouldn't already do :)
limit = limit * limit
argc = argv
w = 200
if argc <= 1 goto noarg
# w = atoi(argv[1]);
$S0 = argv[1]
w = $S0
# h = w
noarg: h = w
# printf("P4\n%d %d\n",w,h);
print "P4\n"
print w
print " "
print h
print "\n"
y = 0
YREDO:
x = 0
XREDO:
# Zr = 0.0; Zi = 0.0;
Zr = 0.0
Zi = 0.0
# Cr = (2*(double)x/w - 1.5);
Cr = x
Cr /= w
Cr *= 2
Cr -= 1.5
# Ci=(2*(double)y/h - 1);
Ci = y
Ci /= h
Ci *= 2
Ci -= 1
i = 0
IREDO:
# Tr = Zr*Zr - Zi*Zi + Cr;
$N1 = Zr * Zr
$N2 = Zi * Zi
Tr = $N1 - $N2
Tr += Cr
# Ti = 2*Zr*Zi + Ci;
Ti = 2
Ti *= Zr
Ti *= Zi
Ti += Ci
# Zr = Tr; Zi = Ti;
Zr = Tr
Zi = Ti
# if (Zr*Zr+Zi*Zi > limit*limit) break;
# $N1 = Zr * Zr
# $N2 = Zi * Zi
$N1 += $N2
if $N1 > limit goto IBRK
inc i
if i < iter goto IREDO
IBRK:
byte_acc <<= 1
if $N1 <= limit goto SLA
byte_acc |= 0
goto SLE
SLA: byte_acc |= 1
SLE: inc bit_num
if bit_num != 8 goto NTST1
PRINT: chr $S1, byte_acc
print $S1
byte_acc = 0
bit_num = 0
goto NTSTE
NTST1: $I1 = w
dec $I1
goto NTSTE
if x != $I1 goto NTSTE
$I1 = w
$I1 %= 8
$I1 = 8 - $I1
byte_acc <<= $I1
goto PRINT
NTSTE:
inc x
if x < w goto XREDO
inc y
if y < h goto YREDO
end
.end