(*************************************)
(*              PRIOQUEUE            *)
(*************************************)

module type PRIOQUEUE =
sig
  type priority = int

  type 'a queue               (* now abstract *)
  val empty : unit -> 'a queue
  val is_empty : 'a queue -> bool
  val insert : 'a queue -> priority -> 'a -> 'a queue
  val delete_min : 'a queue -> priority * 'a * 'a queue
  val find_min : 'a queue -> priority * 'a * 'a queue
  val union : 'a queue -> 'a queue -> 'a queue
  exception Queue_is_empty
end;;


(*************************************)
(*            CYCLE QUEUE            *)
(*************************************)

module type CYCLE_QUEUE =
sig
  type priority = int

  type 'a queue               (* now abstract *)
  val empty : unit -> 'a queue
  val is_empty : 'a queue -> bool
  val insert : 'a queue -> priority -> 'a -> 'a queue
  val delete_min : 'a queue -> priority * 'a * 'a queue
  val find_min : 'a queue -> priority * 'a * 'a queue
  val divide : 'a queue -> priority * 'a queue * 'a queue
  exception Queue_is_empty
  exception Queue_is_full
end;;


(*************************************)
(*     Number of array elements      *)
(*************************************)

module type SIZE =
sig
  val size : int
end;;

(*************************************)
(*     Keys  G E N E R A T O R       *)
(*************************************)

module type KEYS_GENERATOR =
sig

  val permutations : int -> int list list

  val list_i_to_j : int -> int -> int list

  val init_random : unit -> unit

  val random_int_from_i_to_j : int -> int -> int

  val list_of_n_rand_from_i_to_j :  int -> int -> int -> int list

  val prop_s_div_r : int -> int -> bool

  val add_k_min_to_l : int -> int -> int list -> int list

  val list_of_n_i : int -> int -> int list

  val randomize : float -> int list -> int list

end;;

module type PRIOQUEUE_TESTER = functor (Prioqueue : PRIOQUEUE) ->
sig

  type generation_method

  (* this module is parametrized *)
  (* feel free to change the default values *)
  (* though they can be changed dynamically *)

  (* P A R A M E T E R S *)

  (* elem and min need to be of same type 'a *)
  val min : int ref
  (* min should be only used with minimal key *)
  val elem : int ref
  (* defines the smallest key in the list *)
  val min_key : int ref
  (* number of min elements in generated keys list *)
  val num_of_min : int ref
  (* number of other elements in that same list *)
  val num_of_other : int ref
  (* number of devalions when testing speed *)
  val num_of_delete : int ref
  (* size of permutation when generated for stats *)
  val permutation_size : int ref
  (* how many elements will be inserted into queue 
     when generating stats about certain permutations *)
  val queue_input_size : int ref
  (* when random : float is level of randomization, 
     const means only min_key is in keys list *)
  val key_gen_method : generation_method ref
  (* defines hom many times a test will 
     be repeated for one permutation *)
  val how_precise : int ref
  (* please remember, that the same list is used for *)
  (* both speed and correctness testing *)
  val keys : Prioqueue.priority list ref

  (* M E T H O D S    F O R    M O D I F Y I N G    P A R A M E T E R S *)

  val max_permutation_size : int

  exception Parameter_value_is_to_low
  exception Parameter_value_is_to_high

  val set_min : Prioqueue.priority -> unit

  val set_elem : Prioqueue.priority -> unit

  val set_min_key : Prioqueue.priority -> unit

  val set_num_of_min : int -> unit

  val set_num_of_other : int -> unit

  val set_num_of_delete : int -> unit

  val set_same_ins_del : int -> unit

  val set_permutation_size : int -> unit

  val set_queue_input_size : int -> unit

  val set_key_gen_method : float -> unit

  val set_base_keys : Prioqueue.priority list -> unit

  val set_how_precise : int -> unit

  val key_gen : unit -> unit


  (* please remember, that the same list is used for *)
  (* both speed and correctness testing *)

  val keys : Prioqueue.priority list ref

  val key_gen : unit -> unit

  val correct_insert_find_min : unit -> bool

  val correct_insert_del_min : unit -> bool

  val speed_insert_del_min : unit -> float

  val correct_union : int -> bool

  val correct_union_all : unit -> bool

  val speed_union : int -> float

  val permutation_size : int ref

  val queue_input_size : int ref

  val how_precise : int ref

  val choose_best_permutations : unit -> (Prioqueue.priority list * float) list

  val statistics_of_best_permutations : unit -> (Prioqueue.priority list * float) list * float * float * float

end;;