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