~ubuntu-branches/debian/sid/frama-c/sid

« back to all changes in this revision

Viewing changes to cil/ocamlutil/setWithNearest.ml

  • Committer: Bazaar Package Importer
  • Author(s): Mehdi Dogguy
  • Date: 2009-06-03 08:19:25 UTC
  • Revision ID: james.westby@ubuntu.com-20090603081925-kihvxvt0wy3zc4ar
Tags: upstream-20081201.dfsg
ImportĀ upstreamĀ versionĀ 20081201.dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
(**************************************************************************)
 
2
(*                                                                        *)
 
3
(*  Copyright (C) 2001-2003,                                              *)
 
4
(*   George C. Necula    <necula@cs.berkeley.edu>                         *)
 
5
(*   Scott McPeak        <smcpeak@cs.berkeley.edu>                        *)
 
6
(*   Wes Weimer          <weimer@cs.berkeley.edu>                         *)
 
7
(*   Ben Liblit          <liblit@cs.berkeley.edu>                         *)
 
8
(*  All rights reserved.                                                  *)
 
9
(*                                                                        *)
 
10
(*  Redistribution and use in source and binary forms, with or without    *)
 
11
(*  modification, are permitted provided that the following conditions    *)
 
12
(*  are met:                                                              *)
 
13
(*                                                                        *)
 
14
(*  1. Redistributions of source code must retain the above copyright     *)
 
15
(*  notice, this list of conditions and the following disclaimer.         *)
 
16
(*                                                                        *)
 
17
(*  2. Redistributions in binary form must reproduce the above copyright  *)
 
18
(*  notice, this list of conditions and the following disclaimer in the   *)
 
19
(*  documentation and/or other materials provided with the distribution.  *)
 
20
(*                                                                        *)
 
21
(*  3. The names of the contributors may not be used to endorse or        *)
 
22
(*  promote products derived from this software without specific prior    *)
 
23
(*  written permission.                                                   *)
 
24
(*                                                                        *)
 
25
(*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   *)
 
26
(*  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT     *)
 
27
(*  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS     *)
 
28
(*  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE        *)
 
29
(*  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,   *)
 
30
(*  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,  *)
 
31
(*  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;      *)
 
32
(*  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER      *)
 
33
(*  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT    *)
 
34
(*  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN     *)
 
35
(*  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE       *)
 
36
(*  POSSIBILITY OF SUCH DAMAGE.                                           *)
 
37
(*                                                                        *)
 
