Source file OLinq_table.ml
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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
(** {1 Generic-Purpose table} *)
type 'a printer = Format.formatter -> 'a -> unit
type 'a sequence = ('a -> unit) -> unit
(** {2 Scalar Value} *)
type data =
| S of string
| I of int
| B of bool
| F of float
module Data = struct
type t = data
let equal = (=)
let compare = Pervasives.compare
let print out a = match a with
| S s -> Format.pp_print_string out s
| I i -> Format.pp_print_int out i
| F f -> Format.pp_print_float out f
| B b -> Format.pp_print_bool out b
let to_string = function
| S s -> s
| I i -> string_of_int i
| B b -> string_of_bool b
| F f -> string_of_float f
end
let string s = S s
let int i = I i
let float f = F f
let bool b = B b
(** {2 A row of values} *)
let pp_arr_ ?stop ~sep pp_item out a =
let stop = match stop with
| None -> Array.length a
| Some i -> i
in
for i=0 to stop-1 do
let x = a.(i) in
if i > 0 then (
Format.pp_print_string out sep;
Format.pp_print_cut out ()
);
pp_item out x
done
let to_string_ pp x =
let buf = Buffer.create 64 in
let out = Format.formatter_of_buffer buf in
pp out x;
Format.pp_print_flush out ();
Buffer.contents buf
type row = data array
exception IndexError
module Row = struct
type t = row
let empty = [| |]
let make1 d = [| d |]
let make2 a b = [| a; b |]
let of_array a = a
let of_list = Array.of_list
let get_exn i a =
try Array.get a i
with _ -> raise IndexError
let get i a =
try Some (get_exn i a)
with IndexError -> None
let size = Array.length
let map ~f a = Array.map f a
let append a b =
let na = size a in
Array.init (na + size b)
(fun i -> if i<na then a.(i) else b.(i-na))
let remove_index i a =
if i<0 || i>=size a then raise IndexError;
Array.init (size a-1)
(fun j-> if j<i then a.(j) else a.(j+1))
let remove_index_l _l _a = assert false
let print out a =
Format.fprintf out "[@[<hv2>%a@]]" (pp_arr_ ~sep:"; " Data.print) a
let to_string a =
to_string_ print a
end
(** {2 A Table, that is, an extensible list of Rows} *)
exception DimError
(** Raised in case dimensions don't match *)
type t = {
names: string array;
mutable rows: row array;
mutable size: int;
}
let create ?(size=256) ~names () =
{ names;
size=0;
rows=Array.make size Row.empty;
}
let init ~names n f =
{ names;
size=n;
rows=
Array.init n
(fun i ->
let row = f i in
if Row.size row <> Array.length names then raise DimError;
row);
}
let make ~names n row =
init ~names n (fun _ -> row)
let num_rows t = t.size
let num_cols t = Array.length t.names
let size = num_rows
let names t = t.names
let get_exn i t =
if i<0 || i>=t.size then raise IndexError;
t.rows.(i)
let get i t =
try Some (get_exn i t)
with IndexError -> None
let get_cell_exn i j t = Row.get_exn j (get_exn i t)
let get_cell i j t =
try Some (get_cell_exn i j t)
with IndexError -> None
let push tbl r =
if Row.size r <> Array.length tbl.names then raise DimError;
if Array.length tbl.rows = tbl.size then (
let size' = tbl.size + tbl.size / 2 + 10 in
let rows' = Array.make size' Row.empty in
Array.blit tbl.rows 0 rows' 0 tbl.size;
tbl.rows <- rows';
);
tbl.rows.(tbl.size) <- r;
tbl.size <- tbl.size + 1
let push_seq tbl seq = seq (push tbl)
let push_l tbl l = List.iter (push tbl) l
let fold ~f ~x:acc tbl =
let rec aux acc i =
if i=tbl.size then acc
else
let acc = f acc tbl.rows.(i) in
aux acc (i+1)
in
aux acc 0
let iter ~f tbl =
for i=0 to tbl.size - 1 do f tbl.rows.(i) done
let iteri ~f tbl =
for i=0 to tbl.size - 1 do f i tbl.rows.(i) done
let to_seq tbl yield = iter ~f:yield tbl
let to_list_rev tbl =
fold tbl ~f:(fun acc x -> x::acc) ~x:[]
let to_list tbl = List.rev (to_list_rev tbl)
let print out t =
Format.fprintf out "[@[<hv>%a@]]"
(pp_arr_ ~sep:"" ~stop:t.size Row.print) t.rows