diff --git a/src/core/CCInt64.ml b/src/core/CCInt64.ml index ab290798..bb32d24c 100644 --- a/src/core/CCInt64.ml +++ b/src/core/CCInt64.ml @@ -11,6 +11,30 @@ let hash x = Stdlib.abs (to_int x) 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 rec aux acc = function | 1L -> acc diff --git a/src/core/CCInt64.mli b/src/core/CCInt64.mli index 3a55f996..39ccbeec 100644 --- a/src/core/CCInt64.mli +++ b/src/core/CCInt64.mli @@ -30,6 +30,10 @@ val hash : t -> int (** [hash x] computes the hash of [x]. Like {!Stdlib.abs (to_int x)}. *) +val popcount : t -> int +(** Number of bits set to 1. + @since NEXT_RELEASE *) + val sign : t -> int (** [sign x] return [0] if [x = 0], [-1] if [x < 0] and [1] if [x > 0]. Same as [compare x zero].