fix asymptotic behavior of resize functions

This commit is contained in:
Simon Cruanes 2021-10-21 11:07:11 -04:00
parent e6e07ba4da
commit 2c2fa5d008
No known key found for this signature in database
GPG key ID: 4AC01D0849AA62B6

View file

@ -138,9 +138,11 @@ let grow_with_ v ~filler:x =
Use a doubling-size strategy so that calling many times [ensure] will Use a doubling-size strategy so that calling many times [ensure] will
behave well *) behave well *)
let ensure_assuming_not_empty_ v ~size = let ensure_assuming_not_empty_ v ~size =
if size > Sys.max_array_length if size > Sys.max_array_length then (
then invalid_arg "vec.ensure: size too big" invalid_arg "vec.ensure: size too big"
else ( ) else if size < Array.length v.vec then (
() (* nothing to do *)
) else (
let n = ref (max 8 (Array.length v.vec)) in let n = ref (max 8 (Array.length v.vec)) in
while !n < size do n := min Sys.max_array_length (2* !n) done; while !n < size do n := min Sys.max_array_length (2* !n) done;
resize_ v !n v.vec.(0) resize_ v !n v.vec.(0)
@ -203,19 +205,17 @@ let push v x =
let resize_with v f size = let resize_with v f size =
if size<0 then invalid_arg "Vec.resize_with"; if size<0 then invalid_arg "Vec.resize_with";
let new_vec = if Array.length v.vec = 0 then (
if size >= Array.length v.vec then let new_vec = Array.init size f in
let new_vec = Array.make size (f 0) in v.vec <- new_vec;
Array.blit v.vec 0 new_vec 0 v.size; v.size <- size
new_vec ) else (
else ensure_assuming_not_empty_ v size;
v.vec for i = v.size to size - 1 do
in Array.unsafe_set v.vec i (f i)
for i = v.size to size - 1 do done;
Array.unsafe_set new_vec i (f i) v.size <- size
done; )
v.vec <- new_vec;
v.size <- size
(*$T (*$T
let v = make 1 0 in resize_with v (fun i -> i) 5; to_list v = [0;1;2;3;4] let v = make 1 0 in resize_with v (fun i -> i) 5; to_list v = [0;1;2;3;4]
@ -230,19 +230,17 @@ let resize_with v f size =
let resize_with_init v ~init size = let resize_with_init v ~init size =
if size<0 then invalid_arg "Vec.resize_with_init"; if size<0 then invalid_arg "Vec.resize_with_init";
let new_vec = if Array.length v.vec = 0 then (
if size >= Array.length v.vec then let vec = Array.make size init in
let new_vec = Array.make size init in v.vec <- vec;
Array.blit v.vec 0 new_vec 0 v.size; v.size <- size;
new_vec ) else (
else ensure_assuming_not_empty_ v size;
v.vec for i = v.size to size - 1 do
in Array.unsafe_set v.vec i init
for i = v.size to size - 1 do done;
Array.unsafe_set new_vec i init v.size <- size;
done; )
v.vec <- new_vec;
v.size <- size
(*$T (*$T
let v = make 1 0 in resize_with_init v ~init:1 5; to_list v = [0;1;1;1;1] let v = make 1 0 in resize_with_init v ~init:1 5; to_list v = [0;1;1;1;1]
@ -256,6 +254,11 @@ let resize_with_init v ~init size =
let v = make 5 0 in resize_with_init v ~init:1 5; List.length (to_list v) = 5 let v = make 5 0 in resize_with_init v ~init:1 5; List.length (to_list v) = 5
*) *)
(* test for asymptotic behavior *)
(*$T
let v =make 1 0 in for i=0 to 100_000 do resize_with_init v ~init:10 i; done; true
*)
(** Add all elements of b to a *) (** Add all elements of b to a *)
let append a b = let append a b =
if array_is_empty_ a then ( if array_is_empty_ a then (