type statistics = Stdcompat__hashtbl_ext.statistics
  = {
    num_bindings : int;
    num_buckets : int;
    max_bucket_length : int;
    bucket_histogram : int array;
  }

type ('a, 'b) t = ('a, 'b) Hashtbl.t

let clear = Hashtbl.clear

let copy = Hashtbl.copy

let add = Hashtbl.add

let find = Hashtbl.find

let find_all = Hashtbl.find_all

let mem = Hashtbl.mem

let remove = Hashtbl.remove

let replace = Hashtbl.replace

let iter = Hashtbl.iter

let fold = Hashtbl.fold

module type HashedType = Hashtbl.HashedType

let hash = Hashtbl.hash


let to_seq = Hashtbl.to_seq

let to_seq_values = Hashtbl.to_seq_values

let to_seq_keys = Hashtbl.to_seq_keys

let replace_seq = Hashtbl.replace_seq

let add_seq = Hashtbl.add_seq

let of_seq = Hashtbl.of_seq

(*

let to_seq = Stdcompat__hashtbl_ext.to_seq

let to_seq_keys = Stdcompat__hashtbl_ext.to_seq_keys

let to_seq_values = Stdcompat__hashtbl_ext.to_seq_values

(*
let to_seq tbl = Stdcompat__hashtbl_ext.to_seq Hashtbl.fold tbl

let to_seq_keys tbl = Stdcompat__hashtbl_ext.to_seq_keys Hashtbl.fold tbl

let to_seq_values tbl = Stdcompat__hashtbl_ext.to_seq_values Hashtbl.fold tbl
*)

let add_seq tbl g = Stdcompat__hashtbl_ext.add_seq Hashtbl.add tbl g

let replace_seq tbl g = Stdcompat__hashtbl_ext.add_seq Hashtbl.replace tbl g

let of_seq g =
  Stdcompat__hashtbl_ext.of_seq ~create:Hashtbl.create ~replace:Hashtbl.replace g
*)


let find_opt = Hashtbl.find_opt

(*
let find_opt tbl key =
  Stdcompat__tools.option_find (find tbl) key
*)


let is_randomized = Hashtbl.is_randomized

let filter_map_inplace = Hashtbl.filter_map_inplace

(*
let is_randomized () = false


let filter_map_inplace filter table =
  Stdcompat__hashtbl_ext.filter_map_inplace filter table

(*
let filter_map_inplace filter table =
  let dict = {
    Stdcompat__hashtbl_ext.clear = clear;
    Stdcompat__hashtbl_ext.fold = fold;
    Stdcompat__hashtbl_ext.add = add;
    Stdcompat__hashtbl_ext.remove = remove;
    Stdcompat__hashtbl_ext.replace = replace;
  } in
  Stdcompat__hashtbl_ext.filter_map_inplace dict filter table
*)
*)


let length = Hashtbl.length

(*

let length (table : ('a, 'b) t) =
  let table : ('a, 'b) Stdcompat__hashtbl_ext.internal = Obj.magic table in
  table.Stdcompat__hashtbl_ext.size

(*
let length table =
  fold (fun _ _ counter -> succ counter) table 0
*)
*)


let create = Hashtbl.create

let reset = Hashtbl.clear

let randomize = Hashtbl.randomize

let hash_param = Hashtbl.hash_param

let seeded_hash = Hashtbl.seeded_hash

let seeded_hash_param = Hashtbl.seeded_hash_param

let stats = Hashtbl.stats

(*
let create ?random n = Hashtbl.create n

let reset = clear

let randomize () = ()


external hash_param :
  int -> int -> 'a -> int = "caml_hash_univ_param" "noalloc"

(*
external hash_param :
  int -> int -> 'a -> int = "hash_univ_param" "noalloc"
*)

let seeded_hash seed x = Hashtbl.hash (seed, x)

let seeded_hash_param meaningful total seed x =
  Hashtbl.hash_param meaningful total (seed, x)


let stats (h : ('a, 'b) t) =
  Stdcompat__hashtbl_ext.stats h

(*
let stats h =
  Stdcompat__hashtbl_ext.stats ~length h
*)
*)

