mirror of
https://github.com/c-cube/sidekick.git
synced 2025-12-09 20:55:39 -05:00
perf(hash): use FNV hashing
This commit is contained in:
parent
18fbb950bc
commit
903243643f
1 changed files with 53 additions and 11 deletions
|
|
@ -3,24 +3,63 @@
|
||||||
|
|
||||||
type 'a t = 'a -> int
|
type 'a t = 'a -> int
|
||||||
|
|
||||||
let bool b = if b then 1 else 2
|
(* FNV hashing
|
||||||
|
https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function
|
||||||
|
*)
|
||||||
|
let fnv_offset_basis = 0xcbf29ce484222325L
|
||||||
|
let fnv_prime = 0x100000001b3L
|
||||||
|
|
||||||
let int i = i land max_int
|
(* hash an integer *)
|
||||||
|
let hash_int_ n =
|
||||||
|
let h = ref fnv_offset_basis in
|
||||||
|
for k = 0 to 7 do
|
||||||
|
h := Int64.(mul !h fnv_prime);
|
||||||
|
h := Int64.(logxor !h (of_int ((n lsr (k * 8)) land 0xff)));
|
||||||
|
done;
|
||||||
|
(Int64.to_int !h) land max_int (* truncate back to int and remove sign *)
|
||||||
|
|
||||||
let string (s:string) = Hashtbl.hash s
|
let combine2 a b =
|
||||||
|
let h = ref fnv_offset_basis in
|
||||||
|
(* we only do one loop, where we mix bytes of [a] and [b], so as
|
||||||
|
to simplify control flow *)
|
||||||
|
for k = 0 to 7 do
|
||||||
|
h := Int64.(mul !h fnv_prime);
|
||||||
|
h := Int64.(logxor !h (of_int ((a lsr (k * 8)) land 0xff)));
|
||||||
|
h := Int64.(mul !h fnv_prime);
|
||||||
|
h := Int64.(logxor !h (of_int ((b lsr (k * 8)) land 0xff)));
|
||||||
|
done;
|
||||||
|
Int64.to_int !h land max_int
|
||||||
|
|
||||||
let combine f a b = Hashtbl.seeded_hash a (f b)
|
let[@inline] combine f s x =
|
||||||
|
combine2 s (f x)
|
||||||
let combine2 a b = Hashtbl.seeded_hash a b
|
|
||||||
|
|
||||||
let combine3 a b c =
|
let combine3 a b c =
|
||||||
combine2 a b
|
let h = ref fnv_offset_basis in
|
||||||
|> combine2 c
|
(* we only do one loop, where we mix bytes of [a] [b] and [c], so as
|
||||||
|
to simplify control flow *)
|
||||||
|
for k = 0 to 7 do
|
||||||
|
h := Int64.(mul !h fnv_prime);
|
||||||
|
h := Int64.(logxor !h (of_int ((a lsr (k * 8)) land 0xff)));
|
||||||
|
h := Int64.(mul !h fnv_prime);
|
||||||
|
h := Int64.(logxor !h (of_int ((b lsr (k * 8)) land 0xff)));
|
||||||
|
h := Int64.(mul !h fnv_prime);
|
||||||
|
h := Int64.(logxor !h (of_int ((c lsr (k * 8)) land 0xff)));
|
||||||
|
done;
|
||||||
|
Int64.to_int !h land max_int
|
||||||
|
|
||||||
let combine4 a b c d =
|
let combine4 a b c d =
|
||||||
combine2 a b
|
let h = ref fnv_offset_basis in
|
||||||
|> combine2 c
|
for k = 0 to 7 do
|
||||||
|> combine2 d
|
h := Int64.(mul !h fnv_prime);
|
||||||
|
h := Int64.(logxor !h (of_int ((a lsr (k * 8)) land 0xff)));
|
||||||
|
h := Int64.(mul !h fnv_prime);
|
||||||
|
h := Int64.(logxor !h (of_int ((b lsr (k * 8)) land 0xff)));
|
||||||
|
h := Int64.(mul !h fnv_prime);
|
||||||
|
h := Int64.(logxor !h (of_int ((c lsr (k * 8)) land 0xff)));
|
||||||
|
h := Int64.(mul !h fnv_prime);
|
||||||
|
h := Int64.(logxor !h (of_int ((d lsr (k * 8)) land 0xff)));
|
||||||
|
done;
|
||||||
|
Int64.to_int !h land max_int
|
||||||
|
|
||||||
let pair f g (x,y) = combine2 (f x) (g y)
|
let pair f g (x,y) = combine2 (f x) (g y)
|
||||||
|
|
||||||
|
|
@ -28,9 +67,12 @@ let opt f = function
|
||||||
| None -> 42
|
| None -> 42
|
||||||
| Some x -> combine2 43 (f x)
|
| Some x -> combine2 43 (f x)
|
||||||
|
|
||||||
|
let int = hash_int_
|
||||||
|
let bool b = hash_int_ (if b then 1 else 2)
|
||||||
let list f l = List.fold_left (combine f) 0x42 l
|
let list f l = List.fold_left (combine f) 0x42 l
|
||||||
let array f = Array.fold_left (combine f) 0x43
|
let array f = Array.fold_left (combine f) 0x43
|
||||||
let iarray f = IArray.fold (combine f) 0x44
|
let iarray f = IArray.fold (combine f) 0x44
|
||||||
|
let string : string t = Hashtbl.hash
|
||||||
let seq f seq =
|
let seq f seq =
|
||||||
let h = ref 0x43 in
|
let h = ref 0x43 in
|
||||||
seq (fun x -> h := combine f !h x);
|
seq (fun x -> h := combine f !h x);
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue