Mandelbrot set
From Rosetta Code
| This page uses content from Wikipedia. The original article was at Mandelbrot_set. The list of authors can be seen in the page history. As with Rosetta Code, the text of Wikipedia is available under the GNU Free Documentation License. |
You are encouraged to solve this task according to the task description, using any language you may know.
[edit] ALGOL 68
Works with: Algol 68 Genie 1.19.0
Plot part of the Mandelbrot set as a pseudo-gif image.
INT pix = 300, max iter = 256, REAL zoom = 0.33 / pix;
[-pix : pix, -pix : pix] INT plane;
COMPL ctr = 0.05 I 0.75 # center of set #;
# Compute the length of an orbit. #
PROC iterate = (COMPL z0) INT:
BEGIN COMPL z := z0, INT iter := 1;
WHILE (iter +:= 1) < max iter # not converged # AND ABS z < 2 # not diverged #
DO z := z * z + z0
OD;
iter
END;
# Compute set and find maximum orbit length. #
INT max col := 0;
FOR x FROM -pix TO pix
DO FOR y FROM -pix TO pix
DO COMPL z0 = ctr + (x * zoom) I (y * zoom);
IF (plane [x, y] := iterate (z0)) < max iter
THEN (plane [x, y] > max col | max col := plane [x, y])
FI
OD
OD;
# Make a plot. #
FILE plot;
INT num pix = 2 * pix + 1;
make device (plot, "gif", whole (num pix, 0) + "x" + whole (num pix, 0));
open (plot, "mandelbrot.gif", stand draw channel);
FOR x FROM -pix TO pix
DO FOR y FROM -pix TO pix
DO INT col = (plane [x, y] > max col | max col | plane [x, y]);
REAL c = sqrt (1- col / max col); # sqrt to enhance contrast #
draw colour (plot, c, c, c);
draw point (plot, (x + pix) / (num pix - 1), (y + pix) / (num pix - 1))
OD
OD;
close (plot)
[edit] AutoHotkey
Max_Iteration := 256
Width := Height := 400
File := "MandelBrot." Width ".bmp"
Progress, b2 w400 fs9, Creating Colours ...
Gosub, CreateColours
Gosub, CreateBitmap
Progress, Off
Gui, -Caption
Gui, Margin, 0, 0
Gui, Add, Picture,, %File%
Gui, Show,, MandelBrot
Return
GuiClose:
GuiEscape:
ExitApp
;---------------------------------------------------------------------------
CreateBitmap: ; create and save a 32bit bitmap file
;---------------------------------------------------------------------------
; define header details
HeaderBMP := 14
HeaderDIB := 40
DataOffset := HeaderBMP + HeaderDIB
ImageSize := Width * Height * 4 ; 32bit
FileSize := DataOffset + ImageSize
Resolution := 3780 ; from mspaint
; create bitmap header
VarSetCapacity(IMAGE, FileSize, 0)
NumPut(Asc("B") , IMAGE, 0x00, "Char")
NumPut(Asc("M") , IMAGE, 0x01, "Char")
NumPut(FileSize , IMAGE, 0x02, "UInt")
NumPut(DataOffset , IMAGE, 0x0A, "UInt")
NumPut(HeaderDIB , IMAGE, 0x0E, "UInt")
NumPut(Width , IMAGE, 0x12, "UInt")
NumPut(Height , IMAGE, 0x16, "UInt")
NumPut(1 , IMAGE, 0x1A, "Short") ; Planes
NumPut(32 , IMAGE, 0x1C, "Short") ; Bits per Pixel
NumPut(ImageSize , IMAGE, 0x22, "UInt")
NumPut(Resolution , IMAGE, 0x26, "UInt")
NumPut(Resolution , IMAGE, 0x2A, "UInt")
; fill in Data
Gosub, CreatePixels
; save Bitmap to file
FileDelete, %File%
Handle := DllCall("CreateFile", "Str", File, "UInt", 0x40000000
, "UInt", 0, "UInt", 0, "UInt", 2, "UInt", 0, "UInt", 0)
DllCall("WriteFile", "UInt", Handle, "UInt", &IMAGE, "UInt"
, FileSize, "UInt *", Bytes, "UInt", 0)
DllCall("CloseHandle", "UInt", Handle)
Return
;---------------------------------------------------------------------------
CreatePixels: ; create pixels for [-2 < x < 1] [-1.5 < y < 1.5]
;---------------------------------------------------------------------------
Loop, % Height // 2 + 1 {
yi := A_Index - 1
y0 := -1.5 + yi / Height * 3 ; range -1.5 .. +1.5
Progress, % 200*yi // Height, % "Current line: " 2*yi " / " Height
Loop, %Width% {
xi := A_Index - 1
x0 := -2 + xi / Width * 3 ; range -2 .. +1
Gosub, Mandelbrot
p1 := DataOffset + 4 * (Width * yi + xi)
NumPut(Colour, IMAGE, p1, "UInt")
p2 := DataOffset + 4 * (Width * (Height-yi) + xi)
NumPut(Colour, IMAGE, p2, "UInt")
}
}
Return
;---------------------------------------------------------------------------
Mandelbrot: ; calculate a colour for each pixel
;---------------------------------------------------------------------------
x := y := Iteration := 0
While, (x*x + y*y <= 4) And (Iteration < Max_Iteration) {
xtemp := x*x - y*y + x0
y := 2*x*y + y0
x := xtemp
Iteration++
}
Colour := Iteration = Max_Iteration ? 0 : Colour_%Iteration%
Return
;---------------------------------------------------------------------------
CreateColours: ; borrowed from PureBasic example
;---------------------------------------------------------------------------
Loop, 64 {
i4 := (i3 := (i2 := (i1 := A_Index - 1) + 64) + 64) + 64
Colour_%i1% := RGB(4*i1 + 128, 4*i1, 0)
Colour_%i2% := RGB(64, 255, 4*i1)
Colour_%i3% := RGB(64, 255 - 4*i1, 255)
Colour_%i4% := RGB(64, 0, 255 - 4*i1)
}
Return
;---------------------------------------------------------------------------
RGB(r, g, b) { ; return 24bit color value
;---------------------------------------------------------------------------
Return, (r&0xFF)<<16 | g<<8 | b
}
[edit] BASIC
Works with: QBasic
This is almost exactly the same as the pseudocode from the Wikipedia entry's "For programmers" section (which it's closely based on, of course). The image generated is very blocky ("low-res") due to the selected video mode, but it's fairly accurate.
SCREEN 13
WINDOW (-2, 1.5)-(2, -1.5)
FOR x0 = -2 TO 2 STEP .01
FOR y0 = -1.5 TO 1.5 STEP .01
x = 0
y = 0
iteration = 0
maxIteration = 223
WHILE (x * x + y * y <= (2 * 2) AND iteration < maxIteration)
xtemp = x * x - y * y + x0
y = 2 * x * y + y0
x = xtemp
iteration = iteration + 1
WEND
IF iteration <> maxIteration THEN
c = iteration
ELSE
c = 0
END IF
PSET (x0, y0), c + 32
NEXT
NEXT
[edit] Brace
This is a simple Mandelbrot plotter. A longer version based on this smooths colors, and avoids calculating the time-consuming black pixels: http://sam.ai.ki/brace/examples/mandelbrot.d/1
#!/usr/bin/env bx
use b
Main():
num outside = 16, ox = -0.5, oy = 0, r = 1.5
long i, max_i = 100, rb_i = 30
space()
uint32_t *px = pixel()
num d = 2*r/h, x0 = ox-d*w_2, y0 = oy+d*h_2
for(y, 0, h):
cmplx c = x0 + (y0-d*y)*I
repeat(w):
cmplx w = c
for i=0; i < max_i && cabs(w) < outside; ++i
w = w*w + c
*px++ = i < max_i ? rainbow(i*359 / rb_i % 360) : black
c += d
An example plot from the longer version:
[edit] C
This code uses functions from category Raster graphics operations.
#include <stdio.h>
#include "imglib.h"
#define MAX_ITERATIONS 500
void draw_mandel(image img){
unsigned int x, y;
unsigned int width, height;
color_component colour;
double x0, y0, xtemp, cr, ci;
unsigned int i;
width = img->width;
height = img->height;
for (x = 0; x < width; x++) {
for (y = 0; y < height; y++) {
x0 = y0 = 0;
cr = ((double)x / (double)width - 0.5);
ci = ((double)y / (double)height - 0.5);
for (i = 0; x0*x0 + y0*y0 <= 4.0 && i < MAX_ITERATIONS; i++){
xtemp = x0*x0 - y0*y0 + cr;
y0 = 2*x0*y0 + ci;
x0 = xtemp;
}
/* points in the set are coloured as white, others are coloured black. */
colour = (i == MAX_ITERATIONS ? 255 : 0);
put_pixel_clip(img, x, y, colour, colour, colour);
}
}
}
#define W 640
#define H 480
int main()
{
image img;
FILE *o;
img = alloc_img(W, H);
draw_mandel(img);
o = fopen("mandel.ppm", "w");
output_ppm(o, img);
fclose(o);
free_img(img);
}
Or, using complex numbers, the above draw_mandel() function could be written as follows: Works with: C99
#include <complex.h>
void draw_mandel(image img){
unsigned int x, y;
unsigned int width, height;
color_component colour;
double complex z, c;
unsigned int i;
width = img->width;
height = img->height;
for (x = 0; x < width; x++) {
for (y = 0; y < height; y++) {
z = 0;
c = ((double)x / (double)width - 0.5) + ((double)y / (double)height - 0.5)I;
for (i = 0; cabs(z) <= 2.0 && i < MAX_ITERATIONS; i++){
z = z*z + c;
}
/* points in the set are coloured as white, others are coloured black. */
colour = (i == MAX_ITERATIONS ? 255 : 0);
put_pixel_clip(img, x, y, colour, colour, colour);
}
}
}
[edit] C++
This generic function assumes that the image can be accessed like a two-dimensional array of colors. It may be passed a true array (in which case the Mandelbrot set will simply be drawn into that array, which then might be saved as image file), or a class which maps the subscript operator to the pixel drawing routine of some graphics library. In the latter case, there must be functions get_first_dimension and get_second_dimension defined for that type, to be found by argument dependent lookup. The code provides those functions for built-in arrays.
#include <cstdlib>
#include <complex>
// get dimensions for arrays
template<typename ElementType, std::size_t dim1, std::size_t dim2>
std::size_t get_first_dimension(ElementType (&a)[dim1][dim2])
{
return dim1;
}
template<typename ElementType, std::size_t dim1, std::size_t dim2>
std::size_t get_second_dimension(ElementType (&a)[dim1][dim2])
{
return dim2;
}
template<typename ColorType, typename ImageType>
void draw_Mandelbrot(ImageType& image, //where to draw the image
ColorType set_color, ColorType non_set_color, //which colors to use for set/non-set points
double cxmin, double cxmax, double cymin, double cymax,//the rect to draw in the complex plane
unsigned int max_iterations) //the maximum number of iterations
{
std::size_t const ixsize = get_first_dimension(ImageType);
std::size_t const iysize = get_first_dimension(ImageType);
for (std::size_t ix = 0; ix < ixsize; ++ix)
for (std::size_t iy = 0; iy < iysize; ++iy)
{
std::complex c(cxmin + ix/(ixsize-1.0)*(cxmax-cxmin), cymin + iy/(iysize-1.0)*(cymax-cymin));
std::complex z = 0;
unsigned int iterations;
for (iterations = 0; iterations < max_iterations && std::abs(z) < 2.0; ++iterations)
z = z*z + c;
image[ix][iy] = (iterations == max_iterations) ? set_color : non_set_color;
}
}
[edit] C#
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Threading;
using System.Windows.Forms;
/// <summary>
/// Generates bitmap of Mandelbrot Set and display it on the form.
/// </summary>
public class MandelbrotSetForm : Form
{
const double MaxValueExtent = 2.0;
Thread thread;
static double CalcMandelbrotSetColor(ComplexNumber c)
{
// from http://en.wikipedia.org/w/index.php?title=Mandelbrot_set
const int MaxIterations = 1000;
const double MaxNorm = MaxValueExtent * MaxValueExtent;
int iteration = 0;
ComplexNumber z = new ComplexNumber();
do
{
z = z * z + c;
iteration++;
} while (z.Norm() < MaxNorm && iteration < MaxIterations);
if (iteration < MaxIterations)
return (double)iteration / MaxIterations;
else
return 0; // black
}
static void GenerateBitmap(Bitmap bitmap)
{
double scale = 2 * MaxValueExtent / Math.Min(bitmap.Width, bitmap.Height);
for (int i = 0; i < bitmap.Height; i++)
{
double y = (bitmap.Height / 2 - i) * scale;
for (int j = 0; j < bitmap.Width; j++)
{
double x = (j - bitmap.Width / 2) * scale;
double color = CalcMandelbrotSetColor(new ComplexNumber(x, y));
bitmap.SetPixel(j, i, GetColor(color));
}
}
}
static Color GetColor(double value)
{
const double MaxColor = 256;
const double ContrastValue = 0.2;
return Color.FromArgb(0, 0,
(int)(MaxColor * Math.Pow(value, ContrastValue)));
}
public MandelbrotSetForm()
{
// form creation
this.Text = "Mandelbrot Set Drawing";
this.BackColor = System.Drawing.Color.Black;
this.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Stretch;
this.MaximizeBox = false;
this.StartPosition = FormStartPosition.CenterScreen;
this.FormBorderStyle = FormBorderStyle.FixedDialog;
this.ClientSize = new Size(640, 640);
this.Load += new System.EventHandler(this.MainForm_Load);
}
void MainForm_Load(object sender, EventArgs e)
{
thread = new Thread(thread_Proc);
thread.IsBackground = true;
thread.Start(this.ClientSize);
}
void thread_Proc(object args)
{
// start from small image to provide instant display for user
Size size = (Size)args;
int width = 16;
while (width * 2 < size.Width)
{
int height = width * size.Height / size.Width;
Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format24bppRgb);
GenerateBitmap(bitmap);
this.BeginInvoke(new SetNewBitmapDelegate(SetNewBitmap), bitmap);
width *= 2;
Thread.Sleep(200);
}
// then generate final image
Bitmap finalBitmap = new Bitmap(size.Width, size.Height, PixelFormat.Format24bppRgb);
GenerateBitmap(finalBitmap);
this.BeginInvoke(new SetNewBitmapDelegate(SetNewBitmap), finalBitmap);
}
void SetNewBitmap(Bitmap image)
{
if (this.BackgroundImage != null)
this.BackgroundImage.Dispose();
this.BackgroundImage = image;
}
delegate void SetNewBitmapDelegate(Bitmap image);
static void Main()
{
Application.Run(new MandelbrotSetForm());
}
}
struct ComplexNumber
{
public double Re;
public double Im;
public ComplexNumber(double re, double im)
{
this.Re = re;
this.Im = im;
}
public static ComplexNumber operator +(ComplexNumber x, ComplexNumber y)
{
return new ComplexNumber(x.Re + y.Re, x.Im + y.Im);
}
public static ComplexNumber operator *(ComplexNumber x, ComplexNumber y)
{
return new ComplexNumber(x.Re * y.Re - x.Im * y.Im,
x.Re * y.Im + x.Im * y.Re);
}
public double Norm()
{
return Re * Re + Im * Im;
}
}
[edit] Clojure
Translation of: Perl
(ns mandelbrot
(:refer-clojure :exclude [+ * <])
(:use (clojure.contrib complex-numbers)
(clojure.contrib.generic [arithmetic :only [+ *]]
[comparison :only [<]]
[math-functions :only [abs]])))
(defn mandelbrot? [z]
(loop [c 1
m (iterate #(+ z (* % %)) z)]
(if (and (> 20 c)
(< (abs (first m)) 2) )
(recur (inc c)
(rest m))
(if (= 20 c) true false))))
(defn mandelbrot []
(for [y (range 1 -1 -0.05)
x (range -2 0.5 0.0315)]
(if (mandelbrot? (complex x y)) "#" " ")))
(println (interpose \newline (map #(apply str %) (partition 80 (mandelbrot)))))
[edit] D
Library: QD using Library: SDL Library: Phobos
module mandelbrot;
import qd;
double lensqr(cdouble c) { return c.re * c.re + c.im * c.im; }
const Limit = 150;
void main() {
screen(640, 480);
for (int y = 0; y < screen.h; ++y) {
flip; events;
for (int x = 0; x < screen.w; ++x) {
auto
c_x = x * 1.0 / screen.w - 0.5,
c_y = y * 1.0 / screen.h - 0.5,
c = c_y * 2.0i + c_x * 3.0 - 1.0,
z = 0.0i + 0.0,
i = 0;
for (; i < Limit; ++i) {
z = z * z + c;
if (lensqr(z) > 4) break;
}
auto value = cast(ubyte) (i * 255.0 / Limit);
pset(x, y, rgb(value, value, value));
}
}
while (true) { flip; events; }
}
[edit] F#
open System.Drawing
open System.Windows.Forms
type Complex =
{
re : float;
im : float
}
let cplus (x:Complex) (y:Complex) : Complex =
{
re = x.re + y.re;
im = x.im + y.im
}
let cmult (x:Complex) (y:Complex) : Complex =
{
re = x.re * y.re - x.im * y.im;
im = x.re * y.im + x.im * y.re;
}
let norm (x:Complex) : float =
x.re*x.re + x.im*x.im
type Mandel = class
inherit Form
static member xPixels = 500
static member yPixels = 500
val mutable bmp : Bitmap
member x.mandelbrot xMin xMax yMin yMax maxIter =
let rec mandelbrotIterator z c n =
if (norm z) > 2.0 then false else
match n with
| 0 -> true
| n -> let z' = cplus ( cmult z z ) c in
mandelbrotIterator z' c (n-1)
let dx = (xMax - xMin) / (float (Mandel.xPixels))
let dy = (yMax - yMin) / (float (Mandel.yPixels))
in
for xi = 0 to Mandel.xPixels-1 do
for yi = 0 to Mandel.yPixels-1 do
let c = {re = xMin + (dx * float(xi) ) ;
im = yMin + (dy * float(yi) )} in
if (mandelbrotIterator {re=0.;im=0.;} c maxIter) then
x.bmp.SetPixel(xi,yi,Color.Azure)
else
x.bmp.SetPixel(xi,yi,Color.Black)
done
done
member public x.generate () = x.mandelbrot (-1.5) 0.5 (-1.0) 1.0 200 ; x.Refresh()
new() as x = {bmp = new Bitmap(Mandel.xPixels , Mandel.yPixels)} then
x.Text <- "Mandelbrot set" ;
x.Width <- Mandel.xPixels ;
x.Height <- Mandel.yPixels ;
x.BackgroundImage <- x.bmp;
x.generate();
x.Show();
end
let f = new Mandel()
do Application.Run(f)
[edit] Forth
This uses grayscale image utilities.
500 value max-iter
: mandel ( gmp F: imin imax rmin rmax -- )
0e 0e { F: imin F: imax F: rmin F: rmax F: Zr F: Zi }
dup bheight 0 do
i s>f dup bheight s>f f/ imax imin f- f* imin f+ TO Zi
dup bwidth 0 do
i s>f dup bwidth s>f f/ rmax rmin f- f* rmin f+ TO Zr
Zr Zi max-iter
begin 1- dup
while fover fdup f* fover fdup f*
fover fover f+ 4e f<
while f- Zr f+
frot frot f* 2e f* Zi f+
repeat fdrop fdrop
drop 0 \ for a pretty grayscale image, replace with: 255 max-iter */
else drop 255
then fdrop fdrop
over i j rot g!
loop
loop drop ;
80 24 graymap
dup -1e 1e -2e 1e mandel
dup gshow
free bye
[edit] Fortran
Works with: Fortran version 90 and later
program mandelbrot
implicit none
integer , parameter :: rk = selected_real_kind (9, 99)
integer , parameter :: i_max = 800
integer , parameter :: j_max = 600
integer , parameter :: n_max = 100
real (rk), parameter :: x_centre = -0.5_rk
real (rk), parameter :: y_centre = 0.0_rk
real (rk), parameter :: width = 4.0_rk
real (rk), parameter :: height = 3.0_rk
real (rk), parameter :: dx_di = width / i_max
real (rk), parameter :: dy_dj = -height / j_max
real (rk), parameter :: x_offset = x_centre - 0.5_rk * (i_max + 1) * dx_di
real (rk), parameter :: y_offset = y_centre - 0.5_rk * (j_max + 1) * dy_dj
integer, dimension (i_max, j_max) :: image
integer :: i
integer :: j
integer :: n
real (rk) :: x
real (rk) :: y
real (rk) :: x_0
real (rk) :: y_0
real (rk) :: x_sqr
real (rk) :: y_sqr
do j = 1, j_max
y_0 = y_offset + dy_dj * j
do i = 1, i_max
x_0 = x_offset + dx_di * i
x = 0.0_rk
y = 0.0_rk
n = 0
do
x_sqr = x ** 2
y_sqr = y ** 2
if (x_sqr + y_sqr > 4.0_rk) then
image (i, j) = 255
exit
end if
if (n == n_max) then
image (i, j) = 0
exit
end if
y = y_0 + 2.0_rk * x * y
x = x_0 + x_sqr - y_sqr
n = n + 1
end do
end do
end do
open (10, file = 'out.pgm')
write (10, '(a/ i0, 1x, i0/ i0)') 'P2', i_max, j_max, 255
write (10, '(i0)') image
close (10)
end program mandelbrot
[edit] gnuplot
The output from gnuplot is controlled by setting the appropriate values for the options terminal and output.
set terminal png
set output 'mandelbrot.png'
The following script draws an image of the number of iterations it takes to escape the circle with radius rmax with a maximum of nmax.
rmax = 2
nmax = 100
complex (x, y) = x * {1, 0} + y * {0, 1}
mandelbrot (z, z0, n) = n == nmax || abs (z) > rmax ? n : mandelbrot (z ** 2 + z0, z0, n + 1)
set samples 200
set isosamples 200
set pm3d map
set size square
splot [-2 : 2] [-2 : 2] mandelbrot (complex (x, y), complex (x, y), 0) notitle
Output:
[edit] Haskell
Translation of: Ruby
import Data.Complex
mandelbrot a = iterate (\z -> z^2 + a) a !! 50
main = mapM_ putStrLn [[if magnitude (mandelbrot (x :+ y)) < 2 then '*' else ' '
| x <- [-2, -1.9685 .. 0.5]]
| y <- [1, 0.95 .. -1]]
[edit] haXe
This version compiles for flash version 9 or greater. The compilation command is
haxe -swf9 mandelbrot.swf -main Mandelbrot
class Mandelbrot extends flash.display.Sprite
{
inline static var MAX_ITER = 255;
public static function main() {
var w = flash.Lib.current.stage.stageWidth;
var h = flash.Lib.current.stage.stageHeight;
var mandelbrot = new Mandelbrot(w, h);
flash.Lib.current.stage.addChild(mandelbrot);
mandelbrot.drawMandelbrot();
}
var image:flash.display.BitmapData;
public function new(width, height) {
super();
var bitmap:flash.display.Bitmap;
image = new flash.display.BitmapData(width, height, false);
bitmap = new flash.display.Bitmap(image);
this.addChild(bitmap);
}
public function drawMandelbrot() {
image.lock();
var step_x = 3.0 / (image.width-1);
var step_y = 2.0 / (image.height-1);
for (i in 0...image.height) {
var ci = i * step_y - 1.0;
for (j in 0...image.width) {
var k = 0;
var zr = 0.0;
var zi = 0.0;
var cr = j * step_x - 2.0;
while (k <= MAX_ITER && (zr*zr + zi*zi) <= 4) {
var temp = zr*zr - zi*zi + cr;
zi = 2*zr*zi + ci;
zr = temp;
k ++;
}
paint(j, i, k);
}
}
image.unlock();
}
inline function paint(x, y, iter) {
var color = iter > MAX_ITER? 0 : iter * 0x100;
image.setPixel(x, y, color);
}
}
[edit] Icon and Unicon
[edit] Icon
link graphics
procedure main()
width := 750
height := 600
limit := 100
WOpen("size="||width||","||height)
every x:=1 to width & y:=1 to height do
{
z:=complex(0,0)
c:=complex(2.5*x/width-2.0,(2.0*y/height-1.0))
j:=0
while j<limit & cAbs(z)<2.0 do
{
z := cAdd(cMul(z,z),c)
j+:= 1
}
Fg(mColor(j,limit))
DrawPoint(x,y)
}
WriteImage("./mandelbrot.gif")
WDone()
end
procedure mColor(x,limit)
max_color := 2^16-1
color := integer(max_color*(real(x)/limit))
return(if x=limit
then "black"
else color||","||color||",0")
end
record complex(r,i)
procedure cAdd(x,y)
return complex(x.r+y.r,x.i+y.i)
end
procedure cMul(x,y)
return complex(x.r*y.r-x.i*y.i,x.r*y.i+x.i*y.r)
end
procedure cAbs(x)
return sqrt(x.r*x.r+x.i*x.i)
end
Library: Icon Programming Library graphics is required
[edit] Unicon
This Icon solution works in Unicon.
[edit] IDL
IDL - Interactive Data Language (free implementation: GDL - GNU Data Language http://gnudatalanguage.sourceforge.net)
PRO Mandelbrot,xRange,yRange,xPixels,yPixels,iterations
xPixelstartVec = Lindgen( xPixels) * Float(xRange[1]-xRange[0]) / $
xPixels + xRange[0]
yPixelstartVec = Lindgen( yPixels) * Float(YRANGE[1]-yrange[0])$
/ yPixels + yRange[0]
constArr = Complex( Rebin( xPixelstartVec, xPixels, yPixels),$
Rebin( Transpose(yPixelstartVec), xPixels, yPixels))
valArr = ComplexArr( xPixels, yPixels)
res = IntArr( xPixels, yPixels)
oriIndex = Lindgen( Long(xPixels) * yPixels)
FOR i = 0, iterations-1 DO BEGIN ; only one loop needed
; calculation for whole array at once
valArr = valArr^2 - constArr
whereIn = Where( Abs( valArr) LE 4.0d, COMPLEMENT=whereOut)
IF whereIn[0] EQ -1 THEN BREAK
valArr = valArr[ whereIn]
constArr = constArr[ whereIn]
IF whereOut[0] NE -1 THEN BEGIN
res[ oriIndex[ whereOut]] = i+1
oriIndex = oriIndex[ whereIn]
ENDIF
ENDFOR
tv,res ; open a window and show the result
END
Mandelbrot,[-1.,2.3],[-1.3,1.3],640,512,200
END
from the command line:
GDL>.run mandelbrot
or
GDL> Mandelbrot,[-1.,2.3],[-1.3,1.3],640,512,200
[edit] J
The characteristic function of the Mandelbrot can be defined as follows:
mcf=. (<: 2:)@|@(] ((*:@] + [)^:((<: 2:)@|@])^:1000) 0:) NB. 1000 iterations test
The Mandelbrot set can be drawn as follows:
domain=. |.@|:@({.@[ + ] *~ j./&i.&>/@+.@(1j1 + ] %~ -~/@[))&>/
load'graph'
viewmat mcf "0 @ domain (_2j_1 1j1) ; 0.01 NB. Complex interval and resolution
[edit] Java
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import javax.swing.JFrame;
public class Mandelbrot extends JFrame {
private final int MAX_ITER = 570;
private final double ZOOM = 150;
private BufferedImage I;
private double zx, zy, cX, cY, tmp;
public Mandelbrot() {
super("Mandelbrot Set");
setBounds(100, 100, 800, 600);
setResizable(false);
setDefaultCloseOperation(EXIT_ON_CLOSE);
I = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_RGB);
for (int y = 0; y < getHeight(); y++) {
for (int x = 0; x < getWidth(); x++) {
zx = zy = 0;
cX = (x - 400) / ZOOM;
cY = (y - 300) / ZOOM;
int iter = MAX_ITER;
while (zx * zx + zy * zy < 4 && iter > 0) {
tmp = zx * zx - zy * zy + cX;
zy = 2.0 * zx * zy + cY;
zx = tmp;
iter--;
}
I.setRGB(x, y, iter | (iter << 8));
}
}
}
@Override
public void paint(Graphics g) {
g.drawImage(I, 0, 0, this);
}
public static void main(String[] args) {
new Mandelbrot().setVisible(true);
}
}
[edit] JavaScript
Works with: Firefox version 3.5.11
This needs the canvas tag of HTML 5 (it will not run on IE or old browsers).
function Mandeliter(cx, cy, maxiter)
{
var i;
var x = 0.0;
var y = 0.0;
for (i = 0; i < maxiter && x*x + y*y <= 4; ++i)
{
var tmp = 2*x*y;
x = x*x - y*y + cx;
y = tmp + cy;
}
return i;
}
function Mandelbrot()
{
var width = 900;
var height = 600;
var cd = document.getElementById('calcdata');
var xmin = parseFloat(cd.xmin.value);
var xmax = parseFloat(cd.xmax.value);
var ymin = parseFloat(cd.ymin.value);
var ymax = parseFloat(cd.ymax.value);
var iterations = parseInt(cd.iterations.value);
var ctx = document.getElementById('mandelimage').getContext("2d");
var img = ctx.getImageData(0, 0, width, height);
var pix = img.data;
for (var ix = 0; ix < width; ++ix)
for (var iy = 0; iy < height; ++iy)
{
var x = xmin + (xmax-xmin)*ix/(width-1);
var y = ymin + (ymax-ymin)*iy/(height-1);
var i = Mandeliter(x, y, iterations);
var ppos = 4*(900*iy + ix);
if (i == iterations)
{
pix[ppos] = 0;
pix[ppos+1] = 0;
pix[ppos+2] = 0;
}
else
{
var c = 3*Math.log(i)/Math.log(iterations - 1.0);
if (c < 1)
{
pix[ppos] = 255*c;
pix[ppos+1] = 0;
pix[ppos+2] = 0;
}
else if (c < 2)
{
pix[ppos] = 255;
pix[ppos+1] = 255*(c-1);
pix[ppos+2] = 0;
}
else
{
pix[ppos] = 255;
pix[ppos+1] = 255;
pix[ppos+2] = 255*(c-2);
}
}
pix[ppos+3] = 255;
}
ctx.putImageData(img,0,0);
}
The corresponding HTML:
<!DOCTYPE html>
<html>
<head>
<title>Mandelbrot set</title>
<script src="Mandelbrot.js" type="text/javascript"></script>
</head>
<body onload="Mandelbrot()">
<h1>Mandelbrot set</h1>
<form id="calcdata" onsubmit="javascript:Mandelbrot(); return false;">
<table>
<tr>
<td>xmin =</td>
<td><input name="xmin" type="text" size="10" value="-2"></td>
<td>xmax =</td>
<td><input name="xmax" type="text" size="10" value="1"></td>
</tr>
<tr>
<td>ymin =</td>
<td><input name="ymin" type="text" size="10" value="-1"></td>
<td>ymax =</td>
<td><input name="ymax" type="text" size="10" value="1"></td>
</tr>
</table>
<p>iterations =
<input name="iterations" type="text" size="10" value="1000"></p>
<p>
<input type="submit" value=" Calculate ">
<input type="reset" value=" Reset form ">
</p>
</form>
<canvas id="mandelimage" width="900" height="600">
This page needs a browser with canvas support.
</canvas>
</body>
</html>
Output with default parameters:
[edit] Mathematica
The implementation could be better. But this is a start...
eTime[z0_, maxIter_Integer: 100] := (Length@NestWhileList[(# + z0)^2 &, 0, (Abs@# <= 2) &, 1, maxIter]) - 1
DistributeDefinitions[eTime];
mesh = ParallelTable[eTime[(x + I*y), 1000], {y, 1.2, -1.2, -0.01}, {x, -1.72, 1, 0.01}];
ReliefPlot[mesh, Frame -> False]
[edit] MATLAB
This solution uses the escape time algorithm to determine the coloring of the coordinates on the complex plane. The code can be reduced to a single line via vectorization after the Escape Time Algorithm function definition, but the code becomes unnecessarily obfuscated. Also, this code uses a lot of memory. You will need a computer with a lot of memory to compute the set with high resolution.
function [theSet,realAxis,imaginaryAxis] = mandelbrotSet(start,gridSpacing,last,maxIteration)
%Define the escape time algorithm
function escapeTime = escapeTimeAlgorithm(z0)
escapeTime = 0;
z = 0;
while( (abs(z)<=2) && (escapeTime < maxIteration) )
z = (z + z0)^2;
escapeTime = escapeTime + 1;
end
end
%Define the imaginary axis
imaginaryAxis = (imag(start):imag(gridSpacing):imag(last));
%Define the real axis
realAxis = (real(start):real(gridSpacing):real(last));
%Construct the complex plane from the real and imaginary axes
complexPlane = meshgrid(realAxis,imaginaryAxis) + meshgrid(imaginaryAxis(end:-1:1),realAxis)'.*i;
%Apply the escape time algorithm to each point in the complex plane
theSet = arrayfun(@escapeTimeAlgorithm, complexPlane);
%Draw the set
pcolor(realAxis,imaginaryAxis,theSet);
shading flat;
end
To use this function you must specify the:
- lower left hand corner of the complex plane from which to start the image,
- the grid spacing in both the imaginary and real directions,
- the upper right hand corner of the complex plane at which to end the image and
- the maximum iterations for the escape time algorithm.
For example:
- Lower Left Corner: -2.05-1.2i
- Grid Spacing: 0.004+0.0004i
- Upper Right Corner: 0.45+1.2i
- Maximum Iterations: 500
Sample usage:
mandelbrotSet(-2.05-1.2i,0.004+0.0004i,0.45+1.2i,500);
[edit] Modula-3
MODULE Mandelbrot EXPORTS Main;
IMPORT Wr, Stdio, Fmt, Word;
CONST m = 50;
limit2 = 4.0;
TYPE UByte = BITS 8 FOR [0..16_FF];
VAR width := 200;
height := 200;
bitnum: CARDINAL := 0;
byteacc: UByte := 0;
isOverLimit: BOOLEAN;
Zr, Zi, Cr, Ci, Tr, Ti: REAL;
BEGIN
Wr.PutText(Stdio.stdout, "P4\n" & Fmt.Int(width) & " " & Fmt.Int(height) & "\n");
FOR y := 0 TO height - 1 DO
FOR x := 0 TO width - 1 DO
Zr := 0.0; Zi := 0.0;
Cr := 2.0 * FLOAT(x) / FLOAT(width) - 1.5;
Ci := 2.0 * FLOAT(y) / FLOAT(height) - 1.0;
FOR i := 1 TO m + 1 DO
Tr := Zr*Zr - Zi*Zi + Cr;
Ti := 2.0*Zr*Zi + Ci;
Zr := Tr; Zi := Ti;
isOverLimit := Zr*Zr + Zi*Zi > limit2;
IF isOverLimit THEN EXIT; END;
END;
IF isOverLimit THEN
byteacc := Word.Xor(Word.LeftShift(byteacc, 1), 16_00);
ELSE
byteacc := Word.Xor(Word.LeftShift(byteacc, 1), 16_01);
END;
INC(bitnum);
IF bitnum = 8 THEN
Wr.PutChar(Stdio.stdout, VAL(byteacc, CHAR));
byteacc := 0;
bitnum := 0;
ELSIF x = width - 1 THEN
byteacc := Word.LeftShift(byteacc, 8 - (width MOD 8));
Wr.PutChar(Stdio.stdout, VAL(byteacc, CHAR));
byteacc := 0;
bitnum := 0
END;
Wr.Flush(Stdio.stdout);
END;
END;
END Mandelbrot.
[edit] OCaml
#load "graphics.cma";;
let mandelbrot xMin xMax yMin yMax xPixels yPixels maxIter =
let rec mandelbrotIterator z c n =
if (Complex.norm z) > 2.0 then false else
match n with
| 0 -> true
| n -> let z' = Complex.add (Complex.mul z z) c in
mandelbrotIterator z' c (n-1) in
Graphics.open_graph
(" "^(string_of_int xPixels)^"x"^(string_of_int yPixels));
let dx = (xMax -. xMin) /. (float_of_int xPixels)
and dy = (yMax -. yMin) /. (float_of_int yPixels) in
for xi = 0 to xPixels - 1 do
for yi = 0 to yPixels - 1 do
let c = {Complex.re = xMin +. (dx *. float_of_int xi);
Complex.im = yMin +. (dy *. float_of_int yi)} in
if (mandelbrotIterator Complex.zero c maxIter) then
(Graphics.set_color Graphics.white;
Graphics.plot xi yi )
else
(Graphics.set_color Graphics.black;
Graphics.plot xi yi )
done
done;;
mandelbrot (-1.5) 0.5 (-1.0) 1.0 500 500 200;;
[edit] Octave
This code runs rather slowly and produces coloured Mandelbrot set by accident (output image).
#! /usr/bin/octave -qf
global width = 200;
global height = 200;
maxiter = 100;
z0 = 0;
global cmax = 1 + i;
global cmin = -2 - i;
function cs = pscale(c)
global cmax;
global cmin;
global width;
global height;
persistent px = (real(cmax-cmin))/width;
persistent py = (imag(cmax-cmin))/height;
cs = real(cmin) + px*real(c) + i*(imag(cmin) + py*imag(c));
endfunction
ms = zeros(width, height);
for x = 0:width-1
for y = 0:height-1
z0 = 0;
c = pscale(x+y*i);
for ic = 1:maxiter
z1 = z0^2 + c;
if ( abs(z1) > 2 ) break; endif
z0 = z1;
endfor
ms(x+1, y+1) = ic/maxiter;
endfor
endfor
saveimage("mandel.ppm", round(ms .* 255).', "ppm");
[edit] Perl
translation / optimization of the ruby solution
use Math::Complex;
sub mandelbrot {
my ($z, $c) = @_[0,0];
for (1 .. 20) {
$z = $z * $z + $c;
return $_ if abs $z > 2;
}
}
for (my $y = 1; $y >= -1; $y -= 0.05) {
for (my $x = -2; $x <= 0.5; $x += 0.0315)
{print mandelbrot($x + $y * i) ? ' ' : '#'}
print "\n"
}
[edit] PicoLisp
(scl 6)
(let Ppm (make (do 300 (link (need 400))))
(for (Y . Row) Ppm
(for (X . @) Row
(let (ZX 0 ZY 0 CX (*/ (- X 250) 1.0 150) CY (*/ (- Y 150) 1.0 150) C 570)
(while (and (> 4.0 (+ (*/ ZX ZX 1.0) (*/ ZY ZY 1.0))) (gt0 C))
(let Tmp (- (*/ ZX ZX 1.0) (*/ ZY ZY 1.0) (- CX))
(setq
ZY (+ (*/ 2 ZX ZY 1.0) CY)
ZX Tmp ) )
(dec 'C) )
(set (nth Ppm Y X) (list 0 C C)) ) ) )
(out "img.ppm"
(prinl "P6")
(prinl 400 " " 300)
(prinl 255)
(for Y Ppm (for X Y (apply wr X))) ) )
[edit] PostScript
%!PS-Adobe-2.0
%%BoundingBox: 0 0 300 200
%%EndComments
/origstate save def
/ld {load def} bind def
/m /moveto ld /g /setgray ld
/dot { currentpoint 1 0 360 arc fill } bind def
%%EndProlog
% param
/maxiter 200 def
% complex manipulation
/complex { 2 array astore } def
/real { 0 get } def
/imag { 1 get } def
/cmul { /a exch def /b exch def
a real b real mul
a imag b imag mul sub
a real b imag mul
a imag b real mul add
2 array astore
} def
/cadd { aload pop 3 -1 roll aload pop
3 -1 roll add
3 1 roll add exch 2 array astore
} def
/cconj { aload pop neg 2 array astore } def
/cabs2 { dup cconj cmul 0 get} def
% mandel
200 100 translate
-200 1 100 { /x exch def
-100 1 100 { /y exch def
/z0 0.0 0.0 complex def
0 1 maxiter { /iter exch def
x 100 div y 100 div complex
z0 z0 cmul
cadd dup /z0 exch def
cabs2 4 gt {exit} if
} for
iter maxiter div g
x y m dot
} for
} for
%
showpage
origstate restore
%%EOF
[edit] PureBasic
PureBasic forum: discussion
EnableExplicitExample:
#Window1 = 0
#Image1 = 0
#ImgGadget = 0
#max_iteration = 64
#width = 800
#height = 600
Define.d x0 ,y0 ,xtemp ,cr, ci
Define.i i, n, x, y ,Event ,color
Dim Color.l (255)
For n = 0 To 63
Color( 0 + n ) = RGB( n*4+128, 4 * n, 0 )
Color( 64 + n ) = RGB( 64, 255, 4 * n )
Color( 128 + n ) = RGB( 64, 255 - 4 * n , 255 )
Color( 192 + n ) = RGB( 64, 0, 255 - 4 * n )
Next
If OpenWindow(#Window1, 0, 0, #width, #height, "'Mandelbrot set' PureBasic Example", #PB_Window_SystemMenu )
If CreateImage(#Image1, #width, #height)
ImageGadget(#ImgGadget, 0, 0, #width, #height, ImageID(#Image1))
For y.i = 1 To #height -1
StartDrawing(ImageOutput(#Image1))
For x.i = 1 To #width -1
x0 = 0
y0 = 0;
cr = (x / #width)*2.5 -2
ci = (y / #height)*2.5 -1.25
i = 0
While (x0*x0 + y0*y0 <= 4.0) And i < #max_iteration
i +1
xtemp = x0*x0 - y0*y0 + cr
y0 = 2*x0*y0 + ci
x0 = xtemp
Wend
If i >= #max_iteration
Plot(x, y, 0 )
Else
Plot(x, y, Color(i & 255))
EndIf
Next
StopDrawing()
SetGadgetState(#ImgGadget, ImageID(#Image1))
Repeat
Event = WindowEvent()
If Event = #PB_Event_CloseWindow
End
EndIf
Until Event = 0
Next
EndIf
Repeat
Event = WaitWindowEvent()
Until Event = #PB_Event_CloseWindow
EndIf
[edit] Python
Translation of the ruby solution
# Python 3.0+ and 2.5+
try:
from functools import reduce
except:
pass
def mandelbrot(a): return reduce(lambda z, c: z*z + c, (a for i in range(50)), a)
def step(start, step, iterations): return (start + (i * step) for i in range(iterations))
rows = (('*' if abs(mandelbrot(complex(x, y))) < 2 else ' '
for x in step(-2.0, .0315, 80))
for y in step(1, -.05, 41))
print( '\n'.join(''.join(row) for row in rows) )
[edit] R
createmandel <- function(zfrom, zto, inc=0.01, maxiter=100) {
x <- c()
y <- c()
cost <- zfrom
while( Re(cost) <= Re(zto) ) {
cost <- Re(cost) + Im(zfrom)*1i
while ( Im(cost) <= Im(zto) ) {
j <- 0
z <- 0
while( (abs(z) < 2) && (j < maxiter)) {
z <- z^2 + cost
j <- j + 1
}
if ( j == maxiter ) {
x <- c(x, Re(cost))
y <- c(y, Im(cost))
}
cost <- cost + inc*1i
}
cost <- cost + inc
}
plot(x,y, pch=".")
}
createmandel(-2-1i, 1+1i)
[edit] Ruby
Text only, prints an 80-char by 41-line depiction. Found here.
require 'complex'
def mandelbrot(a)
Array.new(50,a).inject(a) { |z,c| z*z + c }
end
(1.0).step(-1,-0.05) do |y|
(-2.0).step(0.5,0.0315) do |x|
print mandelbrot(Complex(x,y)).abs < 2 ? '*' : ' '
end
puts
end
Translation of: Tcl
Uses the text progress bar from Median filter#Ruby
class RGBColour
def self.mandel_colour(i)
self.new( 16*(i % 15), 32*(i % 7), 8*(i % 31) )
end
end
class Pixmap
def self.mandelbrot(width, height)
mandel = Pixmap.new(width,height)
pb = ProgressBar.new(width) if $DEBUG
width.times do |x|
height.times do |y|
x_ish = Float(x - width*11/15) / (width/3)
y_ish = Float(y - height/2) / (height*3/10)
mandel[x,y] = RGBColour.mandel_colour(mandel_iters(x_ish, y_ish))
end
pb.update(x) if $DEBUG
end
pb.close if $DEBUG
mandel
end
def self.mandel_iters(cx,cy)
x = y = 0.0
count = 0
while Math.hypot(x,y) < 2 and count < 255
x, y = (x**2 - y**2 + cx), (2*x*y + cy)
count += 1
end
count
end
end
Pixmap.mandelbrot(300,300).save('mandel.ppm')
[edit] Scheme
This implementation writes an image of the Mandelbrot set to a plain pgm file. The set itself is drawn in white, while the exterior is drawn in black.
(define x-centre -0.5)
(define y-centre 0.0)
(define width 4.0)
(define i-max 800)
(define j-max 600)
(define n 100)
(define r-max 2.0)
(define file "out.pgm")
(define colour-max 255)
(define pixel-size (/ width i-max))
(define x-offset (- x-centre (* 0.5 pixel-size (+ i-max 1))))
(define y-offset (+ y-centre (* 0.5 pixel-size (+ j-max 1))))
(define (inside? z)
(define (*inside? z-0 z n)
(and (< (magnitude z) r-max)
(or (= n 0)
(*inside? z-0 (+ (* z z) z-0) (- n 1)))))
(*inside? z z n))
(define (boolean->integer b)
(if b colour-max 0))
(define (pixel i j)
(boolean->integer
(inside?
(make-rectangular (+ x-offset (* pixel-size i))
(- y-offset (* pixel-size j))))))
(define (plot)
(with-output-to-file file
(lambda ()
(begin (display "P2") (newline)
(display i-max) (newline)
(display j-max) (newline)
(display colour-max) (newline)
(do ((j 1 (+ j 1))) ((> j j-max))
(do ((i 1 (+ i 1))) ((> i i-max))
(begin (display (pixel i j)) (newline))))))))
(plot)
[edit] Scratch
[edit] Tcl
Library: Tk This code makes extensive use of Tk's built-in photo image system, which provides a 32-bit RGBA plotting surface that can be then quickly drawn in any number of places in the application. It uses a computational color scheme that was easy to code...
package require Tk
proc mandelIters {cx cy} {
set x [set y 0.0]
for {set count 0} {hypot($x,$y) < 2 && $count < 255} {incr count} {
set x1 [expr {$x*$x - $y*$y + $cx}]
set y1 [expr {2*$x*$y + $cy}]
set x $x1; set y $y1
}
return $count
}
proc mandelColor {iter} {
set r [expr {16*($iter % 15)}]
set g [expr {32*($iter % 7)}]
set b [expr {8*($iter % 31)}]
format "#%02x%02x%02x" $r $g $b
}
image create photo mandel -width 300 -height 300
# Build picture in strips, updating as we go so we have "progress" monitoring
# Also set the cursor to tell the user to wait while we work.
pack [label .mandel -image mandel -cursor watch]
update
for {set x 0} {$x < 300} {incr x} {
for {set y 0} {$y < 300} {incr y} {
set i [mandelIters [expr {($x-220)/100.}] [expr {($y-150)/90.}]]
mandel put [mandelColor $i] -to $x $y
}
update
}
.mandel configure -cursor {}
[edit] XSLT
The fact that you can create an image of the Mandelbrot Set with XSLT is sometimes under-appreciated. However, it has been discussed extensively on the internet so is best reproduced here, and the code can be executed directly in your browser at that site.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!-- XSLT Mandelbrot - written by Joel Yliluoma 2007, http://iki.fi/bisqwit/ -->
<xsl:output method="html" indent="no"
doctype-public="-//W3C//DTD HTML 4.01//EN"
doctype-system="http://www.w3.org/TR/REC-html40/strict.dtd"
/>
<xsl:template match="/fractal">
<html>
<head>
<title>XSLT fractal</title>
<style type="text/css">
body { color:#55F; background:#000 }
pre { font-family:monospace; font-size:7px }
pre span { background:<xsl:value-of select="background" /> }
</style>
</head>
<body>
<div style="position:absolute;top:20px;left:20em">
Copyright © 1992,2007 Joel Yliluoma
(<a href="http://iki.fi/bisqwit/">http://iki.fi/bisqwit/</a>)
</div>
<h1 style="margin:0px">XSLT fractal</h1>
<pre><xsl:call-template name="bisqwit-mandelbrot" /></pre>
</body>
</html>
</xsl:template>
<xsl:template name="bisqwit-mandelbrot"
><xsl:call-template name="bisqwit-mandelbrot-line">
<xsl:with-param name="y" select="y/min"/>
</xsl:call-template
></xsl:template>
<xsl:template name="bisqwit-mandelbrot-line"
><xsl:param name="y"
/><xsl:call-template name="bisqwit-mandelbrot-column">
<xsl:with-param name="x" select="x/min"/>
<xsl:with-param name="y" select="$y"/>
</xsl:call-template
><xsl:if test="$y < y/max"
><br
/><xsl:call-template name="bisqwit-mandelbrot-line">
<xsl:with-param name="y" select="$y + y/step"/>
</xsl:call-template
></xsl:if
></xsl:template>
<xsl:template name="bisqwit-mandelbrot-column"
><xsl:param name="x"
/><xsl:param name="y"
/><xsl:call-template name="bisqwit-mandelbrot-slot">
<xsl:with-param name="x" select="$x" />
<xsl:with-param name="y" select="$y" />
<xsl:with-param name="zr" select="$x" />
<xsl:with-param name="zi" select="$y" />
</xsl:call-template
><xsl:if test="$x < x/max"
><xsl:call-template name="bisqwit-mandelbrot-column">
<xsl:with-param name="x" select="$x + x/step"/>
<xsl:with-param name="y" select="$y" />
</xsl:call-template
></xsl:if
></xsl:template>
<xsl:template name="bisqwit-mandelbrot-slot"
><xsl:param name="x"
/><xsl:param name="y"
/><xsl:param name="zr"
/><xsl:param name="zi"
/><xsl:param name="iter" select="0"
/><xsl:variable name="zrsqr" select="($zr * $zr)"
/><xsl:variable name="zisqr" select="($zi * $zi)"
/><xsl:choose>
<xsl:when test="(4*scale*scale >= $zrsqr + $zisqr) and (maxiter > $iter+1)"
><xsl:call-template name="bisqwit-mandelbrot-slot">
<xsl:with-param name="x" select="$x" />
<xsl:with-param name="y" select="$y" />
<xsl:with-param name="zi" select="(2 * $zr * $zi) div scale + $y" />
<xsl:with-param name="zr" select="($zrsqr - $zisqr) div scale + $x" />
<xsl:with-param name="iter" select="$iter + 1" />
</xsl:call-template
></xsl:when>
<xsl:otherwise
><xsl:variable name="magnitude" select="magnitude[@value=$iter]"
/><span style="color:{$magnitude/color}"
><xsl:value-of select="$magnitude/symbol"
/></span></xsl:otherwise>
</xsl:choose
></xsl:template>
</xsl:stylesheet>






