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