mirror of
https://github.com/c-cube/ocaml-containers.git
synced 2025-12-06 11:15:31 -05:00
Merge branch 'wip-ccvec'
This commit is contained in:
commit
037a0ef922
2 changed files with 98 additions and 25 deletions
|
|
@ -22,6 +22,16 @@ type 'a vector = ('a, rw) t
|
||||||
|
|
||||||
type 'a ro_vector = ('a, ro) t
|
type 'a ro_vector = ('a, ro) t
|
||||||
|
|
||||||
|
external as_float_arr : 'a array -> float array = "%identity"
|
||||||
|
external as_obj_arr : 'a array -> Obj.t array = "%identity"
|
||||||
|
|
||||||
|
let fill_with_junk_ (a:_ array) i len : unit =
|
||||||
|
if Obj.(tag (repr a) = double_array_tag) then (
|
||||||
|
Array.fill (as_float_arr a) i len 0.;
|
||||||
|
) else (
|
||||||
|
Array.fill (as_obj_arr a) i len (Obj.repr ());
|
||||||
|
)
|
||||||
|
|
||||||
let freeze v = {
|
let freeze v = {
|
||||||
size=v.size;
|
size=v.size;
|
||||||
vec=v.vec;
|
vec=v.vec;
|
||||||
|
|
@ -37,9 +47,12 @@ let create () = {
|
||||||
vec = [| |];
|
vec = [| |];
|
||||||
}
|
}
|
||||||
|
|
||||||
let create_with ?(capacity=128) x = {
|
let create_with ?(capacity=128) x =
|
||||||
|
let vec = Array.make capacity x in
|
||||||
|
fill_with_junk_ vec 0 capacity;
|
||||||
|
{
|
||||||
size = 0;
|
size = 0;
|
||||||
vec = Array.make capacity x;
|
vec
|
||||||
}
|
}
|
||||||
|
|
||||||
(*$T
|
(*$T
|
||||||
|
|
@ -76,6 +89,7 @@ let resize_ v newcapacity =
|
||||||
assert (not (array_is_empty_ v));
|
assert (not (array_is_empty_ v));
|
||||||
let new_vec = Array.make newcapacity v.vec.(0) in
|
let new_vec = Array.make newcapacity v.vec.(0) in
|
||||||
Array.blit v.vec 0 new_vec 0 v.size;
|
Array.blit v.vec 0 new_vec 0 v.size;
|
||||||
|
fill_with_junk_ new_vec v.size (newcapacity-v.size);
|
||||||
v.vec <- new_vec;
|
v.vec <- new_vec;
|
||||||
()
|
()
|
||||||
|
|
||||||
|
|
@ -84,10 +98,35 @@ let resize_ v newcapacity =
|
||||||
ensure v 200; capacity v >= 200
|
ensure v 200; capacity v >= 200
|
||||||
*)
|
*)
|
||||||
|
|
||||||
|
(*$T
|
||||||
|
let v = create() in push v 0.; push v 1.; push v 2.; 3=length v
|
||||||
|
let v = create() in push v 1.; push v 2.; push v 3.; 6. = (get v 0 +. get v 1 +. get v 2)
|
||||||
|
let v = create() in push v 0; push v 1; push v 2; 3=length v
|
||||||
|
let v = create() in push v 1; push v 2; push v 3; 6 = (get v 0 + get v 1 + get v 2)
|
||||||
|
let v = create() in push v "a"; push v "b"; push v "c"; 3=length v
|
||||||
|
let v = create() in push v "a"; push v "b"; push v "c"; "abc" = String.concat "" (to_list v)
|
||||||
|
*)
|
||||||
|
|
||||||
|
(*$R
|
||||||
|
let v = create() in
|
||||||
|
push v 0.; push v 1.;
|
||||||
|
clear v;
|
||||||
|
push v 0.; push v 1.; push v 7.; push v 10.; push v 12.;
|
||||||
|
shrink v 2;
|
||||||
|
assert_equal 1. (fold (+.) 0. v);
|
||||||
|
clear v;
|
||||||
|
assert_equal 0 (size v);
|
||||||
|
push v 0.; push v 1.; push v 7.; push v 10.; push v 12.;
|
||||||
|
assert_equal (1. +. 7. +. 10. +. 12.) (fold (+.) 0. v);
|
||||||
|
*)
|
||||||
|
|
||||||
(* grow the array, using [x] as a filler if required *)
|
(* grow the array, using [x] as a filler if required *)
|
||||||
let grow_with_ v ~filler:x =
|
let grow_with_ v ~filler:x =
|
||||||
if array_is_empty_ v then (
|
if array_is_empty_ v then (
|
||||||
v.vec <- Array.make 4 x
|
let len = 4 in
|
||||||
|
v.vec <- Array.make len x;
|
||||||
|
(* do not really use [x], it was just for knowing the type *)
|
||||||
|
fill_with_junk_ v.vec 0 len;
|
||||||
) else (
|
) else (
|
||||||
let n = Array.length v.vec in
|
let n = Array.length v.vec in
|
||||||
let size = min (2 * n + 3) Sys.max_array_length in
|
let size = min (2 * n + 3) Sys.max_array_length in
|
||||||
|
|
@ -109,14 +148,15 @@ let ensure_assuming_not_empty_ v ~size =
|
||||||
)
|
)
|
||||||
|
|
||||||
let ensure_with ~init v size =
|
let ensure_with ~init v size =
|
||||||
if Array.length v.vec = 0 then (
|
if array_is_empty_ v then (
|
||||||
v.vec <- Array.make size init
|
v.vec <- Array.make size init;
|
||||||
|
fill_with_junk_ v.vec 0 size
|
||||||
) else (
|
) else (
|
||||||
ensure_assuming_not_empty_ v ~size
|
ensure_assuming_not_empty_ v ~size
|
||||||
)
|
)
|
||||||
|
|
||||||
let ensure v size =
|
let ensure v size =
|
||||||
if Array.length v.vec > 0 then (
|
if not (array_is_empty_ v) then (
|
||||||
ensure_assuming_not_empty_ v ~size
|
ensure_assuming_not_empty_ v ~size
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -131,6 +171,22 @@ let clear v =
|
||||||
OUnit.assert_bool "empty_after_clear" (Iter.is_empty (to_seq v));
|
OUnit.assert_bool "empty_after_clear" (Iter.is_empty (to_seq v));
|
||||||
*)
|
*)
|
||||||
|
|
||||||
|
let clear_and_reset v =
|
||||||
|
v.size <- 0;
|
||||||
|
v.vec <- [||]
|
||||||
|
|
||||||
|
(* TODO*)
|
||||||
|
(*
|
||||||
|
let v = create() in
|
||||||
|
let a = Weak.create 1 in
|
||||||
|
push v ("hello"^"world");
|
||||||
|
Weak.set a 0 (Some (get v 0));
|
||||||
|
Gc.full_major(); Gc.compact();
|
||||||
|
OUnit.assert_bool "is alive" (Weak.check a 0);
|
||||||
|
Gc.full_major(); Gc.compact();
|
||||||
|
OUnit.assert_equal None (Weak.get a 0);
|
||||||
|
*)
|
||||||
|
|
||||||
let is_empty v = v.size = 0
|
let is_empty v = v.size = 0
|
||||||
|
|
||||||
let push_unsafe_ v x =
|
let push_unsafe_ v x =
|
||||||
|
|
@ -197,7 +253,8 @@ let remove v i =
|
||||||
if i < v.size - 1
|
if i < v.size - 1
|
||||||
then v.vec.(i) <- v.vec.(v.size - 1);
|
then v.vec.(i) <- v.vec.(v.size - 1);
|
||||||
(* remove one element *)
|
(* remove one element *)
|
||||||
v.size <- v.size - 1
|
v.size <- v.size - 1;
|
||||||
|
fill_with_junk_ v.vec v.size 1
|
||||||
|
|
||||||
let append_seq a seq =
|
let append_seq a seq =
|
||||||
seq (fun x -> push a x)
|
seq (fun x -> push a x)
|
||||||
|
|
@ -326,7 +383,8 @@ let pop_exn v =
|
||||||
let new_size = v.size - 1 in
|
let new_size = v.size - 1 in
|
||||||
v.size <- new_size;
|
v.size <- new_size;
|
||||||
let x = v.vec.(new_size) in
|
let x = v.vec.(new_size) in
|
||||||
if new_size > 0 then v.vec.(new_size) <- v.vec.(0); (* free last element *)
|
(* free last element *)
|
||||||
|
fill_with_junk_ v.vec new_size 1;
|
||||||
x
|
x
|
||||||
|
|
||||||
let pop v =
|
let pop v =
|
||||||
|
|
@ -378,10 +436,8 @@ let shrink v n =
|
||||||
let old_size = v.size in
|
let old_size = v.size in
|
||||||
if n < old_size then (
|
if n < old_size then (
|
||||||
v.size <- n;
|
v.size <- n;
|
||||||
if n > 0 then (
|
|
||||||
(* free elements by erasing them *)
|
(* free elements by erasing them *)
|
||||||
Array.fill v.vec n (old_size-n) v.vec.(0);
|
fill_with_junk_ v.vec n (old_size-n);
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
(*$R
|
(*$R
|
||||||
|
|
@ -401,6 +457,21 @@ let shrink v n =
|
||||||
)
|
)
|
||||||
*)
|
*)
|
||||||
|
|
||||||
|
let shrink_to_fit v : unit =
|
||||||
|
if v.size = 0 then (
|
||||||
|
v.vec <- [| |]
|
||||||
|
) else if v.size < Array.length v.vec then (
|
||||||
|
v.vec <- Array.sub v.vec 0 v.size
|
||||||
|
)
|
||||||
|
|
||||||
|
(*$QR
|
||||||
|
(gen Q.small_int) (fun v ->
|
||||||
|
let v' = copy v in
|
||||||
|
shrink_to_fit v;
|
||||||
|
to_list v = to_list v'
|
||||||
|
)
|
||||||
|
*)
|
||||||
|
|
||||||
let sort' cmp v =
|
let sort' cmp v =
|
||||||
(* possibly copy array (to avoid junk at its end), then sort the array *)
|
(* possibly copy array (to avoid junk at its end), then sort the array *)
|
||||||
let a =
|
let a =
|
||||||
|
|
@ -544,9 +615,7 @@ let filter' p v =
|
||||||
) else incr i
|
) else incr i
|
||||||
done;
|
done;
|
||||||
(* free elements *)
|
(* free elements *)
|
||||||
if !j > 0 && !j < v.size then (
|
fill_with_junk_ v.vec !j (v.size - !j);
|
||||||
Array.fill v.vec !j (v.size - !j) v.vec.(0);
|
|
||||||
);
|
|
||||||
v.size <- !j
|
v.size <- !j
|
||||||
|
|
||||||
(*$T
|
(*$T
|
||||||
|
|
@ -689,7 +758,6 @@ let filter_map f v =
|
||||||
to_list (filter_map f v) = CCList.filter_map f l)
|
to_list (filter_map f v) = CCList.filter_map f l)
|
||||||
*)
|
*)
|
||||||
|
|
||||||
(* TODO: free elements *)
|
|
||||||
let filter_map_in_place f v =
|
let filter_map_in_place f v =
|
||||||
let i = ref 0 in (* cur element *)
|
let i = ref 0 in (* cur element *)
|
||||||
let j = ref 0 in (* cur insertion point *)
|
let j = ref 0 in (* cur insertion point *)
|
||||||
|
|
@ -705,9 +773,7 @@ let filter_map_in_place f v =
|
||||||
incr j
|
incr j
|
||||||
done;
|
done;
|
||||||
(* free elements *)
|
(* free elements *)
|
||||||
if !j > 0 && !j < v.size then (
|
fill_with_junk_ v.vec !j (v.size - !j);
|
||||||
Array.fill v.vec !j (v.size - !j) v.vec.(0);
|
|
||||||
);
|
|
||||||
v.size <- !j
|
v.size <- !j
|
||||||
|
|
||||||
(*$QR
|
(*$QR
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
(* This file is free software, part of containers. See file "license" for more details. *)
|
(* This file is free software, part of containers. See file "license" for more details. *)
|
||||||
|
|
||||||
(** {1 Growable, mutable vector} *)
|
(** {1 Growable, mutable vector} *)
|
||||||
|
|
@ -36,9 +35,8 @@ val create : unit -> ('a, rw) t
|
||||||
(** Create a new, empty vector. *)
|
(** Create a new, empty vector. *)
|
||||||
|
|
||||||
val create_with : ?capacity:int -> 'a -> ('a, rw) t
|
val create_with : ?capacity:int -> 'a -> ('a, rw) t
|
||||||
(** Create a new vector, using the given value as a filler.
|
(** Create a new vector, the value is used to enforce the type the new vector.
|
||||||
@param capacity the size of the underlying array.
|
@param capacity the size of the underlying array. *)
|
||||||
{b caution}: the value will likely not be GC'd before the vector is. *)
|
|
||||||
|
|
||||||
val return : 'a -> ('a, 'mut) t
|
val return : 'a -> ('a, 'mut) t
|
||||||
(** Singleton vector.
|
(** Singleton vector.
|
||||||
|
|
@ -53,10 +51,15 @@ val init : int -> (int -> 'a) -> ('a, 'mut) t
|
||||||
val clear : ('a, rw) t -> unit
|
val clear : ('a, rw) t -> unit
|
||||||
(** Clear the content of the vector. *)
|
(** Clear the content of the vector. *)
|
||||||
|
|
||||||
|
val clear_and_reset : ('a, rw) t -> unit
|
||||||
|
(** Clear the content of the vector, and deallocate the underlying array,
|
||||||
|
removing references to all the elements.
|
||||||
|
@since NEXT_RELEASE *)
|
||||||
|
|
||||||
val ensure_with : init:'a -> ('a, rw) t -> int -> unit
|
val ensure_with : init:'a -> ('a, rw) t -> int -> unit
|
||||||
(** Hint to the vector that it should have at least the given capacity.
|
(** Hint to the vector that it should have at least the given capacity.
|
||||||
@param init if [capacity v = 0], used as a filler
|
@param init if [capacity v = 0], used to enforce the type of the vector
|
||||||
element for the underlying array (see {!create_with}).
|
(see {!create_with}).
|
||||||
@since 0.14 *)
|
@since 0.14 *)
|
||||||
|
|
||||||
val ensure : ('a, rw) t -> int -> unit
|
val ensure : ('a, rw) t -> int -> unit
|
||||||
|
|
@ -118,6 +121,10 @@ val shrink : ('a, rw) t -> int -> unit
|
||||||
(** Shrink to the given size (remove elements above this size).
|
(** Shrink to the given size (remove elements above this size).
|
||||||
Does nothing if the parameter is bigger than the current size. *)
|
Does nothing if the parameter is bigger than the current size. *)
|
||||||
|
|
||||||
|
val shrink_to_fit : ('a, _) t -> unit
|
||||||
|
(** Shrink internal array to fit the size of the vector
|
||||||
|
@since NEXT_RELEASE *)
|
||||||
|
|
||||||
val member : eq:('a -> 'a -> bool) -> 'a -> ('a, _) t -> bool
|
val member : eq:('a -> 'a -> bool) -> 'a -> ('a, _) t -> bool
|
||||||
(** Is the element a member of the vector? *)
|
(** Is the element a member of the vector? *)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue