module type S = sig include Custom.T type elem external get: t -> elem list = "%identity" val singleton: elem -> t val iter: (elem -> unit) -> t -> unit val filter: (elem -> bool) -> t -> t val exists: (elem -> bool) -> t -> bool val fold: ('a -> elem -> 'a) -> 'a -> t -> 'a val pick: t -> elem option val length: t -> int val empty: t val is_empty: t -> bool val from_list : elem list -> t val add: elem -> t -> t val remove: elem -> t -> t val disjoint: t -> t -> bool val cup: t -> t -> t val split: t -> t -> t * t * t (* split l1 l2 = (l1 \ l2, l1 & l2, l2 \ l1) *) val cap: t -> t -> t val diff: t -> t -> t val subset: t -> t -> bool val map: (elem -> elem) -> t -> t val mem: t -> elem -> bool module Map: sig type 'a map external get: 'a map -> (elem * 'a) list = "%identity" val empty: 'a map val iter: ('a -> unit) -> 'a map -> unit val filter: (elem -> 'a -> bool) -> 'a map -> 'a map val is_empty: 'a map -> bool val singleton: elem -> 'a -> 'a map val assoc_remove: elem -> 'a map -> 'a * 'a map val remove: elem -> 'a map -> 'a map val merge: ('a -> 'a -> 'a ) -> 'a map -> 'a map -> 'a map val cap: ('a -> 'a -> 'a ) -> 'a map -> 'a map -> 'a map val sub: ('a -> 'a -> 'a ) -> 'a map -> 'a map -> 'a map val merge_elem: 'a -> 'a map -> 'a map -> 'a map val union_disj: 'a map -> 'a map -> 'a map val diff: 'a map -> t -> 'a map val from_list: ('a -> 'a -> 'a ) -> (elem * 'a) list -> 'a map val from_list_disj: (elem * 'a) list -> 'a map val map_from_slist: (elem -> 'a) -> t -> 'a map val collide: ('a -> 'b -> unit) -> 'a map -> 'b map -> unit val map: ('a -> 'b) -> 'a map -> 'b map val mapi: (elem -> 'a -> 'b) -> 'a map -> 'b map val constant: 'a -> t -> 'a map val num: int -> t -> int map val map_to_list: ('a -> 'b) -> 'a map -> 'b list val mapi_to_list: (elem -> 'a -> 'b) -> 'a map -> 'b list val assoc: elem -> 'a map -> 'a val assoc_present: elem -> 'a map -> 'a val compare: ('a -> 'a -> int) -> 'a map -> 'a map -> int val hash: ('a -> int) -> 'a map -> int val equal: ('a -> 'a -> bool) -> 'a map -> 'a map -> bool end end module Make(X : Custom.T) = struct include Custom.List(X) let rec check = function | x::(y::_ as tl) -> X.check x; assert (X.compare x y < 0); check tl | [x] -> X.check x; | _ -> () type elem = X.t let rec equal l1 l2 = (l1 == l2) || match (l1,l2) with | x1::l1, x2::l2 -> (X.equal x1 x2) && (equal l1 l2) | _ -> false let rec hash accu = function | [] -> 1 + accu | x::l -> hash (17 * accu + X.hash x) l let hash l = hash 1 l let rec compare l1 l2 = if l1 == l2 then 0 else match (l1,l2) with | x1::l1, x2::l2 -> let c = X.compare x1 x2 in if c <> 0 then c else compare l1 l2 | [],_ -> -1 | _ -> 1 let iter = List.iter let filter = List.filter let exists = List.exists let fold = List.fold_left external get: t -> elem list = "%identity" let singleton x = [ x ] let pick = function x::_ -> Some x | _ -> None let length = List.length let empty = [] let is_empty l = l = [] let rec disjoint l1 l2 = if l1 == l2 then l1 == [] else match (l1,l2) with | (t1::q1, t2::q2) -> let c = X.compare t1 t2 in if c < 0 then disjoint q1 l2 else if c > 0 then disjoint l1 q2 else false | _ -> true let rec cup l1 l2 = if l1 == l2 then l1 else match (l1,l2) with | (t1::q1, t2::q2) -> let c = X.compare t1 t2 in if c = 0 then t1::(cup q1 q2) else if c < 0 then t1::(cup q1 l2) else t2::(cup l1 q2) | ([],l2) -> l2 | (l1,[]) -> l1 let add x l = cup [x] l let rec split l1 l2 = match (l1,l2) with | (t1::q1, t2::q2) -> let c = X.compare t1 t2 in if c = 0 then let (l1,i,l2) = split q1 q2 in (l1,t1::i,l2) else if c < 0 then let (l1,i,l2) = split q1 l2 in (t1::l1,i,l2) else let (l1,i,l2) = split l1 q2 in (l1,i,t2::l2) | _ -> (l1,[],l2) let rec diff l1 l2 = if l1 == l2 then [] else match (l1,l2) with | (t1::q1, t2::q2) -> let c = X.compare t1 t2 in if c = 0 then diff q1 q2 else if c < 0 then t1::(diff q1 l2) else diff l1 q2 | _ -> l1 let remove x l = diff l [x] let rec cap l1 l2 = if l1 == l2 then l1 else match (l1,l2) with | (t1::q1, t2::q2) -> let c = X.compare t1 t2 in if c = 0 then t1::(cap q1 q2) else if c < 0 then cap q1 l2 else cap l1 q2 | _ -> [] let rec subset l1 l2 = (l1 == l2) || match (l1,l2) with | (t1::q1, t2::q2) -> let c = X.compare t1 t2 in if c = 0 then ( (* inlined: subset q1 q2 *) (q1 == q2) || match (q1,q2) with | (t1::qq1, t2::qq2) -> let c = X.compare t1 t2 in if c = 0 then subset qq1 qq2 else if c < 0 then false else subset q1 qq2 | [],_ -> true | _ -> false ) else if c < 0 then false else subset l1 q2 | [],_ -> true | _ -> false let from_list l = let rec initlist = function | [] -> [] | e::rest -> [e] :: initlist rest in let rec merge2 = function | l1::l2::rest -> cup l1 l2 :: merge2 rest | x -> x in let rec mergeall = function | [] -> [] | [l] -> l | llist -> mergeall (merge2 llist) in mergeall (initlist l) let map f l = from_list (List.map f l) let rec mem l x = match l with | [] -> false | t::q -> let c = X.compare x t in (c = 0) || ((c > 0) && (mem q x)) module Map = struct type 'a map = (X.t * 'a) list external get: 'a map -> (elem * 'a) list = "%identity" let empty = [] let is_empty l = l = [] let singleton x y = [ (x,y) ] let rec iter f = function | (_,y)::l -> f y; iter f l | [] -> () let rec filter f = function | ((x,y) as c)::l -> if f x y then c::(filter f l) else filter f l | [] -> [] let rec assoc_remove_aux v r = function | ((x,y) as a)::l -> let c = X.compare x v in if c = 0 then (r := Some y; l) else if c < 0 then a :: (assoc_remove_aux v r l) else raise Not_found | [] -> raise Not_found let assoc_remove v l = let r = ref None in let l = assoc_remove_aux v r l in match !r with Some x -> (x,l) | _ -> assert false (* TODO: is is faster to raise exception Not_found and return original list ? *) let rec remove v = function | (((x,y) as a)::rem) as l-> let c = X.compare x v in if c = 0 then rem else if c < 0 then a :: (remove v rem) else l | [] -> [] let rec merge f l1 l2 = match (l1,l2) with | ((x1,y1) as t1)::q1, ((x2,y2) as t2)::q2 -> let c = X.compare x1 x2 in if c = 0 then (x1,(f y1 y2))::(merge f q1 q2) else if c < 0 then t1::(merge f q1 l2) else t2::(merge f l1 q2) | ([],l2) -> l2 | (l1,[]) -> l1 let rec cap f l1 l2 = match (l1,l2) with | ((x1,y1) as t1)::q1, ((x2,y2) as t2)::q2 -> let c = X.compare x1 x2 in if c = 0 then (x1,(f y1 y2))::(cap f q1 q2) else if c < 0 then cap f q1 l2 else cap f l1 q2 | _ -> [] let rec sub f l1 l2 = match (l1,l2) with | ((x1,y1) as t1)::q1, ((x2,y2) as t2)::q2 -> let c = X.compare x1 x2 in if c = 0 then (x1,(f y1 y2))::(sub f q1 q2) else if c < 0 then t1::(sub f q1 l2) else sub f l1 q2 | (l1,_) -> l1 let merge_elem x l1 l2 = merge (fun _ _ -> x) l1 l2 (* TODO: optimize this ? *) let rec union_disj l1 l2 = match (l1,l2) with | ((x1,y1) as t1)::q1, ((x2,y2) as t2)::q2 -> let c = X.compare x1 x2 in if c = 0 then failwith "SortedList.Map.union_disj" else if c < 0 then t1::(union_disj q1 l2) else t2::(union_disj l1 q2) | ([],l2) -> l2 | (l1,[]) -> l1 let rec diff l1 l2 = match (l1,l2) with | (((x1,y1) as t1)::q1, x2::q2) -> let c = X.compare x1 x2 in if c = 0 then diff q1 q2 else if c < 0 then t1::(diff q1 l2) else diff l1 q2 | _ -> l1 let from_list f l = let rec initlist = function | [] -> [] | e::rest -> [e] :: initlist rest in let rec merge2 = function | l1::l2::rest -> merge f l1 l2 :: merge2 rest | x -> x in let rec mergeall = function | [] -> [] | [l] -> l | llist -> mergeall (merge2 llist) in mergeall (initlist l) let from_list_disj l = let rec initlist = function | [] -> [] | e::rest -> [e] :: initlist rest in let rec merge2 = function | l1::l2::rest -> union_disj l1 l2 :: merge2 rest | x -> x in let rec mergeall = function | [] -> [] | [l] -> l | llist -> mergeall (merge2 llist) in mergeall (initlist l) let rec map_from_slist f = function | x::l -> (x,f x)::(map_from_slist f l) | [] -> [] let rec collide f l1 l2 = match (l1,l2) with | (_,y1)::l1, (_,y2)::l2 -> f y1 y2; collide f l1 l2 | [],[] -> () | _ -> assert false let rec map f = function | (x,y)::l -> (x, f y)::(map f l) | [] -> [] let rec mapi f = function | (x,y)::l -> (x, f x y)::(mapi f l) | [] -> [] let rec mapi_to_list f = function | (x,y)::l -> (f x y) ::(mapi_to_list f l) | [] -> [] let rec constant y = function | x::l -> (x,y)::(constant y l) | [] -> [] let rec num i = function [] -> [] | h::t -> (h,i)::(num (i+1) t) let rec map_to_list f = function | (x,y)::l -> (f y)::(map_to_list f l) | [] -> [] let rec assoc v = function | (x,y)::l -> let c = X.compare x v in if c = 0 then y else if c < 0 then assoc v l else raise Not_found | [] -> raise Not_found let rec assoc_present v = function | [(_,y)] -> y | (x,y)::l -> let c = X.compare x v in if c = 0 then y else assoc_present v l | [] -> assert false let rec compare f l1 l2 = if l1 == l2 then 0 else match (l1,l2) with | (x1,y1)::l1, (x2,y2)::l2 -> let c = X.compare x1 x2 in if c <> 0 then c else let c = f y1 y2 in if c <> 0 then c else compare f l1 l2 | [],_ -> -1 | _,[] -> 1 let rec hash f = function | [] -> 1 | (x,y)::l -> X.hash x + 17 * (f y) + 257 * (hash f l) let rec equal f l1 l2 = (l1 == l2) || match (l1,l2) with | (x1,y1)::l1, (x2,y2)::l2 -> (X.equal x1 x2) && (f y1 y2) && (equal f l1 l2) | _ -> false end module MakeMap(Y : Custom.T) = struct include Custom.Dummy type t = Y.t Map.map (* Note: need to eta expand these definitions, because of the compilation of the recursive module definitions in types.ml... *) let hash x = Map.hash Y.hash x let compare x y = Map.compare Y.compare x y let equal x y = Map.equal Y.equal x y end end