mirror of
https://github.com/c-cube/ocaml-containers.git
synced 2025-12-08 20:25:28 -05:00
some optimizations in CCVector
This commit is contained in:
parent
1a20df9393
commit
b8d84de4dc
2 changed files with 48 additions and 27 deletions
|
|
@ -92,36 +92,48 @@ let _resize v newcapacity =
|
||||||
()
|
()
|
||||||
|
|
||||||
(*$T
|
(*$T
|
||||||
(let v = create_with ~capacity:10 1 in ensure v 200; capacity v >= 200)
|
let v = create_with ~capacity:10 1 in \
|
||||||
|
ensure v 200; capacity v >= 200
|
||||||
*)
|
*)
|
||||||
|
|
||||||
(* grow the array, using [x] as a filler if required *)
|
(* grow the array, using [x] as a filler if required *)
|
||||||
let _grow v x =
|
let _grow v x =
|
||||||
if _empty_array v
|
if _empty_array v
|
||||||
then v.vec <- Array.make 32 x
|
then v.vec <- Array.make 32 x
|
||||||
else
|
else (
|
||||||
let n = Array.length v.vec in
|
let n = Array.length v.vec in
|
||||||
let size = min (n + n/2 + 10) Sys.max_array_length in
|
let size = min (2 * n + 10) Sys.max_array_length in
|
||||||
|
if size = n then failwith "vec: can't grow any further";
|
||||||
_resize v size
|
_resize v size
|
||||||
|
)
|
||||||
|
|
||||||
|
(* resize so that capacity is at least size. Use a doubling-size
|
||||||
|
strategy so that calling many times [ensure] will
|
||||||
|
behave well *)
|
||||||
let ensure v size =
|
let ensure v size =
|
||||||
if Array.length v.vec = 0
|
if Array.length v.vec = 0
|
||||||
then ()
|
then ()
|
||||||
else if v.size < size
|
else if size > Sys.max_array_length
|
||||||
then
|
then failwith "vec.ensure: size too big"
|
||||||
let size' = min size Sys.max_array_length in
|
else (
|
||||||
_resize v size'
|
let n = ref (max 16 (Array.length v.vec)) in
|
||||||
|
while !n < size do n := min Sys.max_array_length (2* !n) done;
|
||||||
|
_resize v !n
|
||||||
|
)
|
||||||
|
|
||||||
let clear v =
|
let clear v =
|
||||||
v.size <- 0
|
v.size <- 0
|
||||||
|
|
||||||
let is_empty v = v.size = 0
|
let is_empty v = v.size = 0
|
||||||
|
|
||||||
|
let push_unsafe v x =
|
||||||
|
Array.unsafe_set v.vec v.size x;
|
||||||
|
v.size <- v.size + 1
|
||||||
|
|
||||||
let push v x =
|
let push v x =
|
||||||
if v.size = Array.length v.vec
|
if v.size = Array.length v.vec
|
||||||
then _grow v x;
|
then _grow v x;
|
||||||
Array.unsafe_set v.vec v.size x;
|
push_unsafe v x
|
||||||
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 =
|
||||||
|
|
@ -164,8 +176,10 @@ let append_seq a seq =
|
||||||
seq (fun x -> push a x)
|
seq (fun x -> push a x)
|
||||||
|
|
||||||
let append_array a b =
|
let append_array a b =
|
||||||
ensure a (a.size + Array.length b);
|
let len_b = Array.length b in
|
||||||
Array.iter (push a) b
|
ensure a (a.size + len_b);
|
||||||
|
Array.blit b 0 a.vec a.size len_b;
|
||||||
|
a.size <- a.size + len_b
|
||||||
|
|
||||||
(*$T
|
(*$T
|
||||||
let v1 = init 5 (fun i->i) and v2 = Array.init 5 (fun i->i+5) in \
|
let v1 = init 5 (fun i->i) and v2 = Array.init 5 (fun i->i+5) in \
|
||||||
|
|
@ -274,10 +288,7 @@ let map f v =
|
||||||
then create ()
|
then create ()
|
||||||
else (
|
else (
|
||||||
let vec = Array.init v.size (fun i -> f (Array.unsafe_get v.vec i)) in
|
let vec = Array.init v.size (fun i -> f (Array.unsafe_get v.vec i)) in
|
||||||
{
|
{ size=v.size; vec; }
|
||||||
size=v.size;
|
|
||||||
vec;
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
(*$T
|
(*$T
|
||||||
|
|
@ -286,17 +297,23 @@ let map f v =
|
||||||
*)
|
*)
|
||||||
|
|
||||||
let filter' p v =
|
let filter' p v =
|
||||||
let i = ref (v.size - 1) in
|
let i = ref 0 in (* cur element *)
|
||||||
while !i >= 0 do
|
let j = ref 0 in (* cur insertion point *)
|
||||||
if not (p v.vec.(! i))
|
let n = v.size in
|
||||||
(* remove i-th item! *)
|
while !i < n do
|
||||||
then remove v !i;
|
if p v.vec.(! i) then (
|
||||||
decr i
|
(* move element i at the first empty slot.
|
||||||
done
|
invariant: i >= j*)
|
||||||
|
if !i > !j then v.vec.(!j) <- v.vec.(!i);
|
||||||
|
incr i;
|
||||||
|
incr j
|
||||||
|
) else incr i
|
||||||
|
done;
|
||||||
|
v.size <- !j
|
||||||
|
|
||||||
(*$T
|
(*$T
|
||||||
let v = 1 -- 10 in filter' (fun x->x<4) v; \
|
let v = 1 -- 10 in filter' (fun x->x<4) v; \
|
||||||
to_list v |> List.sort Pervasives.compare = [1;2;3]
|
to_list v = [1;2;3]
|
||||||
*)
|
*)
|
||||||
|
|
||||||
let filter p v =
|
let filter p v =
|
||||||
|
|
@ -305,13 +322,14 @@ let filter p v =
|
||||||
else (
|
else (
|
||||||
let v' = create_with ~capacity:v.size v.vec.(0) in
|
let v' = create_with ~capacity:v.size v.vec.(0) in
|
||||||
Array.iter
|
Array.iter
|
||||||
(fun x -> if p x then push v' x)
|
(fun x -> if p x then push_unsafe v' x)
|
||||||
v.vec;
|
v.vec;
|
||||||
v'
|
v'
|
||||||
)
|
)
|
||||||
|
|
||||||
(*$T
|
(*$T
|
||||||
filter (fun x-> x mod 2=0) (of_list [1;2;3;4;5]) |> to_list = [2;4]
|
filter (fun x-> x mod 2=0) (of_list [1;2;3;4;5]) |> to_list = [2;4]
|
||||||
|
filter (fun x-> x mod 2=0) (1 -- 1_000_000) |> length = 500_000
|
||||||
*)
|
*)
|
||||||
|
|
||||||
let fold f acc v =
|
let fold f acc v =
|
||||||
|
|
@ -463,9 +481,13 @@ let of_list l = match l with
|
||||||
| [] -> create()
|
| [] -> create()
|
||||||
| x::_ ->
|
| x::_ ->
|
||||||
let v = create_with ~capacity:(List.length l + 5) x in
|
let v = create_with ~capacity:(List.length l + 5) x in
|
||||||
List.iter (push v) l;
|
List.iter (push_unsafe v) l;
|
||||||
v
|
v
|
||||||
|
|
||||||
|
(*$T
|
||||||
|
of_list CCList.(1--300_000) |> to_list = CCList.(1--300_000)
|
||||||
|
*)
|
||||||
|
|
||||||
let to_array v =
|
let to_array v =
|
||||||
Array.sub v.vec 0 v.size
|
Array.sub v.vec 0 v.size
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -134,8 +134,7 @@ val filter : ('a -> bool) -> ('a,_) t -> ('a, 'mut) t
|
||||||
returns a new vector that only contains elements of [v] satisfying [p]. *)
|
returns a new vector that only contains elements of [v] satisfying [p]. *)
|
||||||
|
|
||||||
val filter' : ('a -> bool) -> ('a, rw) t -> unit
|
val filter' : ('a -> bool) -> ('a, rw) t -> unit
|
||||||
(** Filter elements in place. Does {b NOT} preserve the order
|
(** Filter elements in place. *)
|
||||||
of the elements. *)
|
|
||||||
|
|
||||||
val fold : ('b -> 'a -> 'b) -> 'b -> ('a,_) t -> 'b
|
val fold : ('b -> 'a -> 'b) -> 'b -> ('a,_) t -> 'b
|
||||||
(** fold on elements of the vector *)
|
(** fold on elements of the vector *)
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue