#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
double m_limit = 5;
double m_epsilon = 0.001;
unsigned int m_max_iter = 600;
unsigned int m_w = 640;
unsigned int m_h = 480;
double m_x1 = -2.2;
double m_x2 = +1;
double m_y1 = -1.1;
double m_y2 = +1.1;
/* C version (since using point() in XS code fails make test (but passes
manual runs huh?) */
unsigned int _point(unsigned int x1, unsigned int y1)
{
double za,zb,za1;
double za2,zb2;
double x,y;
unsigned int RETVAL;
x = (x1 * (m_x2 - m_x1) / m_w) + m_x1;
y = (y1 * (m_y2 - m_y1) / m_h) + m_y1;
za = 0;
zb = 0;
za2 = 0;
zb2 = 0;
RETVAL = 0;
while (RETVAL++ < m_max_iter)
{
za1 = za2 - zb2 + x;
zb = 2 * za * zb + y;
za = za1;
za2 = za * za; zb2 = zb * zb;
if (za2 + zb2 > m_limit)
{
break;
}
}
if (RETVAL >= m_max_iter)
{
RETVAL = 0;
}
return RETVAL;
}
MODULE = Math::Fractal::Mandelbrot PACKAGE = Math::Fractal::Mandelbrot
PROTOTYPES: ENABLE
##############################################################################
# point() - calculate fractal at this point
# input: X and Y coordinates of the point
unsigned int
point(myclass, x1, y1)
unsigned int x1
unsigned int y1
INIT:
double za,zb,za1;
double za2,zb2;
double x,y;
CODE:
x = (x1 * (m_x2 - m_x1) / m_w) + m_x1;
y = (y1 * (m_y2 - m_y1) / m_h) + m_y1;
za = 0;
zb = 0;
za2 = 0;
zb2 = 0;
RETVAL = 0;
while (RETVAL++ < m_max_iter)
{
za1 = za2 - zb2 + x;
zb = 2 * za * zb + y;
za = za1;
za2 = za * za; zb2 = zb * zb;
if (za2 + zb2 > m_limit)
{
break;
}
}
if (RETVAL >= m_max_iter)
{
RETVAL = 0;
}
OUTPUT:
RETVAL
##############################################################################
# hor_line() - calculate fractal at a horizontal stripe
# input: X and Y coordinates of the start point
# L length of line
AV*
hor_line(myclass, x1, y1, l)
unsigned int x1
unsigned int y1
unsigned int l
INIT:
unsigned int x, x2, i, last, iter, same;
AV* a2;
CODE:
a2 = (AV*)sv_2mortal((SV*)newAV());
av_extend (a2, l + 1);
x2 = x1 + l;
i = 1; same = 0; last = _point (x1,y1);
for (x = x1; x < x2; x++)
{
iter = _point (x,y1);
av_push( a2, newSViv(iter) );
if (iter == last) { same++; } else { break; }
}
for (;x < x2; x++)
{
iter = _point (x,y1);
av_push( a2, newSViv(iter) );
}
av_push( a2, newSViv(same) );
RETVAL = (AV*)a2;
OUTPUT:
RETVAL
##############################################################################
# ver_line() - calculate fractal at a vertical stripe
# input: X and Y coordinates of the start point
# L length of line
AV*
ver_line(myclass, x1, y1, l)
unsigned int x1
unsigned int y1
unsigned int l
INIT:
unsigned int y, y2, i, last, iter, same;
AV* a2;
CODE:
a2 = (AV*)sv_2mortal((SV*)newAV());
av_extend (a2, l + 1);
y2 = y1 + l;
i = 1; same = 0; last = _point (x1,y1);
for (y = y1; y < y2; y++)
{
iter = _point (x1,y);
av_push( a2, newSViv(iter) );
if (iter == last) { same++; } else { break; }
}
for (;y < y2; y++)
{
iter = _point (x1,y);
av_push( a2, newSViv(iter) );
}
av_push( a2, newSViv(same) );
RETVAL = a2;
OUTPUT:
RETVAL
##############################################################################
# set_max_iter() - set maximum iterations
# input: new max_iter
unsigned int
set_max_iter(myclass, new_max_iter)
unsigned int new_max_iter
CODE:
m_max_iter = new_max_iter;
if (new_max_iter == 0) { m_max_iter = 1; } /* at least 1 */
RETVAL = m_max_iter;
OUTPUT:
RETVAL
##############################################################################
# set_limit()
# input: new limit
double
set_limit(myclass, new_limit)
double new_limit
CODE:
m_limit = new_limit;
RETVAL = m_limit;
OUTPUT:
RETVAL
##############################################################################
# set_epsilon()
# input: new limit
double
set_epsilon(myclass, new_e)
double new_e
CODE:
m_epsilon = new_e;
RETVAL = m_epsilon;
OUTPUT:
RETVAL
##############################################################################
# set_bounds()
# input: x1,y1, x2,y2, w,h
void
set_bounds(myclass, nx1, ny1, nx2, ny2, nw, nh)
double nx1
double ny1
double nx2
double ny2
unsigned int nw
unsigned int nh
CODE:
m_x1 = nx1;
m_y1 = ny1;
m_x2 = nx2;
m_y2 = ny2;
m_w = nw;
m_h = nh;