blob: 59ce6fb9cb20dfae4bdd7efd5558c8296d78c73e (
plain)
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
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
|
(***********************************************************************)
(* v * The Coq Proof Assistant / The Coq Development Team *)
(* <O___,, * INRIA-Rocquencourt & LRI-CNRS-Orsay *)
(* \VV/ *************************************************************)
(* // * This file is distributed under the terms of the *)
(* * GNU Lesser General Public License Version 2.1 *)
(***********************************************************************)
module type US =
sig
type +'a t
(** We put it covariant even though it isn't, as we're going to use it purely
functionnaly. *)
val length : 'a t -> int
val create : int -> 'a t
val copy : 'a t -> 'a t
val get : 'a t -> int -> 'a
val set : 'a t -> int -> 'a -> unit
end
(** Minimal signature of unsafe arrays *)
module ObjArray =
struct
type +'a t = Obj.t
type dummy = int option
(** We choose this type such that:
1. It is not a float, not to trigger the float unboxing mechanism
2. It is not a scalar, to ensure calling of the caml_copy function,
otherwise that may result in strange GC behaviour.
*)
let length = Obj.size
let create len = Obj.new_block 0 len
let copy obj = Obj.dup obj
let get (obj : 'a t) i : 'a =
let obj : dummy array = Obj.magic obj in
let ans = Array.unsafe_get obj i in
Obj.magic ans
let set (obj : 'a t) i (x : 'a) =
let x : dummy = Obj.magic x in
let obj : dummy array = Obj.magic obj in
Array.unsafe_set obj i x
end
module Make(M : US) =
struct
type +'a t = 'a M.t
let length = M.length
let get t i =
if i < 0 || M.length t <= i then
invalid_arg "Array.get"
else
M.get t i
(* let set t i x =
if i < 0 || M.length t <= i then
invalid_arg "Array.set"
else
M.set t i x *)
let make len x =
let ans = M.create len in
let () =
for i = 0 to pred len do
M.set ans i x
done
in
ans
let copy = M.copy
let init len f =
let ans = M.create len in
let () =
for i = 0 to pred len do
M.set ans i (f i)
done
in
ans
let append t1 t2 =
let len1 = M.length t1 in
let len2 = M.length t2 in
let ans = M.create (len1 + len2) in
let () =
for i = 0 to pred len1 do
M.set ans i (M.get t1 i)
done
in
let () =
for i = 0 to pred len2 do
M.set ans (len1 + i) (M.get t2 i)
done
in
ans
let concat l =
let rec len accu = function
| [] -> accu
| t :: l -> len (M.length t + accu) l
in
let len = len 0 l in
let ans = M.create len in
let rec iter off = function
| [] -> ()
| t :: l ->
let len = M.length t in
let () =
for i = 0 to pred len do
M.set ans (off + i) (M.get t i)
done
in
iter (off + len) l
in
let () = iter 0 l in
ans
let sub t off len =
let tlen = M.length t in
let () = if off < 0 || off + len > tlen then
invalid_arg "Array.sub"
in
let ans = M.create len in
let () =
for i = 0 to len - 1 do
M.set ans i (M.get t (off + i))
done
in
ans
let of_list l =
let len = List.length l in
let ans = M.create len in
let rec iter off = function
| [] -> ()
| x :: l ->
let () = M.set ans off x in
iter (succ off) l
in
let () = iter 0 l in
ans
let to_list t =
let rec iter off accu =
if off < 0 then accu
else iter (pred off) (M.get t off :: accu)
in
iter (M.length t - 1) []
let iter f t =
for i = 0 to M.length t - 1 do
f (M.get t i)
done
let iteri f t =
for i = 0 to M.length t - 1 do
f i (M.get t i)
done
let map f t =
let len = M.length t in
let ans = M.create len in
let () =
for i = 0 to pred len do
M.set ans i (f (M.get t i))
done
in
ans
let mapi f t =
let len = M.length t in
let ans = M.create len in
let () =
for i = 0 to pred len do
M.set ans i (f i (M.get t i))
done
in
ans
let fold_right f accu t =
let rec fold i accu =
if i < 0 then accu
else fold (pred i) (f (M.get t i) accu)
in
fold (M.length t - 1) accu
let fold_left f accu t =
let len = M.length t in
let rec fold i accu =
if len <= i then accu
else fold (succ i) (f accu (M.get t i))
in
fold 0 accu
end
module M = Make(ObjArray)
include M
module Unsafe =
struct
let get = ObjArray.get
let set = ObjArray.set
let of_array (t : 'a array) : 'a ObjArray.t =
let tag = Obj.tag (Obj.repr t) in
let () = if tag = Obj.double_array_tag then
invalid_arg "Array.of_array"
in
Obj.magic t
let to_array (t : 'a ObjArray.t) : 'a array =
if Obj.size t = 0 then [||]
else
let dummy = Obj.field t 0 in
let () = if Obj.tag dummy = Obj.double_tag then
invalid_arg "Array.to_array"
in
Obj.magic t
end
|