mirror of
https://github.com/c-cube/ocaml-containers.git
synced 2025-12-10 05:03:54 -05:00
84 lines
1.9 KiB
OCaml
84 lines
1.9 KiB
OCaml
|
|
(* This file is free software, part of containers. See file "license" for more details. *)
|
|
|
|
(** {1 Hash combinators} *)
|
|
|
|
type hash = int
|
|
|
|
type 'a t = 'a -> hash
|
|
|
|
type 'a sequence = ('a -> unit) -> unit
|
|
type 'a gen = unit -> 'a option
|
|
type 'a klist = unit -> [`Nil | `Cons of 'a * 'a klist]
|
|
|
|
let combine f s x = Hashtbl.seeded_hash s (f x)
|
|
|
|
let combine2 a b = Hashtbl.seeded_hash a b
|
|
|
|
let combine3 a b c =
|
|
combine2 (combine2 a b) c
|
|
|
|
let combine4 a b c d =
|
|
combine2 (combine2 a b) (combine2 c d)
|
|
|
|
(** {2 Combinators} *)
|
|
|
|
let const h _ = h
|
|
let const0 _ = 0
|
|
|
|
let int i = i land max_int
|
|
let bool b = if b then 1 else 2
|
|
let char x = Char.code x
|
|
let int32 (x:int32) = Hashtbl.hash x
|
|
let int64 (x:int64) = Hashtbl.hash x
|
|
let nativeint (x:nativeint) = Hashtbl.hash x
|
|
let string (x:string) = Hashtbl.hash x
|
|
|
|
let slice x i len =
|
|
let j=i+len in
|
|
let rec aux i s =
|
|
if i=j then s else aux (i+1) (combine2 (char x.[i]) s)
|
|
in
|
|
aux i 0
|
|
|
|
let opt f = function
|
|
| None -> 42
|
|
| Some x -> combine2 43 (f x)
|
|
|
|
let list f l = List.fold_left (combine f) 0x42 l
|
|
let array f l = Array.fold_left (combine f) 0x42 l
|
|
|
|
let pair f g (x,y) = combine2 (f x) (g y)
|
|
let triple f g h (x,y,z) = combine2 (combine2 (f x) (g y)) (h z)
|
|
let quad f g h i (x,y,z,w) = combine2 (combine2 (f x) (g y)) (combine2 (h z) (i w))
|
|
|
|
let if_ b then_ else_ h =
|
|
if b then then_ h else else_ h
|
|
|
|
let poly x = Hashtbl.hash x
|
|
|
|
let array_comm f a =
|
|
let arr = Array.init (Array.length a) (fun i -> f a.(i)) in
|
|
Array.sort CCInt.compare arr; (* sort the hashes, so their order does not matter *)
|
|
array (fun h->h) arr
|
|
|
|
let list_comm f l =
|
|
let a = Array.of_list l in
|
|
array_comm f a
|
|
|
|
let seq f seq =
|
|
let h = ref 0x43 in
|
|
seq (fun x -> h := combine f !h x);
|
|
!h
|
|
|
|
let gen f g =
|
|
let rec aux s = match g () with
|
|
| None -> s
|
|
| Some x -> aux (combine2 s (f x))
|
|
in aux 0x42
|
|
|
|
let klist f l =
|
|
let rec aux l s = match l () with
|
|
| `Nil -> s
|
|
| `Cons (x,tail) -> aux tail (combine2 s (f x))
|
|
in aux l 0x42
|