Creating the mandelbrot set
For what happened before, consult the Oberon page In short: I wanted to create the mandelbrot pictures. The obc compiler is only black and white and some depth perception with different shades of colours are then essential. And so my x11 module is required. So I ported the obc source to modula-2. Below is the source:
MODULE mand01; IMPORT x11, InOut, Arguments, NumConv, RealConv, MathLib; TYPE Complex = RECORD real, imag : REAL END; VAR z, z0, c : Complex; startR, startI, step : REAL; count, n : CARDINAL; Mx, My, task : INTEGER; store : Arguments.ArgTable; colours : ARRAY [0..19] OF CARDINAL; PROCEDURE Csq (VAR z : Complex); (* Square a Complex number *) VAR res : Complex; BEGIN res.real := z.real * z.real - z.imag * z.imag; res.imag := 2.0 * z.real * z.imag; z := res END Csq; PROCEDURE Cadd (VAR z : Complex; y : Complex); (* Add two complex numbers *) VAR res : Complex; BEGIN res.real := y.real + z.real; res.imag := y.imag + z.imag; z := res END Cadd; PROCEDURE Csize (VAR z : Complex) : INTEGER; (* Determine size (squared) of a complex number *) VAR len : INTEGER; BEGIN len := MathLib.entier (z.real * z.real + z.imag * z.imag); RETURN len END Csize; (* This function is only used in one spot and to increase speed, the number is not rooted *) PROCEDURE Init; VAR args : SHORTCARD; ok : BOOLEAN; BEGIN Arguments.GetArgs (args, store); IF args < 4 THEN InOut.WriteString ("Mandel X0 Y0 count step"); InOut.WriteLn; startR := -0.71; startI := -0.36; count := 100; step := 40000.0 ELSE startR := RealConv.Str2Real (store^ [1]^, ok); startI := RealConv.Str2Real (store^ [2]^, ok); NumConv.Str2Num (count, 10, store^ [3]^, ok); step := RealConv.Str2Real (store^ [4]^, ok); InOut.WriteLn END; z0.real := 0.0; z0.imag := 0.0 END Init; PROCEDURE build; VAR X0, Y0, x, y, color : INTEGER; BEGIN FOR X0 := 0 TO 799 DO x := X0 - 400; c.real := startR + MathLib.real (x) / step; FOR Y0 := 499 TO 0 BY -1 DO y := Y0 - 250; c.imag := startI + MathLib.real (y) / step; n := 0; z := z0; REPEAT INC (n); Csq (z); Cadd (z, c) UNTIL (Csize (z) > 4) OR (n > count); IF n < count THEN x11.setFgC (99 * n); x11.Plot (X0, Y0) END END END END build; BEGIN Init; x11.setTitle ("Mandelbrot with Mocka"); x11.Xinit (800, 500); x11.SetFont ("10x20"); task := x11.NextEvent (); build; LOOP task := x11.NextEvent (); IF task = -1000 THEN build ELSIF task < 0 THEN task := -task; IF task = ORD ('q') THEN EXIT END ELSIF task > 0 THEN (* Mouse click! *) Mx := task DIV 10000; My := task MOD 10000; END END; x11.Xclose () END mand01.Just use the mocka script to compile. Be sure to set the MOCKALINK environment variable to "-lx11" as explained in the x11 section. When done, this is the result. An example commandline is:
./mand01 -0.372 -0.65 25000 70000The 25000 is some kind of quality factor.
Other colours
The colours are calculated with the 'n' count as input. And there seems to be a favor for smaller n counts. So in the RGB colour system there is a bias for blue. Which is kind of dark. So I added a function to swap the colour parts: mand02:
MODULE mand02; IMPORT x11, InOut, Arguments, NumConv, RealConv, MathLib; TYPE Complex = RECORD real, imag : REAL END; VAR z, z0, c : Complex; startR, startI, step : REAL; count, n : CARDINAL; Mx, My, task : INTEGER; store : Arguments.ArgTable; colours : ARRAY [0..19] OF CARDINAL; PROCEDURE Csq (VAR z : Complex); VAR res : Complex; BEGIN res.real := z.real * z.real - z.imag * z.imag; res.imag := 2.0 * z.real * z.imag; z := res END Csq; PROCEDURE Cadd (VAR z : Complex; y : Complex); VAR res : Complex; BEGIN res.real := y.real + z.real; res.imag := y.imag + z.imag; z := res END Cadd; PROCEDURE Csize (VAR z : Complex) : INTEGER; VAR len : INTEGER; BEGIN len := MathLib.entier (z.real * z.real + z.imag * z.imag); RETURN len END Csize; PROCEDURE Init; VAR args : SHORTCARD; ok : BOOLEAN; BEGIN Arguments.GetArgs (args, store); IF args < 4 THEN InOut.WriteString ("Mandel X0 Y0 count step"); InOut.WriteLn; startR := -0.71; startI := -0.36; count := 100; step := 40000.0 ELSE startR := RealConv.Str2Real (store^ [1]^, ok); startI := RealConv.Str2Real (store^ [2]^, ok); NumConv.Str2Num (count, 10, store^ [3]^, ok); step := RealConv.Str2Real (store^ [4]^, ok); InOut.WriteLn END; z0.real := 0.0; z0.imag := 0.0 END Init; PROCEDURE SwapColour (c : INTEGER) : INTEGER; VAR R, G, B, res : INTEGER; BEGIN B := c MOD 256; G := (c DIV 256) MOD 256; R := c DIV 65536; res := 65536 * R + 256 * B + G; RETURN res END SwapColour; PROCEDURE build; VAR X0, Y0, x, y, color : INTEGER; BEGIN FOR X0 := 0 TO 799 DO x := X0 - 400; c.real := startR + MathLib.real (x) / step; FOR Y0 := 499 TO 0 BY -1 DO y := Y0 - 250; c.imag := startI + MathLib.real (y) / step; n := 0; z := z0; REPEAT INC (n); Csq (z); Cadd (z, c) UNTIL (Csize (z) > 4) OR (n > count); IF n < count THEN x11.setFgC (SwapColour (99 * n)); x11.Plot (X0, Y0) END END END END build; BEGIN Init; x11.setTitle ("Mandelbrot with Mocka"); x11.Xinit (800, 500); x11.SetFont ("10x20"); task := x11.NextEvent (); build; LOOP task := x11.NextEvent (); IF task = -1000 THEN build ELSIF task < 0 THEN task := -task; IF task = ORD ('q') THEN EXIT END ELSIF task > 0 THEN (* Mouse click! *) Mx := task DIV 10000; My := task MOD 10000; END END; x11.Xclose () END mand02.Resulting in the colours to be RBG instead of RGB. An array with 1000 colours would be best. I'll have to think of a way to generate such an array.
Mand04 : better colours, better resolution
Although the obc Oberon version was quite fast (for a JIT compiled program), it would be no match for these Mocka Mandelbrot searchers. It would take the obc version days on end to calculate]
./mand04 -0.6963047 -0.474999 1000000 10000000000That is with 1 million colours (and the max count) and stepsize of 1.0EE-10. That is a stepsize of 1 in 10 billion. In order to get this done I had to change all REALs into LONGREALs. It is quite astonishing to see how much influence the iteration count has on picture outputs. The below pictures (which were reduced by 75% in size) show the results for max counts of 500, 1100, 2200, 11000, 22000, 60000, 100000, 400000 and 1000000. One thing: the colours are dynamically calculated so they can not be compared between pictures.
Mand04 : the source
Below is the source code of the new mand04 Mandelbrot searcher. In essence the prgram is not changed a lot. See for yourself.
MODULE mand04; IMPORT x11, InOut, Arguments, NumConv, RealConv, MathLib; TYPE Complex = RECORD real, imag : LONGREAL END; VAR z, z0, c : Complex; startR, startI, step : LONGREAL; count, n : CARDINAL; Mx, My, task : INTEGER; store : Arguments.ArgTable; PROCEDURE Csq (VAR z : Complex); VAR res : Complex; BEGIN res.real := z.real * z.real - z.imag * z.imag; res.imag := 2.0 * z.real * z.imag; z := res END Csq; PROCEDURE Cadd (VAR z : Complex; y : Complex); VAR res : Complex; BEGIN res.real := y.real + z.real; res.imag := y.imag + z.imag; z := res END Cadd; PROCEDURE Csize (VAR z : Complex) : INTEGER; VAR len : INTEGER; BEGIN len := MathLib.entierL (z.real * z.real + z.imag * z.imag); RETURN len END Csize; PROCEDURE Init; VAR args : SHORTCARD; ok : BOOLEAN; BEGIN Arguments.GetArgs (args, store); IF args < 4 THEN InOut.WriteString ("Mandel X0 Y0 count step"); InOut.WriteLn; startR := -0.71; startI := -0.36; count := 100; step := 40000.0 ELSE startR := RealConv.Str2LongReal (store^ [1]^, ok); startI := RealConv.Str2LongReal (store^ [2]^, ok); NumConv.Str2Num (count, 10, store^ [3]^, ok); step := RealConv.Str2LongReal (store^ [4]^, ok) END; z0.real := 0.0; z0.imag := 0.0 END Init; PROCEDURE build; VAR X0, Y0, x, y, color : INTEGER; BEGIN FOR X0 := 0 TO 799 DO x := X0 - 400; c.real := startR + MathLib.realL (x) / step; FOR Y0 := 499 TO 0 BY -1 DO y := 249 - Y0; c.imag := startI + MathLib.realL (y) / step; n := 0; z := z0; REPEAT INC (n); Csq (z); Cadd (z, c) UNTIL (Csize (z) > 4) OR (n > count); IF n < count THEN x11.setFgC ((16000000 DIV count) * n); x11.Plot (X0, Y0) END END END END build; BEGIN Init; x11.setTitle ("Mandelbrot with Mocka"); x11.Xinit (800, 500); x11.SetFont ("10x20"); task := x11.NextEvent (); build; LOOP task := x11.NextEvent (); IF task = -1000 THEN build ELSIF task < 0 THEN task := -task; IF task = ORD ('q') THEN EXIT END ELSIF task > 0 THEN (* Mouse click! *) Mx := task DIV 10000; My := task MOD 10000; END END; x11.Xclose () END mand04.The new colour to be plotted is calculated by
x11.setFgC ((16000000 DIV count) * n);x11 uses 24 bit colours, which is something like 16 million. Almost all colours are now used. The smaller the max count is, the bigger the change between any two colours. I did a test with an array of 6000 colours but that didn't work out satisfactorily. This one, with "the fraction of white" works great.
The commandline for producing the series of images above was:
./mand04 -0.6963047 -0.474999 1000000 10000000000With 1 million colours, the black spots (the actual Mandelbrot set points) take quite some time to calculate. Perhaps a nex version should not use a 'Complex TYPE' but just a collection of numbers.
Interesting area's
Below is a list with interesting area's to explore:
Downloads
Page created 4 November 2018 and