X-Git-Url: http://matita.cs.unibo.it/gitweb/?a=blobdiff_plain;f=helm%2Fsoftware%2Fcomponents%2Fextlib%2FhExtlib.ml;h=0b13cd83e4566013b74ec3b18019c4d2e542482d;hb=145583de619b9d2fcc4abe3f4d68d01538f9f394;hp=13dd2f2665da9fa8f8aed93c542d18b20ebf2c15;hpb=c717e9d642a19ed5f0b9ac4e3c206942ee0b44cc;p=helm.git diff --git a/helm/software/components/extlib/hExtlib.ml b/helm/software/components/extlib/hExtlib.ml index 13dd2f266..0b13cd83e 100644 --- a/helm/software/components/extlib/hExtlib.ml +++ b/helm/software/components/extlib/hExtlib.ml @@ -331,47 +331,67 @@ let rec list_assoc_all a = function | _ :: tl -> list_assoc_all a tl ;; -let rec rm_assoc n = function - | [] -> assert false - | (x,i)::tl when n=x -> i,tl - | p::tl -> let i,tl = rm_assoc n tl in i,p::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 n m = - let cn,canonicals = rm_assoc n canonicals in - let cm,canonicals = rm_assoc m canonicals in - let ln,elements = rm_assoc cn elements in - let lm,elements = rm_assoc 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 +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) and (f x) must - be a subset of l *) +(* 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 _,elements = + let extern = [] in + let _,elements,extern = List.fold_left - (fun (canonicals,elements) x -> + (fun (canonicals,elements,extern) x -> let dep = f x in List.fold_left - (fun (canonicals,elements) d -> - merge canonicals elements d x) - (canonicals,elements) dep) - (canonicals,elements) l + (fun (canonicals,elements,extern) d -> + merge canonicals elements extern d x) + (canonicals,elements,extern) dep) + (canonicals,elements,extern) l in - List.map snd elements + let c = (List.map snd elements) in + if extern = [] then c else extern::c ;; (** {2 File predicates} *)