
(* arithmétique de virgule fixe *)
module Fixed(Prec : sig val q:int end) = struct

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

  let q : int = Prec.q

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

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

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

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

  let zero : int = 0

  let of_int (x:int) : 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 : int = A.of_int 2
  let four : int = A.of_int 4

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

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

  let rec iter (n:int) (a:int) (b:int) (xn:int) (yn:int) : bool =
    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) : bool = 
    iter 0 x y A.zero A.zero

  let rec row (j : int) (y : int) : unit =
    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 0 else 1);
       row (j+1) y)

  let rec mandelbrot (i : int) : unit =
    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 Prec = struct
  let q:int = 8192 (* 13 bits pour la partie décimale *)
end
module Arith = Fixed(Prec)

module P = struct let steps : int = 20 end
module M = Draw(Arith)(P)
