let rec list_filter_map f l = match l with
| [] -> []
| hd::tl -> begin
match f hd with
| Some v -> v :: list_filter_map f tl
| None -> list_filter_map f tl
end
let list_map f l = list_filter_map (fun x -> Some(f x)) l
let list_filter f l = list_filter_map (fun x -> if f x then Some x else None) l
type 'a bintree =
| Feuille of 'a
| Arbre of 'a bintree * 'a bintree
let rec bintree_filter_map f a = match a with
| Feuille v -> begin
match f v with
| None -> None
| Some v2 -> Some (Feuille v2)
end
| Arbre(filsg, filsd) -> begin
match bintree_filter_map f filsg, bintree_filter_map f filsd with
| None, x | x, None -> x
| Some a1, Some a2 -> Some (Arbre(a1, a2))
end
let array_filter_map f arr =
let n = ref 0 in
let a_val = ref None in
let arr2 = Array.map f arr in
for i = 0 to Array.length arr - 1 do
if arr2.(i) <> None then begin
n := !n + 1;
a_val := arr2.(i)
end
done;
if !n = 0 then [||] else
let res = Array.make !n (Option.get !a_val) in
let j = ref 0 in
for i = 0 to Array.length arr - 1 do
if arr2.(i) <> None then begin
res.(!j) <- Option.get arr2.(i);
j := !j + 1
end
done;
res
let array_filter_map f arr =
let arr2 = Array.map f arr in
let count_some arr = Array.fold_left (fun n -> function None -> n | Some _ -> n+1) 0 arr2 in
let find_some arr = Array.fold_left (fun v -> function None -> v | Some v2 -> Some v2) None arr2 in
match (count_some arr, find_some arr) with
| 0, None -> [||]
| _, None -> assert false
| n, Some v_default ->
let res = Array.make n v_default in
let j = ref 0 in
Array.iter (function None -> () | Some v -> res.(!j)<-v; j:= !j+1) arr2;
res
let array_filter_map f arr =
let arr2 = Array.map f arr in
let count_some arr = Array.fold_left (fun n -> function None -> n | Some _ -> n+1) 0 arr2 in
let i = ref (-1) in
let rec get_next () =
i := !i + 1; match f arr.(!i) with
| None -> get_next ()
| Some v -> v
in Array.init (count_some arr) (fun _ -> get_next ())
let rec andlist l = match l with
| [] -> true
| false::_ -> false
| _::tl -> andlist tl
type 'a binop_partial_application =
| Result of 'a
| Transformation of ('a -> 'a)
type 'a lazy_binop = 'a -> 'a binop_partial_application
let lazy_product n = match n with
| 0 -> Result 0
| _ -> Transformation (fun m -> n * m)
let fun_of_lazy_binop op x y = match op x with
| Result v -> v
| Transformation f -> f y
let rec lazy_reduce plus zero l = match l with
| [] -> zero
| hd::tl -> begin
match plus zero with
| Result v -> v
| Transformation f -> lazy_reduce plus (f hd) tl
end
module type PERSISTANT_MATRIX = sig
type t
val init: int -> int -> (int -> int -> float) -> t
val dim: t -> (int * int)
val get: t -> int -> int -> float
val set: t -> int -> int -> float -> t
end
module ArrayBasedMatrix : PERSISTANT_MATRIX = struct
type t = float array array
let init n m f = Array.init n (fun i -> Array.init m (fun j-> f i j))
let dim mat = (Array.length mat, Array.length mat.(0))
let get mat i j = mat.(i).(j)
let set mat i j x =
let (n,m) = dim mat in
init n m (fun i2 j2 -> if (i,j)<>(i2,j2) then mat.(i).(j) else x)
end
module SparseMatrix : PERSISTANT_MATRIX = struct
type t = {
width: int;
height: int;
non_null_cells: (int * int * float) list
}
let init n m f =
let l = ref [] in
for i=0 to n-1 do
for j=0 to m-1 do
let x = f i j in
if x <> 0. then l := (i, j, x) :: !l
done
done;
{width = m; height = n; non_null_cells = !l}
let dim mat = (mat.height, mat.width)
let get mat i j =
let rec iter = function
| [] -> 0.
| (i2, j2, x)::_ when (i,j)=(i2,j2) -> x
| _ :: tl -> iter tl
in iter mat.non_null_cells
let set mat i j x =
{mat with non_null_cells = (i, j, x) :: mat.non_null_cells}
let set mat i j x =
if x <> 0.
then {mat with non_null_cells = (i, j, x) :: mat.non_null_cells}
else {mat with non_null_cells = List.filter (fun (i2,j2,_) -> (i,j)<>(i2,j2)) mat.non_null_cells}
end