32f0e4887a16f45370303f2d34267bf052933b7e
[SXSI/xpathcomp.git] / finiteCofinite.ml
1 (******************************************************************************)
2 (*  SXSI : XPath evaluator                                                    *)
3 (*  Kim Nguyen (Kim.Nguyen@nicta.com.au)                                      *)
4 (*  Copyright NICTA 2008                                                      *)
5 (*  Distributed under the terms of the LGPL (see LICENCE)                     *)
6 (******************************************************************************)
7
8 exception InfiniteSet
9 module type S = 
10 sig
11   type elt
12   type t
13   val empty : t
14   val any : t
15   val is_empty : t -> bool
16   val is_any : t -> bool
17   val is_finite : t -> bool
18   val kind : t -> [ `Finite | `Cofinite ]
19   val singleton : elt -> t
20   val mem : elt -> t -> bool
21   val add : elt -> t -> t
22   val remove : elt -> t -> t
23   val cup : t -> t -> t
24   val cap : t -> t -> t
25   val diff : t -> t -> t
26   val neg : t -> t
27   val compare : t -> t -> int
28   val subset : t -> t -> bool
29   val kind_split : t list -> t * t
30   val fold : (elt -> 'a -> 'a) -> t -> 'a -> 'a
31   val for_all : (elt -> bool) -> t -> bool
32   val exists : (elt -> bool) -> t -> bool
33   val filter : (elt -> bool) -> t -> t
34   val partition : (elt -> bool) -> t -> t * t
35   val cardinal : t -> int
36   val elements : t -> elt list
37   val from_list : elt list -> t
38   val choose : t -> elt
39   val hash : t -> int
40   val equal : t -> t -> bool
41 end
42
43 module Make (E : Sigs.Set) : S with type elt = E.elt =
44 struct
45
46   type elt = E.elt
47   type t = Finite of E.t | CoFinite of E.t
48
49
50   let empty = Finite E.empty
51   let any = CoFinite E.empty
52
53   let is_empty =  function
54       Finite s when E.is_empty s -> true
55     | _ -> false
56
57   let is_any = function
58       CoFinite s when E.is_empty s -> true
59     | _ -> false
60
61   let is_finite = function
62     | Finite _ -> true | _ -> false
63
64   let kind = function
65       Finite _ -> `Finite 
66     | _ -> `Cofinite 
67
68   let mem x = function Finite s -> E.mem x s
69     | CoFinite s -> not (E.mem x s)
70
71   let singleton x = Finite (E.singleton x)
72   let add e = function 
73     | Finite s -> Finite (E.add e s)
74     | CoFinite s -> CoFinite (E.remove e s)
75   let remove e = function
76     | Finite s -> Finite (E.remove e s)
77     | CoFinite s -> CoFinite (E.add e s)
78         
79   let cup s t = match (s,t) with
80     | Finite s, Finite t -> Finite (E.union s t)
81     | CoFinite s, CoFinite t -> CoFinite ( E.inter s t)
82     | Finite s, CoFinite t -> CoFinite (E.diff t s)
83     | CoFinite s, Finite t-> CoFinite (E.diff s t)
84
85   let cap s t = match (s,t) with
86     | Finite s, Finite t -> Finite (E.inter s t)
87     | CoFinite s, CoFinite t -> CoFinite (E.union s t)
88     | Finite s, CoFinite t -> Finite (E.diff s t)
89     | CoFinite s, Finite t-> Finite (E.diff t s)
90         
91   let diff s t = match (s,t) with
92     | Finite s, Finite t -> Finite (E.diff s t)
93     | Finite s, CoFinite t -> Finite(E.inter s t)
94     | CoFinite s, Finite t -> CoFinite(E.union t s)
95     | CoFinite s, CoFinite t -> Finite (E.diff t s)
96
97   let neg = function 
98     | Finite s -> CoFinite s
99     | CoFinite s -> Finite s
100         
101   let compare s t = match (s,t) with
102     | Finite s , Finite t -> E.compare s t
103     | CoFinite s , CoFinite t -> E.compare t s
104     | Finite _, CoFinite _ -> -1
105     | CoFinite _, Finite _ -> 1
106         
107   let subset s t = match (s,t) with
108     | Finite s , Finite t -> E.subset s t
109     | CoFinite s , CoFinite t -> E.subset t s
110     | Finite s, CoFinite t -> E.is_empty (E.inter s t)
111     | CoFinite _, Finite _ -> false
112
113         (* given a  list l of type t list, 
114            returns two sets (f,c) where :
115            - f is the union of all the finite sets of l
116            - c is the union of all the cofinite sets of l
117            - f and c are disjoint
118            Invariant : cup f c = List.fold_left cup empty l
119
120            We treat the CoFinite part explicitely :
121         *)
122
123   let kind_split l =
124     
125     let rec next_finite_cofinite facc cacc = function 
126       | [] -> Finite facc, CoFinite (E.diff cacc facc)
127       | Finite s ::r -> next_finite_cofinite (E.union s facc) cacc r
128       | CoFinite _ ::r when E.is_empty cacc -> next_finite_cofinite facc cacc r
129       | CoFinite s ::r -> next_finite_cofinite facc (E.inter cacc s) r
130     in
131     let rec first_cofinite facc = function
132       | [] -> empty,empty
133       | Finite s :: r-> first_cofinite (E.union s facc) r
134       | CoFinite s :: r -> next_finite_cofinite facc s r  
135     in
136       first_cofinite E.empty l
137         
138   let fold f t a = match t with
139     | Finite s -> E.fold f s a
140     | CoFinite _ -> raise InfiniteSet
141
142   let for_all f = function
143     | Finite s -> E.for_all f s
144     | CoFinite _ -> raise InfiniteSet
145
146   let exists f = function
147     | Finite s -> E.exists f s
148     | CoFinite _ -> raise InfiniteSet
149
150   let filter f = function
151     | Finite s -> Finite (E.filter f s)
152     | CoFinite _ -> raise InfiniteSet
153
154   let partition f = function
155     | Finite s -> let a,b = E.partition f s in Finite a,Finite b
156     | CoFinite _ -> raise InfiniteSet
157
158   let cardinal = function
159     | Finite s -> E.cardinal s
160     | CoFinite _ -> raise InfiniteSet
161
162   let elements = function
163     | Finite s -> E.elements s
164     | CoFinite _ -> raise InfiniteSet
165         
166   let from_list l = 
167     Finite(List.fold_left (fun x a -> E.add a x ) E.empty l)
168
169   let choose = function
170       Finite s -> E.choose s
171     | _ -> raise InfiniteSet
172
173   let equal a b = 
174     match a,b with
175       | Finite x, Finite y | CoFinite x, CoFinite y -> E.equal x y
176       | _ -> false
177
178   let hash = 
179     function Finite x -> (E.hash x)
180       | CoFinite x -> ( ~-(E.hash x) land max_int)
181
182 end
183