diff --git a/src/data/CCBV.ml b/src/data/CCBV.ml index c3a13979..2215e60b 100644 --- a/src/data/CCBV.ml +++ b/src/data/CCBV.ml @@ -165,20 +165,28 @@ let cardinal bv = *) let really_resize_ bv ~desired ~current size = - let b = Bytes.make desired zero in - Bytes.blit bv.b 0 b 0 current; - bv.b <- b; - bv.size <- size + bv.size <- size; + if desired <> current then ( + let b = Bytes.make desired zero in + Bytes.blit bv.b 0 b 0 current; + bv.b <- b; + ) + +let[@inline never] grow_real_ bv size = + (* beyond capacity *) + let desired = bytes_length_of_size size in + let current = Bytes.length bv.b in + assert (desired > current); + really_resize_ bv ~desired ~current size let grow_ bv size = - if size <= capacity bv (* within capacity *) - then bv.size <- size - else ( - (* beyond capacity *) - let desired = bytes_length_of_size size in - let current = Bytes.length bv.b in - assert (desired > current); - really_resize_ bv ~desired ~current size + if size <= capacity bv then ( + (* within capacity *) + bv.size <- size + ) else ( + (* resize. This is a separate function so it's easier to + inline the happy path. *) + grow_real_ bv size ) let shrink_ bv size = @@ -188,11 +196,19 @@ let shrink_ bv size = let resize bv size = if size < 0 then invalid_arg "resize: negative size"; - if size < bv.size (* shrink *) - then shrink_ bv size - else if size = bv.size - then () - else grow_ bv size + if size < bv.size then ( + bv.size <- size; + ) else if size > bv.size then ( + grow_ bv size + ) + +let resize_minimize_memory bv size = + if size < 0 then invalid_arg "resize: negative size"; + if size < bv.size then ( + shrink_ bv size + ) else if size > bv.size then ( + grow_ bv size + ) (*$R let bv1 = CCBV.create ~size:87 true in diff --git a/src/data/CCBV.mli b/src/data/CCBV.mli index e466b12b..d00747c2 100644 --- a/src/data/CCBV.mli +++ b/src/data/CCBV.mli @@ -39,10 +39,16 @@ val capacity : t -> int @since 1.2 *) val resize : t -> int -> unit -(** Resize the BV so that it has the specified length. This can grow or shrink - the underlying bitvector. +(** Resize the BV so that it has the specified length. This can grow + the underlying array, but it will not shrink it, to minimize + memory traffic. + @raise Invalid_argument on negative sizes. *) - @raise Invalid_arg on negative sizes. *) +val resize_minimize_memory : t -> int -> unit +(** Same as {!resize}, but this can also shrink the underlying + array if this reduces the size. + @raise Invalid_argument on negative sizes. + @since NEXT_RELEASE *) val is_empty : t -> bool (** Are there any true bits? *)