module type S = sig
  type key
  
    type !'a t
  
  (*
    type 'a t
  *)
  val create : int -> 'a t
  val clear : 'a t -> unit
  val reset : 'a t -> unit
  val copy : 'a t -> 'a t
  val add : 'a t -> key -> 'a -> unit
  val remove : 'a t -> key -> unit
  val find : 'a t -> key -> 'a
  val find_opt : 'a t -> key -> 'a option
  val find_all : 'a t -> key -> 'a list
  val replace : 'a t -> key -> 'a -> unit
  val mem : 'a t -> key -> bool
  val iter : (key -> 'a -> unit) -> 'a t -> unit
  val filter_map_inplace : (key -> 'a -> 'a option) -> 'a t -> unit
  val fold : (key -> 'a -> 'b -> 'b) -> 'a t -> 'b -> 'b
  val length : 'a t -> int
  val stats : 'a t -> statistics
  val to_seq : 'a t -> (key * 'a) Stdcompat__seq.t
  val to_seq_keys : 'a t -> key Stdcompat__seq.t
  val to_seq_values : 'a t -> 'a Stdcompat__seq.t
  val add_seq : 'a t -> (key * 'a) Stdcompat__seq.t -> unit
  val replace_seq : 'a t -> (key * 'a) Stdcompat__seq.t -> unit
  val of_seq : (key * 'a) Stdcompat__seq.t -> 'a t
end


module Make = Hashtbl.Make

(*
module Make (H : HashedType) = struct
  include Hashtbl.Make (H)


  let to_seq = Stdcompat__hashtbl_ext.to_seq

  let to_seq_keys = Stdcompat__hashtbl_ext.to_seq_keys

  let to_seq_values = Stdcompat__hashtbl_ext.to_seq_values

(*
  let to_seq tbl = Stdcompat__hashtbl_ext.to_seq fold tbl

  let to_seq_keys tbl = Stdcompat__hashtbl_ext.to_seq_keys fold tbl

  let to_seq_values tbl = Stdcompat__hashtbl_ext.to_seq_values fold tbl
*)

  let add_seq tbl g = Stdcompat__hashtbl_ext.add_seq add tbl g

  let replace_seq tbl g = Stdcompat__hashtbl_ext.add_seq replace tbl g

  let of_seq g = Stdcompat__hashtbl_ext.of_seq ~create ~replace g

(*
  let find_opt tbl key =
    Stdcompat__tools.option_find (find tbl) key
*)

(*

  let filter_map_inplace filter table =
    Stdcompat__hashtbl_ext.filter_map_inplace filter table

(*
  let filter_map_inplace filter table =
    let dict = {
      Stdcompat__hashtbl_ext.clear = clear;
      Stdcompat__hashtbl_ext.fold = fold;
      Stdcompat__hashtbl_ext.add = add;
      Stdcompat__hashtbl_ext.remove = remove;
      Stdcompat__hashtbl_ext.replace = replace;
    } in
    Stdcompat__hashtbl_ext.filter_map_inplace dict filter table
*)
*)

(*

  let length (table : 'a t) =
    let table : (key, 'a) Stdcompat__hashtbl_ext.internal = Obj.magic table in
    table.Stdcompat__hashtbl_ext.size

(*
  let length table =
    fold (fun _ _ counter -> succ counter) table 0
*)
*)

(*
  let create capacity = create capacity

  let reset = clear


  let stats (h : 'a t) =
    Stdcompat__hashtbl_ext.stats h

(*
  let stats h =
    Stdcompat__hashtbl_ext.stats ~length h
*)
*)
end
*)

module type SeededHashedType = sig
  type t

  val equal : t -> t -> bool

  val seeded_hash : int -> t -> int
end

module type SeededS = sig
  type key
  
    type !'a t
  
  (*
    type 'a t
  *)
  val create : ?random:bool -> int -> 'a t
  val clear : 'a t -> unit
  val reset : 'a t -> unit
  val copy : 'a t -> 'a t
  val add : 'a t -> key -> 'a -> unit
  val remove : 'a t -> key -> unit
  val find : 'a t -> key -> 'a
  val find_opt : 'a t -> key -> 'a option
  val find_all : 'a t -> key -> 'a list
  val replace : 'a t -> key -> 'a -> unit
  val mem : 'a t -> key -> bool
  val iter : (key -> 'a -> unit) -> 'a t -> unit
  val filter_map_inplace : (key -> 'a -> 'a option) -> 'a t -> unit
  val fold : (key -> 'a -> 'b -> 'b) -> 'a t -> 'b -> 'b
  val length : 'a t -> int
  val stats : 'a t -> statistics
  val to_seq : 'a t -> (key * 'a) Stdcompat__seq.t
  val to_seq_keys : 'a t -> key Stdcompat__seq.t
  val to_seq_values : 'a t -> 'a Stdcompat__seq.t
  val add_seq : 'a t -> (key * 'a) Stdcompat__seq.t -> unit
  val replace_seq : 'a t -> (key * 'a) Stdcompat__seq.t -> unit
  val of_seq : (key * 'a) Stdcompat__seq.t -> 'a t
end

(*
module MakeSeeded = Hashtbl.MakeSeeded
*)

module MakeSeeded (H : SeededHashedType) = struct
  include Stdcompat__hashtbl_ext.MakeSeeded (H)


  let to_seq = Stdcompat__hashtbl_ext.to_seq

  let to_seq_keys = Stdcompat__hashtbl_ext.to_seq_keys

  let to_seq_values = Stdcompat__hashtbl_ext.to_seq_values

(*
  let to_seq tbl = Stdcompat__hashtbl_ext.to_seq fold tbl

  let to_seq_keys tbl = Stdcompat__hashtbl_ext.to_seq_keys fold tbl

  let to_seq_values tbl = Stdcompat__hashtbl_ext.to_seq_values fold tbl
*)

  let add_seq tbl g = Stdcompat__hashtbl_ext.add_seq add tbl g

  let replace_seq tbl g = Stdcompat__hashtbl_ext.add_seq replace tbl g

  let of_seq g = Stdcompat__hashtbl_ext.of_seq ~create ~replace g

(*
  let find_opt tbl key =
    Stdcompat__tools.option_find (find tbl) key
*)

(*

  let filter_map_inplace filter table =
    Stdcompat__hashtbl_ext.filter_map_inplace filter table

(*
  let filter_map_inplace filter table =
    let dict = {
      Stdcompat__hashtbl_ext.clear = clear;
      Stdcompat__hashtbl_ext.fold = fold;
      Stdcompat__hashtbl_ext.add = add;
      Stdcompat__hashtbl_ext.remove = remove;
      Stdcompat__hashtbl_ext.replace = replace;
    } in
    Stdcompat__hashtbl_ext.filter_map_inplace dict filter table
*)
*)

(*

let length (table : 'a t) =
  let table : (key, 'a) Stdcompat__hashtbl_ext.internal = Obj.magic table in
  table.Stdcompat__hashtbl_ext.size

(*
let length table =
  fold (fun _ _ counter -> succ counter) table 0
*)
*)

(*
  let create ?random capacity = create capacity

  let reset = clear

  let stats tbl = {
      num_bindings = length tbl;
      num_buckets = 0;
      max_bucket_length = 0;
      bucket_histogram = [| |];
    }
*)
end



let rebuild = Hashtbl.rebuild

(*
let rebuild ?random tbl =
  let result = create ?random (stats tbl).num_buckets in
  iter (add result) tbl;
  result
*)
