-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathpersistent_array.ml
More file actions
60 lines (51 loc) · 1.35 KB
/
Copy pathpersistent_array.ml
File metadata and controls
60 lines (51 loc) · 1.35 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
(* Module taken from the work of Sylvain Conchon
* and Jean-Christophe Filliatre *)
type 'a t = 'a data ref
and 'a data =
| Arr of int array
| Diff of int * 'a * 'a t
| Invalid
let init n f = ref (Arr (Array.init n f))
let rec length pa =
match !pa with
| Arr a -> Array.length a
| Diff (i, v, pa') -> length pa'
| Invalid -> assert false
let rec expand pa n f =
match !pa with
| Arr a -> ref (Arr (Array.init (Array.length a + n)
(fun i -> if i < Array.length a
then a.(i) else f i)))
| Diff (i, v, pa') -> ref (Diff (i, v, expand pa' n f))
| Invalid -> assert false
let rec reroot t = match !t with
| Arr _ -> ()
| Diff (i, v, t') ->
reroot t';
begin match !t' with
| Arr a as n ->
a.(i) <- v;
t := n;
t' := Invalid
| Diff _ | Invalid -> assert false
end
| Invalid -> assert false
let set t i v =
reroot t;
match !t with
| Arr a as n ->
let old = a.(i) in
a.(i) <- v;
let res = ref n in
t := Diff (i, old, res);
res
| Diff _ | Invalid -> assert false
let rec get t i = match !t with
| Arr a -> a.(i)
| Diff _ ->
reroot t;
begin match !t with
| Arr a -> a.(i)
| Diff _ | Invalid -> assert false
end
| Invalid -> assert false