wip: perf(bitvec): use a VecI32.t underneath

This commit is contained in:
Simon Cruanes 2021-08-18 12:43:56 -04:00
parent c81d10426f
commit 76df299a36
3 changed files with 22 additions and 25 deletions

View file

@ -1,55 +1,45 @@
type t = { type t = VecI32.t
mutable chunks: bytes; (* TODO: use a in32vec with bigarray *)
}
let create () : t = { let create () : t = VecI32.create ~cap:16 ()
chunks = Bytes.make 32 '\x00';
}
let i2c = Char.chr
let c2i = Char.code
(* from index to offset in bytes *) (* from index to offset in bytes *)
let[@inline] idx_bytes_ (i:int) : int = i lsr 3 let[@inline] idx_in_vec_ (i:int) : int = i lsr 5
(* from index to offset in a single char *) (* from index to offset in a single chunk *)
let mask_ = 0b111 let mask_ = 0b11111
(* number of bytes *) (* number of bytes *)
let[@inline] len_ (self:t) : int = Bytes.length self.chunks let[@inline] len_ (self:t) : int = VecI32.size self
let[@inline never] resize_ self idx : unit = let[@inline never] resize_ self idx : unit =
let new_size = let new_size =
min Sys.max_string_length min Sys.max_string_length
(max (idx+2) (let l = len_ self in l + 10 + l / 2)) (max (idx+2) (let l = len_ self in l + 10 + l / 2))
in in
let new_chunks = Bytes.make new_size (i2c 0) in VecI32.ensure_size self new_size;
Bytes.blit self.chunks 0 new_chunks 0 (len_ self);
self.chunks <- new_chunks;
assert (len_ self > idx) assert (len_ self > idx)
let[@inline] ensure_size self i = let[@inline] ensure_size self i =
let idx = idx_bytes_ i in let idx = idx_in_vec_ i in
if idx >= len_ self then ( if idx >= len_ self then (
resize_ self idx resize_ self idx
) )
let[@inline] get self i : bool = let[@inline] get self i : bool =
let idx = idx_bytes_ i in let idx = idx_in_vec_ i in
let c = c2i (Bytes.get self.chunks idx) in let c = VecI32.get self idx in
(c land (1 lsl (i land mask_))) <> 0 (c land (1 lsl (i land mask_))) <> 0
let set self i b : unit = let set self i b : unit =
let idx = idx_bytes_ i in let idx = idx_in_vec_ i in
let c = c2i (Bytes.get self.chunks idx) in let c = VecI32.get self idx in
let c = let c =
if b if b
then c lor (1 lsl (i land mask_)) then c lor (1 lsl (i land mask_))
else c land (lnot (1 lsl (i land mask_))) else c land (lnot (1 lsl (i land mask_)))
in in
Bytes.set self.chunks idx (i2c c) VecI32.set self idx c
let clear_all self = let clear_all self = VecI32.fill self 0
Bytes.fill self.chunks 0 (len_ self) '\x00'

View file

@ -18,6 +18,8 @@ let[@inline] shrink self n = if n < self.sz then self.sz <- n
let[@inline] size self = self.sz let[@inline] size self = self.sz
let[@inline] is_empty self = self.sz = 0 let[@inline] is_empty self = self.sz = 0
let[@inline] fill self x = A.fill self.data (Int32.of_int x)
(* ensure capacity is [new_cap] *) (* ensure capacity is [new_cap] *)
let resize_cap_ self new_cap = let resize_cap_ self new_cap =
assert (A.dim self.data < new_cap); assert (A.dim self.data < new_cap);
@ -34,7 +36,10 @@ let ensure_cap self (n:int) =
let ensure_size self n = let ensure_size self n =
if n > self.sz then ( if n > self.sz then (
ensure_cap self n; ensure_cap self n;
self.sz <- n for i=self.sz to n-1 do
A.set self.data i 0l;
done;
self.sz <- n;
) )
let[@inline] push (self:t) i : unit = let[@inline] push (self:t) i : unit =

View file

@ -11,6 +11,8 @@ val ensure_size : t -> int -> unit
val size : t -> int val size : t -> int
val fill : t -> int -> unit
val clear : t -> unit val clear : t -> unit
val is_empty : t -> bool val is_empty : t -> bool