#!./parrot
# Copyright (C) 2005-2009, Parrot Foundation.
# $Id: mandelbrot.pir 38369 2009-04-26 12:57:09Z fperrad $

=head1 NAME

examples/shootout/mandelbrot.pir - Print the Mandelbrot set

=head1 SYNOPSIS

    % ./parrot examples/shootout/mandelbrot.pir -R jit 600 > 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 <pbaylies@gmail.com>.

The C code is at:
   The Great Computer Language Shootout
   http://shootout.alioth.debian.org/

=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
    .local 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

# Local Variables:
#   mode: pir
#   fill-column: 100
# End:
# vim: expandtab shiftwidth=4 ft=pir:
