program Mandelbrot;

(* arithmétique de virgule fixe *)
module Fixed := struct

 (* interprétation de l'entier n : n * 2^(-q) *)

var q : integer; (* 13 bits pour la partie décimale *)
      
procedure add (x, y : integer; var res: integer);
begin
   res := x + y
end; { add }

procedure sub (x, y : integer; var res : integer);
begin
   res := x - y;
end; { sub }

procedure mul (x, y : integer; var res : integer);
var t : integer;
begin
   t := x * y;
   res := (t + q div 2) div q
end; { mul }

procedure divi (x, y : integer; var res : integer);
var t : integer;
begin
   t := x * q;
   res := (t + y div 2) div y
end; { divi }

var zero : integer;

procedure of_int (x : integer; var res : integer);
begin
   res := x * q
end; { of_int }

begin
   q := 8192;
   zero := 0
end;
end;

module Draw
 (M : sig 
    procedure add (x, y : integer; var res : integer);
    procedure sub (x, y : integer; var res : integer); 
    procedure mul (x, y : integer; var res : integer);
    procedure divi (x, y : integer; var res : integer);
    var zero : integer;
    procedure of_int (x : integer; var res : integer);
  end;
  C : sig var steps : integer; end) := struct

var two : integer;
var four : integer;

var xmin : integer;
var xmax : integer; 
var deltax : integer;

var ymin : integer; 
var ymax : integer; 
var deltay : integer; 

procedure iter (n, a, b, xn, yn	: integer; var res: boolean);
var xn2, yn2, aux, aux1_1, aux1_2, aux2_1, aux2_2, aux2_3 : integer;
begin
   if n = 100 then
      res := true
   else begin
      M.mul (xn, xn, xn2);
      M.mul (yn, yn, yn2);
      M.add (xn2, yn2, aux);
      if (aux <= four) then begin
	 M.sub (xn2, yn2, aux1_1);
	 M.add (aux1_1, a, aux1_2);
	 M.mul (xn, yn, aux2_1);
	 M.mul (two, aux2_1, aux2_2);
	 M.add (aux2_2, b, aux2_3);
	 iter ((n+1), a, b, aux1_2, aux2_3, res)
      end
      else
	 res := false
   end
end; { iter }

procedure inside (x, y : integer; var res : boolean);
begin
   iter (0, x, y, M.zero, M.zero, res)
end; { inside }

procedure row (j, y : integer);
var aux1, aux2, x : integer; res : boolean;
begin 
   if j < 2 * C.steps then begin
      M.of_int (j, aux1);
      M.mul (aux1, deltax, aux2);
      M.add (xmin, aux2, x);
      inside(x,y,res);
      if res then
	 write(1)
      else
	 write(0);
      row (j+1, y)
   end
end; { row }



procedure mandelbrot (i : integer);
var aux1, aux2, y : integer;
begin
   if i < C.steps then begin
      M.of_int (i,aux1);
      M.mul (aux1, deltay, aux2);
      M.add (ymin, aux2, y);
      row (0, y);
      writeln;
      mandelbrot (i+1);
   end
end; { mandelbrot }

var aux : integer; 
var aux1    : integer; 
var aux2 : integer; 
begin
   M.of_int (2, two);
   M.of_int (4, four);
   M.of_int (-2, xmin);
   
   M.of_int (1, aux1);
   M.divi (aux1, two, xmax);
   
   M.sub (xmax, xmin, aux1);
   M.of_int (2 * C.steps, aux2);
   M.divi (aux1, aux2, deltax);
   
   M.of_int (-1, ymin);
   M.of_int (1, ymax);
   
   M.sub (ymax, ymin, aux1);
   M.of_int (C.steps, aux2);
   M.divi (aux1, aux2, deltay);
   
   mandelbrot (0);
end;
end;

module S := struct
var steps : integer;
begin
   steps := 60
end;
end;

module M := Draw(Fixed, S);

begin end.

{
(* arithmétique de virgule fixe *)
module Fixed = struct

 (* interprétation de l'entier n : n * 2^(-q) *)

 let q = 8192 (* 13 bits pour la partie décimale *)

 let add (x:int) (y:int) = x + y

 let sub (x:int) (y:int) = x - y

 let mul (x:int) (y:int) = 
   let t = x * y in (t + q / 2) / q

 let div (x:int) (y:int) = 
   let t = x * q in (t + y / 2) / y

 let zero = 0

 let of_int (x:int) = x * q

end

module Draw
 (A : sig 
    val add : int -> int -> int 
    val sub : int -> int -> int 
    val mul : int -> int -> int
    val div : int -> int -> int
    val zero : int
    val of_int : int -> int
  end)
 (C : sig val steps : int end) =
struct

 let two = A.of_int 2
 let four = A.of_int 4

 let xmin = A.of_int (-2)
 let xmax = A.div (A.of_int 1) two
 let deltax = A.div (A.sub xmax xmin) (A.of_int (2 * C.steps))

 let ymin = A.of_int (-1)
 let ymax = A.of_int 1
 let deltay = A.div (A.sub ymax ymin) (A.of_int C.steps)

 let rec iter (n:int) (a:int) (b:int) (xn:int) (yn:int) =
   n = 100 ||
  (let xn2 = A.mul xn xn in
   let yn2 = A.mul yn yn in
   A.add xn2 yn2 <= four &&
   iter (n+1) a b 
     (A.add (A.sub xn2 yn2) a) (A.add (A.mul two (A.mul xn yn)) b))

 let inside (x : int) (y : int) = 
   iter 0 x y A.zero A.zero

 let rec row (j : int) (y : int) =
   if j < 2 * C.steps then 
     let x = A.add xmin (A.mul (A.of_int j) deltax) in
     (print_int (if inside x y then 1 else 0);
      row (j+1) y)

 let rec mandelbrot (i : int) =
   if i < C.steps then
     let y = A.add ymin (A.mul (A.of_int i) deltay) in
     (row 0 y;
      print_newline ();
      mandelbrot (i+1))

 let () = mandelbrot 0

end

module M = Draw(Fixed)(struct let steps = 60 end)
}