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
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
let parallel_for ?(n_fibers = 1) ~start ~finish body =
let chunk_size = (finish - start + 1) / n_fibers in
let rec work bundle s e =
if e - s < chunk_size then
for i = s to e do
body i
done
else
let d = s + ((e - s) / 2) in
Picos_std_structured.Bundle.fork bundle (fun () -> work bundle s d);
work bundle (d + 1) e
in
Picos_std_structured.Bundle.join_after (fun bundle ->
work bundle start finish)
let parallel_for_reduce ?(n_fibers = 1) ~start ~finish ~body reduce_fn init =
let chunk_size = (finish - start + 1) / n_fibers in
let rec work bundle s e =
if e - s < chunk_size then
let rec loop i acc =
if i > e then acc else loop (i + 1) (reduce_fn acc (body i))
in
loop (s + 1) (body s)
else
let d = s + ((e - s) / 2) in
let p =
Picos_std_structured.Bundle.fork_as_promise bundle (fun _ ->
work bundle s d)
in
let right = work bundle (d + 1) e in
let left = Picos_std_structured.Promise.await p in
reduce_fn left right
in
if finish < start then init
else
reduce_fn init
(Picos_std_structured.Bundle.join_after (fun bundle ->
work bundle start finish))
module Finite_vector = struct
type 'a data = Empty of int | Buf of 'a array
let capacity = function Empty n -> n | Buf a -> Array.length a
type 'a t = { mutable size : int; mutable buf : 'a data }
let length t = t.size
let pp f fmt t =
match t.buf with
| Empty cap ->
Format.fprintf fmt "[| %s |]"
(String.concat "; " (List.init cap (fun _ -> "_")))
| Buf arr ->
Format.fprintf fmt "[| %a |]"
(Format.pp_print_list
~pp_sep:(fun fmt _ -> Format.fprintf fmt "; ")
(fun fmt -> function
| None -> Format.fprintf fmt "_"
| Some vl -> f fmt vl))
(List.init (Array.length arr) (fun i ->
if i < t.size then Some arr.(i) else None))
let init ?(capacity = 8) () = { size = 0; buf = Empty capacity }
let init_with ?(capacity = 8) n f =
let capacity = max n capacity in
let n = max n 0 in
if n = 0 then { size = 0; buf = Empty capacity }
else
let saved = ref None in
let arr =
Array.init capacity (fun i ->
if i = n - 1 then (
let res = f i in
saved := Some res;
res)
else if i < n then f i
else Option.get !saved)
in
{ size = n; buf = Buf arr }
let singleton ?(capacity = 8) v =
{ size = 1; buf = Buf (Array.make capacity v) }
let to_array t =
match t.buf with Empty _ -> [||] | Buf a -> Array.sub a 0 t.size
let get t i =
if t.size <= i then invalid_arg "invalid index for dereference";
match t.buf with
| Empty _ -> failwith "found empty buf"
| Buf arr -> arr.(i)
let set t i vl =
if t.size <= i then invalid_arg "invalid index for dereference";
match t.buf with
| Empty _ -> failwith "found empty buf"
| Buf arr -> arr.(i) <- vl
let fold_left f x a =
match a.buf with
| Empty _ -> x
| Buf arr ->
let r = ref x in
for i = 0 to a.size - 1 do
r := f !r (Array.unsafe_get arr i)
done;
!r
let iter f a =
match a.buf with
| Empty _ -> ()
| Buf arr ->
for i = 0 to a.size - 1 do
f (Array.unsafe_get arr i)
done
let split_from t index =
if t.size < index || index < 0 then invalid_arg "splitting by invalid index";
match t.buf with
| Empty n -> { size = 0; buf = Empty n }
| Buf arr ->
let new_arr =
Array.init (Array.length arr) (fun i ->
if index + i < t.size then arr.(index + i) else arr.(t.size - 1))
in
let upper_buffer = { size = t.size - index; buf = Buf new_arr } in
t.size <- index;
upper_buffer
let drop_last t =
if t.size <= 0 then invalid_arg "attempt to drop last on empty array";
(if t.size > 1 then
match t.buf with
| Empty _ -> assert false
| Buf arr -> arr.(t.size - 1) <- arr.(t.size - 2));
t.size <- t.size - 1
let insert t i vl =
if t.size >= capacity t.buf then failwith "out of capacity";
if i >= t.size + 1 then invalid_arg "invalid index for insert";
match t.buf with
| Empty cap ->
let arr = Array.make cap vl in
t.size <- i + 1;
t.buf <- Buf arr
| Buf arr ->
for j = t.size downto i + 1 do
arr.(j) <- arr.(j - 1)
done;
t.size <- t.size + 1;
arr.(i) <- vl
let clip t i =
if i > t.size then invalid_arg "attempt to clip larger than size";
if i < 0 then invalid_arg "invalid clip size less than 0";
match t.buf with
| Empty _ -> ()
| Buf arr ->
if i > 0 then (
for j = i to t.size do
arr.(j) <- arr.(j - 1)
done;
t.size <- i)
else (
t.buf <- Empty (Array.length arr);
t.size <- 0)
end