mirror of
https://github.com/c-cube/ocaml-containers.git
synced 2025-12-06 11:15:31 -05:00
perf(ccint): single implementation of popcount using int64
This commit is contained in:
parent
8edddf5414
commit
6eab4269f1
1 changed files with 16 additions and 26 deletions
|
|
@ -332,14 +332,6 @@ let range_by ~step i j yield =
|
||||||
(CCInt.range i j |> Iter.to_list) )
|
(CCInt.range i j |> Iter.to_list) )
|
||||||
*)
|
*)
|
||||||
|
|
||||||
(* we use the simple version for non-64 bits. *)
|
|
||||||
let popcount_32 (b:int) : int =
|
|
||||||
let rec loop count x =
|
|
||||||
if x=0 then count
|
|
||||||
else loop (count+1) (x land (x-1))
|
|
||||||
in
|
|
||||||
loop 0 b
|
|
||||||
|
|
||||||
(*
|
(*
|
||||||
from https://en.wikipedia.org/wiki/Hamming_weight
|
from https://en.wikipedia.org/wiki/Hamming_weight
|
||||||
|
|
||||||
|
|
@ -360,25 +352,23 @@ let popcount_32 (b:int) : int =
|
||||||
m2 = 0x3333333333333333
|
m2 = 0x3333333333333333
|
||||||
m4 = 0x0f0f0f0f0f0f0f0f
|
m4 = 0x0f0f0f0f0f0f0f0f
|
||||||
*)
|
*)
|
||||||
let popcount_64 (b:int) : int =
|
let popcount (b:int) : int =
|
||||||
(* break up into parts to allow compilation on 32-bit and jsoo *)
|
let m1 = 0x5555555555555555L in
|
||||||
let m1 = 0x55555555 lor 0x55555555 lsl 32 in
|
let m2 = 0x3333333333333333L in
|
||||||
let m2 = 0x33333333 lor 0x33333333 lsl 32 in
|
let m4 = 0x0f0f0f0f0f0f0f0fL in
|
||||||
let m4 = 0x0f0f0f0f lor 0x0f0f0f0f lsl 32 in
|
let open Int64 in
|
||||||
let b = b - ((b lsr 1) land m1) in
|
|
||||||
let b = (b land m2) + ((b lsr 2) land m2) in
|
|
||||||
let b = (b + (b lsr 4)) land m4 in
|
|
||||||
let b = b + (b lsr 8) in
|
|
||||||
let b = b + (b lsr 16) in
|
|
||||||
let b = b + (b lsr 32) in
|
|
||||||
b land 0x7f
|
|
||||||
|
|
||||||
(* pick at runtime, see:
|
let b = of_int b in (* int->int64 *)
|
||||||
- https://github.com/c-cube/ocaml-containers/issues/346
|
let b = logand b 0x7fffffffffffffffL in (* remove sign bit, we deal with uint64 here *)
|
||||||
- https://github.com/ocsigen/js_of_ocaml/issues/1079
|
|
||||||
*)
|
let b = sub b (logand (shift_right_logical b 1) m1) in
|
||||||
let popcount =
|
let b = add (logand b m2) (logand (shift_right_logical b 2) m2) in
|
||||||
if Sys.int_size = 63 then popcount_64 else popcount_32
|
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
|
||||||
|
|
||||||
(*$=
|
(*$=
|
||||||
0 (popcount 0)
|
0 (popcount 0)
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue