mirror of
https://github.com/c-cube/ocaml-containers.git
synced 2025-12-06 03:05:28 -05:00
feat(CCInt32): add popcount function
This commit is contained in:
parent
22bbe23c5a
commit
b8c93f42fa
2 changed files with 34 additions and 0 deletions
|
|
@ -32,6 +32,36 @@ let pow a b =
|
|||
pow 0l 1l = 0l
|
||||
*)
|
||||
|
||||
(* see {!CCInt.popcount} for more details *)
|
||||
let[@inline] popcount (b:t) : int =
|
||||
let m1 = 0x55555555l in
|
||||
let m2 = 0x33333333l in
|
||||
let m4 = 0x0f0f0f0fl in
|
||||
|
||||
let b = sub b (logand (shift_right_logical b 1) m1) in
|
||||
let b = add (logand b m2) (logand (shift_right_logical b 2) m2) in
|
||||
let b = logand (add b (shift_right_logical b 4)) m4 in
|
||||
let b = add b (shift_right_logical b 8) in
|
||||
let b = add b (shift_right_logical b 16) in
|
||||
let b = logand b 0x7fl in
|
||||
to_int b
|
||||
|
||||
(*$Q
|
||||
Q.(0 -- (Int32.max_int |> Int32.to_int)) (fun i -> \
|
||||
let n1 = CCInt.popcount i in \
|
||||
let n2 = CCInt32.popcount (Int32.of_int i) in \
|
||||
CCInt.(n1 = n2))
|
||||
*)
|
||||
|
||||
(*$= & ~printer:CCInt.to_string
|
||||
0 (popcount 0l)
|
||||
1 (popcount 1l)
|
||||
31 (popcount max_int)
|
||||
1 (popcount min_int)
|
||||
10 (popcount 0b1110010110110001010l)
|
||||
5 (popcount 0b1101110000000000l)
|
||||
*)
|
||||
|
||||
let floor_div a n =
|
||||
if compare a 0l < 0 && compare n 0l >= 0 then
|
||||
sub (div (add a 1l) n) 1l
|
||||
|
|
|
|||
|
|
@ -41,6 +41,10 @@ val pow : t -> t -> t
|
|||
Raises [Invalid_argument] if [x = y = 0] or [y] < 0.
|
||||
@since 0.11 *)
|
||||
|
||||
val popcount : t -> int
|
||||
(** Number of bits set to 1.
|
||||
@since NEXT_RELEASE *)
|
||||
|
||||
val floor_div : t -> t -> t
|
||||
(** [floor_div x n] is integer division rounding towards negative infinity.
|
||||
It satisfies [x = m * floor_div x n + rem x n].
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue