mirror of
https://github.com/c-cube/ocaml-containers.git
synced 2025-12-07 19:55:31 -05:00
update of Vector, with more functions (length, rev, append_seq...)
and better performance (using unsafe_set/unsafe_get in Array)
This commit is contained in:
parent
7a0605d96f
commit
32985129e0
2 changed files with 73 additions and 26 deletions
77
vector.ml
77
vector.ml
|
|
@ -40,40 +40,45 @@ let create i =
|
|||
(** resize the underlying array so that it can contains the
|
||||
given number of elements *)
|
||||
let resize v newcapacity =
|
||||
let newcapacity = min newcapacity Sys.max_array_length in
|
||||
if newcapacity <= Array.length v.vec
|
||||
then () (* already big enough *)
|
||||
else begin
|
||||
assert (newcapacity >= v.size);
|
||||
let new_vec = Array.create newcapacity (Obj.magic None) in
|
||||
Array.blit v.vec 0 new_vec 0 v.size;
|
||||
v.vec <- new_vec;
|
||||
end
|
||||
()
|
||||
|
||||
(** Be sure that [v] can contain [size] elements, resize it if needed. *)
|
||||
let ensure v size =
|
||||
if v.size < size
|
||||
then
|
||||
let size' = min (2 * v.size) Sys.max_array_length in
|
||||
resize v size'
|
||||
|
||||
let clear v =
|
||||
v.size <- 0;
|
||||
if Array.length v.vec > 1024 (* shrink if too large *)
|
||||
then (v.vec <- Array.create 10 (Obj.magic None))
|
||||
v.size <- 0
|
||||
|
||||
let is_empty v = v.size = 0
|
||||
|
||||
let push v x =
|
||||
(if Array.length v.vec = v.size
|
||||
then resize v (2 * v.size));
|
||||
v.vec.(v.size) <- x;
|
||||
(if v.size = Array.length v.vec then resize v (2 * v.size));
|
||||
Array.unsafe_set v.vec v.size x;
|
||||
v.size <- v.size + 1
|
||||
|
||||
(** add all elements of b to a *)
|
||||
let append a b =
|
||||
resize a (a.size + b.size);
|
||||
(if Array.length a.vec < a.size + b.size
|
||||
then resize a (2 * (a.size + b.size)));
|
||||
Array.blit b.vec 0 a.vec a.size b.size;
|
||||
a.size <- a.size + b.size
|
||||
|
||||
let append_array a b =
|
||||
resize a (a.size + Array.length b);
|
||||
(if Array.length a.vec < a.size + Array.length b
|
||||
then resize a (2 * (a.size + Array.length b)));
|
||||
Array.blit b 0 a.vec a.size (Array.length b);
|
||||
a.size <- a.size + Array.length b
|
||||
|
||||
let append_seq a seq =
|
||||
Sequence.iter (fun x -> push a x) seq
|
||||
|
||||
let pop v =
|
||||
(if v.size = 0 then failwith "Vector.pop on empty vector");
|
||||
v.size <- v.size - 1;
|
||||
|
|
@ -87,7 +92,9 @@ let copy v =
|
|||
v'
|
||||
|
||||
let shrink v n =
|
||||
if n > v.size then failwith "cannot shrink to bigger size" else v.size <- n
|
||||
if n > v.size
|
||||
then failwith "cannot shrink to bigger size"
|
||||
else v.size <- n
|
||||
|
||||
let member ?(eq=(=)) v x =
|
||||
let n = v.size in
|
||||
|
|
@ -120,32 +127,36 @@ let uniq_sort ?(cmp=compare) v =
|
|||
|
||||
let iter v k =
|
||||
for i = 0 to v.size -1 do
|
||||
k v.vec.(i)
|
||||
k (Array.unsafe_get v.vec i)
|
||||
done
|
||||
|
||||
let iteri v k =
|
||||
for i = 0 to v.size -1 do
|
||||
k i v.vec.(i)
|
||||
k i (Array.unsafe_get v.vec i)
|
||||
done
|
||||
|
||||
let map v f =
|
||||
let v' = create v.size in
|
||||
for i = 0 to v.size - 1 do
|
||||
push v' (f v.vec.(i));
|
||||
let x = f (Array.unsafe_get v.vec i) in
|
||||
Array.unsafe_set v'.vec i x
|
||||
done;
|
||||
v'.size <- v.size;
|
||||
v'
|
||||
|
||||
let filter v f =
|
||||
let v' = create v.size in
|
||||
for i = 0 to v.size - 1 do
|
||||
if f v.vec.(i) then push v' v.vec.(i);
|
||||
let x = Array.unsafe_get v.vec i in
|
||||
if f x then push v' x;
|
||||
done;
|
||||
v'
|
||||
|
||||
let fold v acc f =
|
||||
let acc = ref acc in
|
||||
for i = 0 to v.size - 1 do
|
||||
acc := f !acc v.vec.(i);
|
||||
let x = Array.unsafe_get v.vec i in
|
||||
acc := f !acc x;
|
||||
done;
|
||||
!acc
|
||||
|
||||
|
|
@ -175,23 +186,45 @@ let find v p =
|
|||
|
||||
let get v i =
|
||||
(if i < 0 || i >= v.size then failwith "Vector.get");
|
||||
v.vec.(i)
|
||||
Array.unsafe_get v.vec i
|
||||
|
||||
let set v i x =
|
||||
(if i < 0 || i >= v.size then failwith "Vector.set");
|
||||
v.vec.(i) <- x
|
||||
Array.unsafe_set v.vec i x
|
||||
|
||||
let rev v =
|
||||
let n = v.size in
|
||||
let vec = v.vec in
|
||||
for i = 0 to (n-1)/2 do
|
||||
let x = Array.unsafe_get vec i in
|
||||
let y = Array.unsafe_get vec (n-i-1) in
|
||||
Array.unsafe_set vec i y;
|
||||
Array.unsafe_set vec (n-i-1) x;
|
||||
done
|
||||
|
||||
let size v = v.size
|
||||
|
||||
let length v = v.size
|
||||
|
||||
let unsafe_get_array v = v.vec
|
||||
|
||||
let of_seq ?(init=create 10) seq =
|
||||
Sequence.iter (fun x -> push init x) seq;
|
||||
append_seq init seq;
|
||||
init
|
||||
|
||||
let to_seq t =
|
||||
Sequence.from_iter (fun k -> iter t k)
|
||||
|
||||
let slice v start len =
|
||||
assert (start >= 0 && len >= 0);
|
||||
Sequence.from_iter
|
||||
(fun k ->
|
||||
assert (start+len < v.size);
|
||||
for i = start to start+len do
|
||||
let x = Array.unsafe_get v.vec i in
|
||||
k x
|
||||
done)
|
||||
|
||||
let from_array a =
|
||||
let c = Array.length a in
|
||||
let v = create c in
|
||||
|
|
|
|||
14
vector.mli
14
vector.mli
|
|
@ -46,6 +46,9 @@ val append : 'a t -> 'a t -> unit
|
|||
val append_array : 'a t -> 'a array -> unit
|
||||
(** same as append, with an array *)
|
||||
|
||||
val append_seq : 'a t -> 'a Sequence.t -> unit
|
||||
(** Append content of sequence *)
|
||||
|
||||
val pop : 'a t -> 'a
|
||||
(** remove last element, or raise a Failure if empty *)
|
||||
|
||||
|
|
@ -94,17 +97,28 @@ val get : 'a t -> int -> 'a
|
|||
val set : 'a t -> int -> 'a -> unit
|
||||
(** access element, or Failure if bad index *)
|
||||
|
||||
val rev : 'a t -> unit
|
||||
(** Reverse array in place *)
|
||||
|
||||
val size : 'a t -> int
|
||||
(** number of elements in vector *)
|
||||
|
||||
val length : _ t -> int
|
||||
(** Synonym for {! size} *)
|
||||
|
||||
val unsafe_get_array : 'a t -> 'a array
|
||||
(** Access the underlying *shared* array (do not modify!).
|
||||
[unsafe_get_array v] is longer than [size v], but elements at higher
|
||||
index than [size v] are undefined (do not access!). *)
|
||||
|
||||
val of_seq : ?init:'a t -> 'a Sequence.t -> 'a t
|
||||
|
||||
val to_seq : 'a t -> 'a Sequence.t
|
||||
|
||||
val slice : 'a t -> int -> int -> 'a Sequence.t
|
||||
(** [slice v start len] is the sequence of elements from [v.(start)]
|
||||
to [v.(start+len)] included. *)
|
||||
|
||||
val from_array : 'a array -> 'a t
|
||||
val from_list : 'a list -> 'a t
|
||||
val to_array : 'a t -> 'a array
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue