permit multiline comments and strings in macros
[bpt/coccinelle.git] / commons / ocamlextra / dynArray.mli
CommitLineData
97111a47
C
1(*
2 * DynArray - Resizeable Ocaml arrays
3 * Copyright (C) 2003 Brian Hurt
4 * Copyright (C) 2003 Nicolas Cannasse
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version,
10 * with the special exception on linking described in file LICENSE.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 *)
21
22(** Dynamic arrays.
23
24 A dynamic array is equivalent to a OCaml array that will resize itself
25 when elements are added or removed, except that floats are boxed and
26 that no initialization element is required.
27*)
28
29type 'a t
30
31exception Invalid_arg of int * string * string
32(** When an operation on an array fails, [Invalid_arg] is raised. The
33 integer is the value that made the operation fail, the first string
34 contains the function name that has been called and the second string
35 contains the parameter name that made the operation fail.
36*)
37
38(** {6 Array creation} *)
39
40val create : unit -> 'a t
41(** [create()] returns a new empty dynamic array. *)
42
43val make : int -> 'a t
44(** [make count] returns an array with some memory already allocated so
45 up to [count] elements can be stored into it without resizing. *)
46
47val init : int -> (int -> 'a) -> 'a t
48(** [init n f] returns an array of [n] elements filled with values
49 returned by [f 0 , f 1, ... f (n-1)]. *)
50
51(** {6 Array manipulation functions} *)
52
53val empty : 'a t -> bool
54(** Return true if the number of elements in the array is 0. *)
55
56val length : 'a t -> int
57(** Return the number of elements in the array. *)
58
59val get : 'a t -> int -> 'a
60(** [get darr idx] gets the element in [darr] at index [idx]. If [darr] has
61 [len] elements in it, then the valid indexes range from [0] to [len-1]. *)
62
63val last : 'a t -> 'a
64(** [last darr] returns the last element of [darr]. *)
65
66val set : 'a t -> int -> 'a -> unit
67(** [set darr idx v] sets the element of [darr] at index [idx] to value
68 [v]. The previous value is overwritten. *)
69
70val insert : 'a t -> int -> 'a -> unit
71(** [insert darr idx v] inserts [v] into [darr] at index [idx]. All elements
72 of [darr] with an index greater than or equal to [idx] have their
73 index incremented (are moved up one place) to make room for the new
74 element. *)
75
76val add : 'a t -> 'a -> unit
77(** [add darr v] appends [v] onto [darr]. [v] becomes the new
78 last element of [darr]. *)
79
80val append : 'a t -> 'a t -> unit
81(** [append src dst] adds all elements of [src] to the end of [dst]. *)
82
83val delete : 'a t -> int -> unit
84(** [delete darr idx] deletes the element of [darr] at [idx]. All elements
85 with an index greater than [idx] have their index decremented (are
86 moved down one place) to fill in the hole. *)
87
88val delete_last : 'a t -> unit
89(** [delete_last darr] deletes the last element of [darr]. This is equivalent
90 of doing [delete darr ((length darr) - 1)]. *)
91
92val delete_range : 'a t -> int -> int -> unit
93(** [delete_range darr p len] deletes [len] elements starting at index [p].
94 All elements with an index greater than [p+len] are moved to fill
95 in the hole. *)
96
97val clear : 'a t -> unit
98(** remove all elements from the array and resize it to 0. *)
99
100val blit : 'a t -> int -> 'a t -> int -> int -> unit
101(** [blit src srcidx dst dstidx len] copies [len] elements from [src]
102 starting with index [srcidx] to [dst] starting at [dstidx]. *)
103
104val compact : 'a t -> unit
105(** [compact darr] ensures that the space allocated by the array is minimal.*)
106
107(** {6 Array copy and conversion} *)
108
109val to_list : 'a t -> 'a list
110(** [to_list darr] returns the elements of [darr] in order as a list. *)
111
112val to_array : 'a t -> 'a array
113(** [to_array darr] returns the elements of [darr] in order as an array. *)
114
115val enum : 'a t -> 'a Enum.t
116(** [enum darr] returns the enumeration of [darr] elements. *)
117
118val of_list : 'a list -> 'a t
119(** [of_list lst] returns a dynamic array with the elements of [lst] in
120 it in order. *)
121
122val of_array : 'a array -> 'a t
123(** [of_array arr] returns an array with the elements of [arr] in it
124 in order. *)
125
126val of_enum : 'a Enum.t -> 'a t
127(** [of_enum e] returns an array that holds, in order, the elements of [e]. *)
128
129val copy : 'a t -> 'a t
130(** [copy src] returns a fresh copy of [src], such that no modification of
131 [src] affects the copy, or vice versa (all new memory is allocated for
132 the copy). *)
133
134val sub : 'a t -> int -> int -> 'a t
135(** [sub darr start len] returns an array holding the subset of [len]
136 elements from [darr] starting with the element at index [idx]. *)
137
138(** {6 Array functional support} *)
139
140val iter : ('a -> unit) -> 'a t -> unit
141(** [iter f darr] calls the function [f] on every element of [darr]. It
142 is equivalent to [for i = 0 to length darr - 1 do f (get darr i) done;] *)
143
144val iteri : (int -> 'a -> unit) -> 'a t -> unit
145(** [iter f darr] calls the function [f] on every element of [darr]. It
146 is equivalent to [for i = 0 to length darr - 1 do f i (get darr i) done;]
147 *)
148
149val map : ('a -> 'b) -> 'a t -> 'b t
150(** [map f darr] applies the function [f] to every element of [darr]
151 and creates a dynamic array from the results - similar to [List.map] or
152 [Array.map]. *)
153
154val mapi : (int -> 'a -> 'b) -> 'a t -> 'b t
155(** [mapi f darr] applies the function [f] to every element of [darr]
156 and creates a dynamic array from the results - similar to [List.mapi] or
157 [Array.mapi]. *)
158
159val fold_left : ('a -> 'b -> 'a) -> 'a -> 'b t -> 'a
160(** [fold_left f x darr] computes
161 [f ( ... ( f ( f (get darr 0) x) (get darr 1) ) ... ) (get darr n-1)],
162 similar to [Array.fold_left] or [List.fold_left]. *)
163
164val fold_right : ('a -> 'b -> 'b) -> 'a t -> 'b -> 'b
165(** [fold_right f darr x] computes
166 [ f (get darr 0) (f (get darr 1) ( ... ( f (get darr n-1) x ) ... ) ) ]
167 similar to [Array.fold_right] or [List.fold_right]. *)
168
169val index_of : ('a -> bool) -> 'a t -> int
170(** [index_of f darr] returns the index of the first element [x] in darr such
171 as [f x] returns [true] or raise [Not_found] if not found. *)
172
173val filter : ('a -> bool) -> 'a t -> unit
174
175(** {6 Array resizers} *)
176
177type resizer_t = currslots:int -> oldlength:int -> newlength:int -> int
178(** The type of a resizer function.
179
180 Resizer functions are called whenever elements are added to
181 or removed from the dynamic array to determine what the current number of
182 storage spaces in the array should be. The three named arguments
183 passed to a resizer are the current number of storage spaces in
184 the array, the length of the array before the elements are
185 added or removed, and the length the array will be after the
186 elements are added or removed. If elements are being added, newlength
187 will be larger than oldlength, if elements are being removed,
188 newlength will be smaller than oldlength. If the resizer function
189 returns exactly oldlength, the size of the array is only changed when
190 adding an element while there is not enough space for it.
191
192 By default, all dynamic arrays are created with the [default_resizer].
193 When a dynamic array is created from another dynamic array (using [copy],
194 [map] , etc. ) the resizer of the copy will be the same as the original
195 dynamic array resizer. To change the resizer, use the [set_resizer]
196 function.
197*)
198
199val set_resizer : 'a t -> resizer_t -> unit
200(** Change the resizer for this array. *)
201
202val get_resizer : 'a t -> resizer_t
203(** Get the current resizer function for a given array *)
204
205val default_resizer : resizer_t
206(** The default resizer function the library is using - in this version
207 of DynArray, this is the [exponential_resizer] but should change in
208 next versions. *)
209
210val exponential_resizer : resizer_t
211(** The exponential resizer- The default resizer except when the resizer
212 is being copied from some other darray.
213
214 [exponential_resizer] works by doubling or halving the number of
215 slots until they "fit". If the number of slots is less than the
216 new length, the number of slots is doubled until it is greater
217 than the new length (or Sys.max_array_size is reached).
218
219 If the number of slots is more than four times the new length,
220 the number of slots is halved until it is less than four times the
221 new length.
222
223 Allowing darrays to fall below 25% utilization before shrinking them
224 prevents "thrashing". Consider the case where the caller is constantly
225 adding a few elements, and then removing a few elements, causing
226 the length to constantly cross above and below a power of two.
227 Shrinking the array when it falls below 50% would causing the
228 underlying array to be constantly allocated and deallocated.
229 A few elements would be added, causing the array to be reallocated
230 and have a usage of just above 50%. Then a few elements would be
231 remove, and the array would fall below 50% utilization and be
232 reallocated yet again. The bulk of the array, untouched, would be
233 copied and copied again. By setting the threshold at 25% instead,
234 such "thrashing" only occurs with wild swings- adding and removing
235 huge numbers of elements (more than half of the elements in the array).
236
237 [exponential_resizer] is a good performing resizer for most
238 applications. A list allocates 2 words for every element, while an
239 array (with large numbers of elements) allocates only 1 word per
240 element (ignoring unboxed floats). On insert, [exponential_resizer]
241 keeps the amount of wasted "extra" array elements below 50%, meaning
242 that less than 2 words per element are used. Even on removals
243 where the amount of wasted space is allowed to rise to 75%, that
244 only means that darray is using 4 words per element. This is
245 generally not a significant overhead.
246
247 Furthermore, [exponential_resizer] minimizes the number of copies
248 needed- appending n elements into an empty darray with initial size
249 0 requires between n and 2n elements of the array be copied- O(n)
250 work, or O(1) work per element (on average). A similar argument
251 can be made that deletes from the end of the array are O(1) as
252 well (obviously deletes from anywhere else are O(n) work- you
253 have to move the n or so elements above the deleted element down).
254
255*)
256
257val step_resizer : int -> resizer_t
258(** The stepwise resizer- another example of a resizer function, this
259 time of a parameterized resizer.
260
261 The resizer returned by [step_resizer step] returns the smallest
262 multiple of [step] larger than [newlength] if [currslots] is less
263 then [newlength]-[step] or greater than [newlength].
264
265 For example, to make an darray with a step of 10, a length
266 of len, and a null of null, you would do:
267 [make] ~resizer:([step_resizer] 10) len null
268*)
269
270val conservative_exponential_resizer : resizer_t
271(** [conservative_exponential_resizer] is an example resizer function
272 which uses the oldlength parameter. It only shrinks the array
273 on inserts- no deletes shrink the array, only inserts. It does
274 this by comparing the oldlength and newlength parameters. Other
275 than that, it acts like [exponential_resizer].
276*)
277
278(** {6 Unsafe operations} **)
279
280val unsafe_get : 'a t -> int -> 'a
281val unsafe_set : 'a t -> int -> 'a -> unit