38
(*  File modified by CEA (Commissariat ļæ½ l'ļæ½nergie Atomique).             *)
 
39
(**************************************************************************)
 
40
 
 
41
(******************************************************************)
 
42
(* Derived from the file Set.ml of the Objective Caml library     *)
 
43
(* No function modification, only extra functions have been added *)
 
44
(******************************************************************)
 
45
 
 
46
(* Sets over ordered types *)
 
47
 
 
48
module type OrderedType =
 
49
  sig
 
50
    include Set.OrderedType
 
51
  end
 
52
 
 
53
module type S =
 
54
  sig
 
55
    include Set.S
 
56
    val nearest_elt_le: elt -> t -> elt
 
57
    val nearest_elt_ge: elt -> t -> elt
 
58
  end
 
59
 
 
60
module Make(Ord: OrderedType) =
 
61
  struct
 
62
    type elt = Ord.t
 
63
    type t = Empty | Node of t * elt * t * int
 
64
 
 
65
    (* Sets are represented by balanced binary trees (the heights of the
 
66
       children differ by at most 2 *)
 
67
 
 
68
    let height = function
 
69
        Empty -> 0
 
70
      | Node(_, _, _, h) -> h
 
71
 
 
72
    (* Creates a new node with left son l, value v and right son r.
 
73
       We must have all elements of l < v < all elements of r.
 
74
       l and r must be balanced and | height l - height r | <= 2.
 
75
       Inline expansion of height for better speed. *)
 
76
 
 
77
    let create l v r =
 
78
      let hl = match l with Empty -> 0 | Node(_,_,_,h) -> h in
 
79
      let hr = match r with Empty -> 0 | Node(_,_,_,h) -> h in
 
80
      Node(l, v, r, (if hl >= hr then hl + 1 else hr + 1))
 
81
 
 
82
    (* Same as create, but performs one step of rebalancing if necessary.
 
83
       Assumes l and r balanced and | height l - height r | <= 3.
 
84
       Inline expansion of create for better speed in the most frequent case
 
85
       where no rebalancing is required. *)
 
86
 
 
87
    let bal l v r =
 
88
      let hl = match l with Empty -> 0 | Node(_,_,_,h) -> h in
 
89
      let hr = match r with Empty -> 0 | Node(_,_,_,h) -> h in
 
90
      if hl > hr + 2 then begin
 
91
        match l with
 
92
          Empty -> invalid_arg "Set.bal"
 
93
        | Node(ll, lv, lr, _) ->
 
94
            if height ll >= height lr then
 
95
              create ll lv (create lr v r)
 
96
            else begin
 
97
              match lr with
 
98
                Empty -> invalid_arg "Set.bal"
 
99
              | Node(lrl, lrv, lrr, _)->
 
100
                  create (create ll lv lrl) lrv (create lrr v r)
 
101
            end
 
102
      end else if hr > hl + 2 then begin
 
103
        match r with
 
104
          Empty -> invalid_arg "Set.bal"
 
105
        | Node(rl, rv, rr, _) ->
 
106
            if height rr >= height rl then
 
107
              create (create l v rl) rv rr
 
108
            else begin
 
109
              match rl with
 
110
                Empty -> invalid_arg "Set.bal"
 
111
              | Node(rll, rlv, rlr, _) ->
 
112
                  create (create l v rll) rlv (create rlr rv rr)
 
113
            end
 
114
      end else
 
115
        Node(l, v, r, (if hl >= hr then hl + 1 else hr + 1))
 
116
 
 
117
    (* Insertion of one element *)
 
118
 
 
119
    let rec add x = function
 
120
        Empty -> Node(Empty, x, Empty, 1)
 
121
      | Node(l, v, r, _) as t ->
 
122
          let c = Ord.compare x v in
 
123
          if c = 0 then t else
 
124
          if c < 0 then bal (add x l) v r else bal l v (add x r)
 
125
 
 
126
    (* Same as create and bal, but no assumptions are made on the
 
127
       relative heights of l and r. *)
 
128
 
 
129
    let rec join l v r =
 
130
      match (l, r) with
 
131
        (Empty, _) -> add v r
 
132
      | (_, Empty) -> add v l
 
133
      | (Node(ll, lv, lr, lh), Node(rl, rv, rr, rh)) ->
 
134
          if lh > rh + 2 then bal ll lv (join lr v r) else
 
135
          if rh > lh + 2 then bal (join l v rl) rv rr else
 
136
          create l v r
 
137
 
 
138
    (* Smallest and greatest element of a set *)
 
139
 
 
140
    let rec min_elt = function
 
141
        Empty -> raise Not_found
 
142
      | Node(Empty, v, _r, _) -> v
 
143
      | Node(l, _v, _r, _) -> min_elt l
 
144
 
 
145
    let rec max_elt = function
 
146
        Empty -> raise Not_found
 
147
      | Node(_l, v, Empty, _) -> v
 
148
      | Node(_l, _v, r, _) -> max_elt r
 
149
 
 
150
    (* Remove the smallest element of the given set *)
 
151
 
 
152
    let rec remove_min_elt = function
 
153
        Empty -> invalid_arg "Set.remove_min_elt"
 
154
      | Node(Empty, _v, r, _) -> r
 
155
      | Node(l, v, r, _) -> bal (remove_min_elt l) v r
 
156
 
 
157
    (* Merge two trees l and r into one.
 
158
       All elements of l must precede the elements of r.
 
159
       Assume | height l - height r | <= 2. *)
 
160
 
 
161
    let merge t1 t2 =
 
162
      match (t1, t2) with
 
163
        (Empty, t) -> t
 
164
      | (t, Empty) -> t
 
165
      | (_, _) -> bal t1 (min_elt t2) (remove_min_elt t2)
 
166
 
 
167
    (* Merge two trees l and r into one.
 
168
       All elements of l must precede the elements of r.
 
169
       No assumption on the heights of l and r. *)
 
170
 
 
171
    let concat t1 t2 =
 
172
      match (t1, t2) with
 
173
        (Empty, t) -> t
 
174
      | (t, Empty) -> t
 
175
      | (_, _) -> join t1 (min_elt t2) (remove_min_elt t2)
 
176
 
 
177
    (* Splitting.  split x s returns a triple (l, present, r) where
 
178
        - l is the set of elements of s that are < x
 
179
        - r is the set of elements of s that are > x
 
180
        - present is false if s contains no element equal to x,
 
181
          or true if s contains an element equal to x. *)
 
182
 
 
183
    let rec split x = function
 
184
        Empty ->
 
185
          (Empty, false, Empty)
 
186
      | Node(l, v, r, _) ->
 
187
          let c = Ord.compare x v in
 
188
          if c = 0 then (l, true, r)
 
189
          else if c < 0 then
 
190
            let (ll, pres, rl) = split x l in (ll, pres, join rl v r)
 
191
          else
 
192
            let (lr, pres, rr) = split x r in (join l v lr, pres, rr)
 
193
 
 
194
    (* Implementation of the set operations *)
 
195
 
 
196
    let empty = Empty
 
197
 
 
198
    let is_empty = function Empty -> true | _ -> false
 
199
 
 
200
    let rec mem x = function
 
201
        Empty -> false
 
202
      | Node(l, v, r, _) ->
 
203
          let c = Ord.compare x v in
 
204
          c = 0 || mem x (if c < 0 then l else r)
 
205
 
 
206
    let singleton x = Node(Empty, x, Empty, 1)
 
207
 
 
208
    let rec remove x = function
 
209
        Empty -> Empty
 
210
      | Node(l, v, r, _) ->
 
211
          let c = Ord.compare x v in
 
212
          if c = 0 then merge l r else
 
213
          if c < 0 then bal (remove x l) v r else bal l v (remove x r)
 
214
 
 
215
    let rec union s1 s2 =
 
216
      match (s1, s2) with
 
217
        (Empty, t2) -> t2
 
218
      | (t1, Empty) -> t1
 
219
      | (Node(l1, v1, r1, h1), Node(l2, v2, r2, h2)) ->
 
220
          if h1 >= h2 then
 
221
            if h2 = 1 then add v2 s1 else begin
 
222
              let (l2, _, r2) = split v1 s2 in
 
223
              join (union l1 l2) v1 (union r1 r2)
 
224
            end
 
225
          else
 
226
            if h1 = 1 then add v1 s2 else begin
 
227
              let (l1, _, r1) = split v2 s1 in
 
228
              join (union l1 l2) v2 (union r1 r2)
 
229
            end
 
230
 
 
231
    let rec inter s1 s2 =
 
232
      match (s1, s2) with
 
233
        (Empty, _t2) -> Empty
 
234
      | (_t1, Empty) -> Empty
 
235
      | (Node(l1, v1, r1, _), t2) ->
 
236
          match split v1 t2 with
 
237
            (l2, false, r2) ->
 
238
              concat (inter l1 l2) (inter r1 r2)
 
239
          | (l2, true, r2) ->
 
240
              join (inter l1 l2) v1 (inter r1 r2)
 
241
 
 
242
    let rec diff s1 s2 =
 
243
      match (s1, s2) with
 
244
        (Empty, _t2) -> Empty
 
245
      | (t1, Empty) -> t1
 
246
      | (Node(l1, v1, r1, _), t2) ->
 
247
          match split v1 t2 with
 
248
            (l2, false, r2) ->
 
249
              join (diff l1 l2) v1 (diff r1 r2)
 
250
          | (l2, true, r2) ->
 
251
              concat (diff l1 l2) (diff r1 r2)
 
252
 
 
253
    type enumeration = End | More of elt * t * enumeration
 
254
 
 
255
    let rec cons_enum s e =
 
256
      match s with
 
257
        Empty -> e
 
258
      | Node(l, v, r, _) -> cons_enum l (More(v, r, e))
 
259
 
 
260
    let rec compare_aux e1 e2 =
 
261
        match (e1, e2) with
 
262
        (End, End) -> 0
 
263
      | (End, _)  -> -1
 
264
      | (_, End) -> 1
 
265
      | (More(v1, r1, e1), More(v2, r2, e2)) ->
 
266
          let c = Ord.compare v1 v2 in
 
267
          if c <> 0
 
268
          then c
 
269
          else compare_aux (cons_enum r1 e1) (cons_enum r2 e2)
 
270
 
 
271
    let compare s1 s2 =
 
272
      compare_aux (cons_enum s1 End) (cons_enum s2 End)
 
273
 
 
274
    let equal s1 s2 =
 
275
      compare s1 s2 = 0
 
276
 
 
277
    let rec subset s1 s2 =
 
278
      match (s1, s2) with
 
279
        Empty, _ ->
 
280
          true
 
281
      | _, Empty ->
 
282
          false
 
283
      | Node (l1, v1, r1, _), (Node (l2, v2, r2, _) as t2) ->
 
284
          let c = Ord.compare v1 v2 in
 
285
          if c = 0 then
 
286
            subset l1 l2 && subset r1 r2
 
287
          else if c < 0 then
 
288
            subset (Node (l1, v1, Empty, 0)) l2 && subset r1 t2
 
289
          else
 
290
            subset (Node (Empty, v1, r1, 0)) r2 && subset l1 t2
 
291
 
 
292
    let rec iter f = function
 
293
        Empty -> ()
 
294
      | Node(l, v, r, _) -> iter f l; f v; iter f r
 
295
 
 
296
    let rec fold f s accu =
 
297
      match s with
 
298
        Empty -> accu
 
299
      | Node(l, v, r, _) -> fold f r (f v (fold f l accu))
 
300
 
 
301
    let rec for_all p = function
 
302
        Empty -> true
 
303
      | Node(l, v, r, _) -> p v && for_all p l && for_all p r
 
304
 
 
305
    let rec exists p = function
 
306
        Empty -> false
 
307
      | Node(l, v, r, _) -> p v || exists p l || exists p r
 
308
 
 
309
    let filter p s =
 
310
      let rec filt accu = function
 
311
        | Empty -> accu
 
312
        | Node(l, v, r, _) ->
 
313
            filt (filt (if p v then add v accu else accu) l) r in
 
314
      filt Empty s
 
315
 
 
316
    let partition p s =
 
317
      let rec part (t, f as accu) = function
 
318
        | Empty -> accu
 
319
        | Node(l, v, r, _) ->
 
320
            part (part (if p v then (add v t, f) else (t, add v f)) l) r in
 
321
      part (Empty, Empty) s
 
322
 
 
323
    let rec cardinal = function
 
324
        Empty -> 0
 
325
      | Node(l, _v, r, _) -> cardinal l + 1 + cardinal r
 
326
 
 
327
    let rec elements_aux accu = function
 
328
        Empty -> accu
 
329
      | Node(l, v, r, _) -> elements_aux (v :: elements_aux accu r) l
 
330
 
 
331
    let elements s =
 
332
      elements_aux [] s
 
333
 
 
334
    let choose = min_elt
 
335
 
 
336
    (************************* Extra functions **************************)
 
337
 
 
338
    (* The nearest value of [s] le [v]. Raise Not_found if none *)
 
339
    let rec nearest_elt_le x = function
 
340
        Empty ->
 
341
          raise Not_found
 
342
      | Node(l, v, r, _) ->
 
343
          let c = Ord.compare x v in
 
344
            if c = 0 then v
 
345
            else if c < 0 then
 
346
              nearest_elt_le x l
 
347
            else
 
348
              let rec nearest w x = function
 
349
                  Empty -> w
 
350
                | Node(l, v, r, _) ->
 
351
                    let c = Ord.compare x v in
 
352
                      if c = 0 then v
 
353
                      else if c < 0 then
 
354
                        nearest w x l
 
355
                      else
 
356
                        nearest v x r
 
357
              in nearest v x r
 
358
 
 
359
    (* The nearest value of [s] ge [v]. Raise Not_found if none *)
 
360
    let rec nearest_elt_ge x = function
 
361
        Empty ->
 
362
          raise Not_found
 
363
      | Node(l, v, r, _) ->
 
364
          let c = Ord.compare x v in
 
365
            if c = 0 then v
 
366
            else if c < 0 then
 
367
              let rec nearest w x = function
 
368
                  Empty -> w
 
369
                | Node(l, v, r, _) ->
 
370
                    let c = Ord.compare x v in
 
371
                      if c = 0 then v
 
372
                      else if c < 0 then
 
373
                        nearest v x l
 
374
                      else
 
375
                        nearest w x r
 
376
              in nearest v x l
 
377
            else
 
378
              nearest_elt_ge x r
 
379
  end