From 88f8bf707898701b5a1a14068038fac6263fb540 Mon Sep 17 00:00:00 2001 From: Rudi Grinberg Date: Sat, 30 Mar 2024 16:44:08 +0000 Subject: [PATCH] refactor: re-implement bit bector properly Signed-off-by: Rudi Grinberg --- lib/automata.ml | 4 +--- lib/bit_vector.ml | 49 ++++++++++++++++++++++++++++++++++++++-------- lib/bit_vector.mli | 2 +- 3 files changed, 43 insertions(+), 12 deletions(-) diff --git a/lib/automata.ml b/lib/automata.ml index 44f1f4ff..eefe14d6 100644 --- a/lib/automata.ml +++ b/lib/automata.ml @@ -330,8 +330,6 @@ let create_working_area () = ref (Bit_vector.singleton false) let index_count w = Bit_vector.length !w -let reset_table a = Bit_vector.set_all a false - let rec mark_used_indices tbl = List.iter (function | E.TSeq (l, _, _) -> mark_used_indices tbl l @@ -345,7 +343,7 @@ let rec find_free tbl idx len = let free_index tbl_ref l = let tbl = !tbl_ref in - reset_table tbl; + Bit_vector.reset_zero tbl; mark_used_indices tbl l; let len = Bit_vector.length tbl in let idx = find_free tbl 0 len in diff --git a/lib/bit_vector.ml b/lib/bit_vector.ml index f275dede..a731f1e8 100644 --- a/lib/bit_vector.ml +++ b/lib/bit_vector.ml @@ -1,14 +1,47 @@ -type t = bool array +type t = + { len : int + ; bits : Bytes.t + } +let byte s i = Char.code (Bytes.unsafe_get s i) -let singleton v = [| v |] +let low_mask = Array.init 9 (fun i -> (1 lsl i) - 1) +let set_byte s i x = Bytes.unsafe_set s i (Char.chr x) -let length t = Array.length t +let create len b = + let initv = if b then 255 else 0 in + let q = len lsr 3 in + let r = len land 7 in + if r = 0 then + { len ; bits = Bytes.make q (Char.chr initv) } + else begin + let s = Bytes.make (q + 1) (Char.chr initv) in + set_byte s q (initv land low_mask.(r)); + { len ; bits = s } + end -let set t i a = t.(i) <- a +let singleton v = create 1 v -let get t i = t.(i) +let length t = t.len -let create len v = Array.make len v +let unsafe_set v n b = + let i = n lsr 3 in + let c = byte v.bits i in + let mask = 1 lsl (n land 7) in + set_byte v.bits i (if b then c lor mask else c land (lnot mask)) -let set_all t v = - Array.fill t 0 (length t) v +let set v n b = + if n < 0 || n >= v.len then invalid_arg "Bitv.set"; + unsafe_set v n b + +let unsafe_get v n = + let i = n lsr 3 in + (byte v.bits i) land (1 lsl (n land 7)) > 0 + +let get v n = + if n < 0 || n >= v.len then invalid_arg "Bitv.get"; + unsafe_get v n + +let reset_zero t = + for i = 0 to Bytes.length t.bits - 1 do + Bytes.set t.bits i '\000' + done diff --git a/lib/bit_vector.mli b/lib/bit_vector.mli index 5155b312..c9420a1e 100644 --- a/lib/bit_vector.mli +++ b/lib/bit_vector.mli @@ -10,4 +10,4 @@ val create : int -> bool -> t val get : t -> int -> bool -val set_all : t -> bool -> unit +val reset_zero : t -> unit