diff --git a/core/CCBV.ml b/core/CCBV.ml index 34f9a99a..37eeebb2 100644 --- a/core/CCBV.ml +++ b/core/CCBV.ml @@ -57,8 +57,21 @@ let create ~size default = { a = arr } end +(*$T + create ~size:17 true |> cardinal = 17 + create ~size:32 true |> cardinal= 32 + create ~size:132 true |> cardinal = 132 + create ~size:200 false |> cardinal = 0 + create ~size:29 true |> to_sorted_list = CCList.range 0 28 +*) + let copy bv = { a=Array.copy bv.a; } +(*$Q + (Q.list Q.small_int) (fun l -> \ + let bv = of_list l in to_list bv = to_list (copy bv)) +*) + let length bv = Array.length bv.a let resize bv len = @@ -109,6 +122,11 @@ let set bv i = let i = i - n * __width in bv.a.(n) <- bv.a.(n) lor (1 lsl i) +(*$T + let bv = create ~size:3 false in set bv 0; get bv 0 + let bv = create ~size:3 false in set bv 1; not (get bv 0) +*) + let reset bv i = let n = i / __width in if n >= Array.length bv.a @@ -116,6 +134,10 @@ let reset bv i = let i = i - n * __width in bv.a.(n) <- bv.a.(n) land (lnot (1 lsl i)) +(*$T + let bv = create ~size:3 false in set bv 0; reset bv 0; not (get bv 0) +*) + let flip bv i = let n = i / __width in if n >= Array.length bv.a @@ -126,6 +148,10 @@ let flip bv i = let clear bv = Array.iteri (fun i _ -> bv.a.(i) <- 0) bv.a +(*$T +let bv = create ~size:37 true in cardinal bv = 37 && (clear bv; cardinal bv= 0) +*) + let iter bv f = let len = Array.length bv.a in for n = 0 to len - 1 do @@ -145,17 +171,30 @@ let iter_true bv f = done done +(*$T + of_list [1;5;7] |> iter_true |> CCSequence.to_list |> List.sort CCOrd.compare = [1;5;7] +*) + let to_list bv = let l = ref [] in iter_true bv (fun i -> l := i :: !l); !l +let to_sorted_list bv = + List.rev (to_list bv) + let of_list l = let size = List.fold_left max 0 l in let bv = create ~size false in List.iter (fun i -> set bv i) l; bv +(*$T + of_list [1;32;64] |> CCFun.flip get 64 + of_list [1;32;64] |> CCFun.flip get 32 + of_list [1;31;63] |> CCFun.flip get 63 +*) + exception FoundFirst of int let first bv = @@ -165,9 +204,18 @@ let first bv = with FoundFirst i -> i +(*$T + of_list [50; 10; 17; 22; 3; 12] |> first = 3 +*) + let filter bv p = iter_true bv - (fun i -> if not (p i) then reset bv i) + (fun i -> if not (p i) then reset bv i) + +(*$T + let bv = of_list [1;2;3;4;5;6;7] in filter bv (fun x->x mod 2=0); \ + to_sorted_list bv = [2;4;6] +*) let union_into ~into bv = if length into < length bv @@ -182,6 +230,10 @@ let union bv1 bv2 = union_into ~into:bv bv2; bv +(*$T +union (of_list [1;2;3;4;5]) (of_list [7;3;5;6]) |> to_sorted_list = CCList.range 1 7 +*) + let inter_into ~into bv = let n = min (length into) (length bv) in for i = 0 to n - 1 do @@ -199,6 +251,10 @@ let inter bv1 bv2 = let () = inter_into ~into:bv bv1 in bv +(*$T + inter (of_list [1;2;3;4]) (of_list [2;4;6;1]) |> to_sorted_list = [1;2;4] +*) + let select bv arr = let l = ref [] in begin try @@ -222,3 +278,25 @@ let selecti bv arr = with Exit -> () end; !l + +(*$T + selecti (of_list [1;4;3]) [| 0;1;2;3;4;5;6;7;8 |] \ + |> List.sort CCOrd.compare = [1, 1; 3,3; 4,4] +*) + +type 'a sequence = ('a -> unit) -> unit + +let to_seq bv k = iter_true bv k + +let of_seq seq = + let l = ref [] and maxi = ref 0 in + seq (fun x -> l := x :: !l; maxi := max !maxi x); + let bv = create ~size:(!maxi+1) false in + List.iter (fun i -> set bv i) !l; + bv + +(*$T + CCList.range 0 10 |> CCList.to_seq |> of_seq |> to_seq \ + |> CCList.of_seq |> List.sort CCOrd.compare = CCList.range 0 10 +*) + diff --git a/core/CCBV.mli b/core/CCBV.mli index c32701bc..f3ffd3bb 100644 --- a/core/CCBV.mli +++ b/core/CCBV.mli @@ -73,6 +73,10 @@ val iter_true : t -> (int -> unit) -> unit val to_list : t -> int list (** List of indexes that are true *) +val to_sorted_list : t -> int list + (** Same as {!to_list}, but also guarantees the list is sorted in + increasing order *) + val of_list : int list -> t (** From a list of true bits *) @@ -104,3 +108,8 @@ val select : t -> 'a array -> 'a list val selecti : t -> 'a array -> ('a * int) list (** Same as {!select}, but selected elements are paired with their index *) + +type 'a sequence = ('a -> unit) -> unit + +val to_seq : t -> int sequence +val of_seq : int sequence -> t diff --git a/core/CCBool.ml b/core/CCBool.ml index 3db3dbc0..b890edeb 100644 --- a/core/CCBool.ml +++ b/core/CCBool.ml @@ -30,6 +30,8 @@ let equal a b = a=b let compare a b = Pervasives.compare a b +let negate x = not x + type 'a printer = Buffer.t -> 'a -> unit type 'a formatter = Format.formatter -> 'a -> unit diff --git a/core/CCBool.mli b/core/CCBool.mli index 0ea1131c..e0cc63bc 100644 --- a/core/CCBool.mli +++ b/core/CCBool.mli @@ -32,6 +32,8 @@ val compare : t -> t -> int val equal : t -> t -> bool +val negate : t -> t + type 'a printer = Buffer.t -> 'a -> unit type 'a formatter = Format.formatter -> 'a -> unit