1
+ (* Copyright (C) 2015-2016 Bloomberg Finance L.P.
2
+ *
3
+ * This program is free software: you can redistribute it and/or modify
4
+ * it under the terms of the GNU Lesser General Public License as published by
5
+ * the Free Software Foundation, either version 3 of the License, or
6
+ * (at your option) any later version.
7
+ *
8
+ * In addition to the permissions granted to you by the LGPL, you may combine
9
+ * or link a "work that uses the Library" with a publicly distributed version
10
+ * of this file to produce a combined library or application, then distribute
11
+ * that combined work under the terms of your choosing, with no requirement
12
+ * to comply with the obligations normally placed on you by section 4 of the
13
+ * LGPL version 3 (or the corresponding section of a later version of the LGPL
14
+ * should you choose to use a later version).
15
+ *
16
+ * This program is distributed in the hope that it will be useful,
17
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
18
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19
+ * GNU Lesser General Public License for more details.
20
+ *
21
+ * You should have received a copy of the GNU Lesser General Public License
22
+ * along with this program; if not, write to the Free Software
23
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *)
24
+
25
+
26
+
27
+
28
+
29
+ let reverse_range a i len =
30
+ if len = 0 then ()
31
+ else
32
+ for k = 0 to (len-1 )/ 2 do
33
+ let t = Array. unsafe_get a (i+ k) in
34
+ Array. unsafe_set a (i+ k) ( Array. unsafe_get a (i+ len-1 - k));
35
+ Array. unsafe_set a (i+ len-1 - k) t;
36
+ done
37
+
38
+
39
+ let reverse_in_place a =
40
+ reverse_range a 0 (Array. length a)
41
+
42
+ let reverse a =
43
+ let b_len = Array. length a in
44
+ if b_len = 0 then [||] else
45
+ let b = Array. copy a in
46
+ for i = 0 to b_len - 1 do
47
+ Array. unsafe_set b i (Array. unsafe_get a (b_len - 1 - i ))
48
+ done ;
49
+ b
50
+
51
+ let reverse_of_list = function
52
+ | [] -> [||]
53
+ | hd ::tl as l ->
54
+ let len = List. length l in
55
+ let a = Array. make len hd in
56
+ let rec fill i = function
57
+ | [] -> a
58
+ | hd ::tl -> Array. unsafe_set a (len - i - 2 ) hd; fill (i+ 1 ) tl in
59
+ fill 0 tl
60
+
61
+ let filter f a =
62
+ let arr_len = Array. length a in
63
+ let rec aux acc i =
64
+ if i = arr_len
65
+ then reverse_of_list acc
66
+ else
67
+ let v = Array. unsafe_get a i in
68
+ if f v then
69
+ aux (v::acc) (i+ 1 )
70
+ else aux acc (i + 1 )
71
+ in aux [] 0
72
+
73
+
74
+ let filter_map (f : _ -> _ option ) a =
75
+ let arr_len = Array. length a in
76
+ let rec aux acc i =
77
+ if i = arr_len
78
+ then reverse_of_list acc
79
+ else
80
+ let v = Array. unsafe_get a i in
81
+ match f v with
82
+ | Some v ->
83
+ aux (v::acc) (i+ 1 )
84
+ | None ->
85
+ aux acc (i + 1 )
86
+ in aux [] 0
87
+
88
+ let range from to_ =
89
+ if from > to_ then invalid_arg " Ext_array.range"
90
+ else Array. init (to_ - from + 1 ) (fun i -> i + from)
91
+
92
+ let map2i f a b =
93
+ let len = Array. length a in
94
+ if len <> Array. length b then
95
+ invalid_arg " Ext_array.map2i"
96
+ else
97
+ Array. mapi (fun i a -> f i a ( Array. unsafe_get b i )) a
98
+
99
+
100
+ let rec tolist_aux a f i res =
101
+ if i < 0 then res else
102
+ let v = Array. unsafe_get a i in
103
+ tolist_aux a f (i - 1 )
104
+ (match f v with
105
+ | Some v -> v :: res
106
+ | None -> res)
107
+
108
+ let to_list_map f a =
109
+ tolist_aux a f (Array. length a - 1 ) []
110
+
111
+ let to_list_map_acc f a acc =
112
+ tolist_aux a f (Array. length a - 1 ) acc
113
+
114
+
115
+ (* TODO: What would happen if [f] raise, memory leak? *)
116
+ let of_list_map f a =
117
+ match a with
118
+ | [] -> [||]
119
+ | h ::tl ->
120
+ let hd = f h in
121
+ let len = List. length tl + 1 in
122
+ let arr = Array. make len hd in
123
+ let rec fill i = function
124
+ | [] -> arr
125
+ | hd :: tl ->
126
+ Array. unsafe_set arr i (f hd);
127
+ fill (i + 1 ) tl in
128
+ fill 1 tl
129
+
130
+ (* *
131
+ {[
132
+ # rfind_with_index [|1;2;3|] (=) 2;;
133
+ - : int = 1
134
+ # rfind_with_index [|1;2;3|] (=) 1;;
135
+ - : int = 0
136
+ # rfind_with_index [|1;2;3|] (=) 3;;
137
+ - : int = 2
138
+ # rfind_with_index [|1;2;3|] (=) 4;;
139
+ - : int = -1
140
+ ]}
141
+ *)
142
+ let rfind_with_index arr cmp v =
143
+ let len = Array. length arr in
144
+ let rec aux i =
145
+ if i < 0 then i
146
+ else if cmp (Array. unsafe_get arr i) v then i
147
+ else aux (i - 1 ) in
148
+ aux (len - 1 )
149
+
150
+ type 'a split = [ `No_split | `Split of 'a array * 'a array ]
151
+ let rfind_and_split arr cmp v : _ split =
152
+ let i = rfind_with_index arr cmp v in
153
+ if i < 0 then
154
+ `No_split
155
+ else
156
+ `Split (Array. sub arr 0 i , Array. sub arr (i + 1 ) (Array. length arr - i - 1 ))
157
+
158
+
159
+ let find_with_index arr cmp v =
160
+ let len = Array. length arr in
161
+ let rec aux i len =
162
+ if i > = len then - 1
163
+ else if cmp (Array. unsafe_get arr i ) v then i
164
+ else aux (i + 1 ) len in
165
+ aux 0 len
166
+
167
+ let find_and_split arr cmp v : _ split =
168
+ let i = find_with_index arr cmp v in
169
+ if i < 0 then
170
+ `No_split
171
+ else
172
+ `Split (Array. sub arr 0 i, Array. sub arr (i + 1 ) (Array. length arr - i - 1 ))
173
+
174
+ (* * TODO: available since 4.03, use {!Array.exists} *)
175
+
176
+ let exists p a =
177
+ let n = Array. length a in
178
+ let rec loop i =
179
+ if i = n then false
180
+ else if p (Array. unsafe_get a i) then true
181
+ else loop (succ i) in
182
+ loop 0
183
+
184
+
185
+ let is_empty arr =
186
+ Array. length arr = 0
187
+
188
+
189
+ let rec unsafe_loop index len p xs ys =
190
+ if index > = len then true
191
+ else
192
+ p
193
+ (Array. unsafe_get xs index)
194
+ (Array. unsafe_get ys index) &&
195
+ unsafe_loop (succ index) len p xs ys
196
+
197
+ let for_all2_no_exn p xs ys =
198
+ let len_xs = Array. length xs in
199
+ let len_ys = Array. length ys in
200
+ len_xs = len_ys &&
201
+ unsafe_loop 0 len_xs p xs ys
0 commit comments