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;
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

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^ ^, ok);
startI := RealConv.Str2Real (store^ ^, ok);
NumConv.Str2Num (count, 10, store^ ^, ok);
step := RealConv.Str2Real (store^ ^, 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);
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");
build;
LOOP
build
IF  task = ORD ('q')  THEN  EXIT  END
ELSIF  task > 0  THEN	(* Mouse click!	*)
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 70000`
The 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;
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

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^ ^, ok);
startI := RealConv.Str2Real (store^ ^, ok);
NumConv.Str2Num (count, 10, store^ ^, ok);
step := RealConv.Str2Real (store^ ^, 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);
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");
build;
LOOP
build
IF  task = ORD ('q')  THEN  EXIT  END
ELSIF  task > 0  THEN	(* Mouse click!	*)
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 10000000000`
That 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;
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

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^ ^, ok);
startI := RealConv.Str2LongReal (store^ ^, ok);
NumConv.Str2Num (count, 10, store^ ^, ok);
step := RealConv.Str2LongReal (store^ ^, 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);
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");
build;
LOOP
build
IF  task = ORD ('q')  THEN  EXIT  END
ELSIF  task > 0  THEN	(* Mouse click!	*)
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 10000000000`
With 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:

1. -0.75 0 100 200
2. -0.7 -0.27 100000 250000
3. -0.7 -0.27 100000 2500
4. -0.7001 -0.27 2500 200000000
5. -0.6964 -0.4752 4000 1000000
6. -0.69630 -0.475 5000 250000000
7. -0.6963048 -0.474999 11000 50000000
8. -0.6963047 -0.474999 11000 10000000000
9. -1.5 0 15000 400000000000
10. -0.3705 -0.649 700000 200000
11. -0.71 0.3125 100 10000
12. 0.365 -0.24 100 12000
13. -0.71 -0.36 100 40000
14. -0.6735 -0.3615 125 30000
15. -0.71 0.3125 100 10000