X-Git-Url: http://matita.cs.unibo.it/gitweb/?a=blobdiff_plain;f=helm%2Fsoftware%2Fcomponents%2Fextlib%2FhExtlib.ml;h=0b13cd83e4566013b74ec3b18019c4d2e542482d;hb=145583de619b9d2fcc4abe3f4d68d01538f9f394;hp=cccb467674e22415b59de320e72cbbe845812142;hpb=571d199acd4e6743a48f8f64f28c62d18182d04d;p=helm.git diff --git a/helm/software/components/extlib/hExtlib.ml b/helm/software/components/extlib/hExtlib.ml index cccb46767..0b13cd83e 100644 --- a/helm/software/components/extlib/hExtlib.ml +++ b/helm/software/components/extlib/hExtlib.ml @@ -211,6 +211,19 @@ let sharing_map f l = if !unchanged then l else l1 ;; +let sharing_map_acc f acc l = + let unchanged = ref true in + let final_acc = ref acc in + let rec aux b acc = function + | [] as t -> unchanged := b; final_acc := acc; t + | he::tl -> + let acc, he1 = f acc he in + he1 :: aux (b && he1 == he) acc tl + in + let l1 = aux true acc l in + !final_acc, if !unchanged then l else l1 +;; + let rec list_uniq ?(eq=(=)) = function | [] -> [] | h::[] -> [h] @@ -318,6 +331,69 @@ let rec list_assoc_all a = function | _ :: tl -> list_assoc_all a tl ;; +let rec rm_assoc_option n = function + | [] -> None,[] + | (x,i)::tl when n=x -> Some i,tl + | p::tl -> let i,tl = rm_assoc_option n tl in i,p::tl +;; + +let rm_assoc_assert n l = + match rm_assoc_option n l with + | None,_ -> assert false + | Some i,l -> i,l +;; + +(* naif implementation of the union-find merge operation + canonicals maps elements to canonicals + elements maps canonicals to the classes *) +let merge canonicals elements extern n m = + let cn,canonicals = rm_assoc_option n canonicals in + let cm,canonicals = rm_assoc_option m canonicals in + match cn,cm with + | None, None -> canonicals, elements, extern + | None, Some c + | Some c, None -> + let l,elements = rm_assoc_assert c elements in + let canonicals = + List.filter (fun (_,xc) -> not (xc = c)) canonicals + in + canonicals,elements,l@extern + | Some cn, Some cm when cn=cm -> + (n,cm)::(m,cm)::canonicals, elements, extern + | Some cn, Some cm -> + let ln,elements = rm_assoc_assert cn elements in + let lm,elements = rm_assoc_assert cm elements in + let canonicals = + (n,cm)::(m,cm)::List.map + (fun ((x,xc) as p) -> + if xc = cn then (x,cm) else p) canonicals + in + let elements = (cm,ln@lm)::elements + in + canonicals,elements,extern +;; + +(* f x gives the direct dependencies of x. + x must not belong to (f x). + All elements not in l are merged into a single extern class *) +let clusters f l = + let canonicals = List.map (fun x -> (x,x)) l in + let elements = List.map (fun x -> (x,[x])) l in + let extern = [] in + let _,elements,extern = + List.fold_left + (fun (canonicals,elements,extern) x -> + let dep = f x in + List.fold_left + (fun (canonicals,elements,extern) d -> + merge canonicals elements extern d x) + (canonicals,elements,extern) dep) + (canonicals,elements,extern) l + in + let c = (List.map snd elements) in + if extern = [] then c else extern::c +;; + (** {2 File predicates} *) let is_dir fname =