Mandelbrot set
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 FDL. (See links for details on variance) |
You are encouraged to solve this task according to the task description, using any language you may know.
Generate and draw the Mandelbrot set.
C
This code uses functions from category Raster graphics operations.
<lang c>#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); i = 0; while (((x0*x0 + y0*y0) <= 4.0) && (i < MAX_ITERATIONS)){ xtemp = x0*x0 - y0*y0 + cr; y0 = 2*x0*y0 + ci; x0 = xtemp; i++; } /* 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);
}</lang>
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. <lang cpp>
- 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 rectangle 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 = 0;
while (iterations < max_iterations && std::norm(z) < 4.0) // note: std::norm(z) gives the *squared* absolute value of z { z = z*z + c; ++iterations; }
if (iterations == max_iterations) image[ix][iy] = set_color; else image[ix][iy] = non_set_color; }
} </lang>
Forth
This uses grayscale image utilities. <lang Forth>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</lang>
Octave
This code runs rather slowly and produces coloured Mandelbrot set by accident (output image here).
<lang matlab>#! /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");</lang>
PostScript
<lang 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</lang>
Tcl
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... <lang tcl>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 {}</lang>
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 not reproduced here, not when the code can be executed directly in your browser at that site.