feat(CCInt64): add popcount operation

adapted from CCInt, but directly on int64, so it works for
Int64.{min_int/max_int}.
This commit is contained in:
Simon Cruanes 2022-01-02 21:16:45 -05:00
parent 19c65b5472
commit 22bbe23c5a
No known key found for this signature in database
GPG key ID: 4AC01D0849AA62B6
2 changed files with 28 additions and 0 deletions

View file

@ -11,6 +11,30 @@ let hash x = Stdlib.abs (to_int x)
let sign i = compare i zero let sign i = compare i zero
(* see {!CCInt.popcount} for more details *)
let[@inline] popcount (b:t) : int =
let m1 = 0x5555555555555555L in
let m2 = 0x3333333333333333L in
let m4 = 0x0f0f0f0f0f0f0f0fL 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 = add b (shift_right_logical b 32) in
let b = logand b 0x7fL in
to_int b
(*$= & ~printer:CCInt.to_string
0 (popcount 0L)
1 (popcount 1L)
63 (popcount max_int)
1 (popcount min_int)
10 (popcount 0b1110010110110001010L)
5 (popcount 0b1101110000000000L)
*)
let pow a b = let pow a b =
let rec aux acc = function let rec aux acc = function
| 1L -> acc | 1L -> acc

View file

@ -30,6 +30,10 @@ val hash : t -> int
(** [hash x] computes the hash of [x]. (** [hash x] computes the hash of [x].
Like {!Stdlib.abs (to_int x)}. *) Like {!Stdlib.abs (to_int x)}. *)
val popcount : t -> int
(** Number of bits set to 1.
@since NEXT_RELEASE *)
val sign : t -> int val sign : t -> int
(** [sign x] return [0] if [x = 0], [-1] if [x < 0] and [1] if [x > 0]. (** [sign x] return [0] if [x = 0], [-1] if [x < 0] and [1] if [x > 0].
Same as [compare x zero]. Same as [compare x zero].