(*Generated by Lem from sorting.lem.*)


open Lem_bool
open Lem_basic_classes
open Lem_maybe
open Lem_list
open Lem_num

(* ------------------------- *)
(* permutations              *)
(* ------------------------- *)

(*val isPermutation : forall 'a. Eq 'a => list 'a -> list 'a -> bool*)
(*val isPermutationBy : forall 'a. ('a -> 'a -> bool) -> list 'a -> list 'a -> bool*)

let rec isPermutationBy eq l1 l2 = ((match l1 with
  | [] -> list_null l2
  | (x :: xs) -> begin
      (match list_delete_first (eq x) l2 with
        | None -> false
        | Some ys -> isPermutationBy eq xs ys
      )
    end
))



(* ------------------------- *)
(* isSorted                  *)
(* ------------------------- *)

(* isSortedBy R l 
   checks, whether the list l is sorted by ordering R. 
   R should represent an order, i.e. it should be transitive.
   Different backends defined "isSorted" slightly differently. However,
   the definitions coincide for transitive R. Therefore there is the
   following restriction:

   WARNING: Use isSorted and isSortedBy only with transitive relations!
*)

(*val isSorted : forall 'a. Ord 'a => list 'a -> bool*)
(*val isSortedBy : forall 'a. ('a -> 'a -> bool) -> list 'a -> bool*)

(* DPM: rejigged the definition with a nested match to get past Coq's termination checker. *)
let rec isSortedBy cmp l = ((match l with
  | [] -> true
  | x1 :: xs ->
    (match xs with
      | [] -> true
      | x2 :: _ -> (cmp x1 x2 && isSortedBy cmp xs)
    )
))


(* ----------------------- *)
(* insertion sort          *)
(* ----------------------- *) 

(*val insert : forall 'a. Ord 'a => 'a -> list 'a -> list 'a*)
(*val insertBy : forall 'a. ('a -> 'a -> bool) -> 'a -> list 'a -> list 'a*)

(*val insertSort: forall 'a. Ord 'a => list 'a -> list 'a*)
(*val insertSortBy: forall 'a. ('a -> 'a -> bool) -> list 'a -> list 'a*)

let rec insertBy cmp e l = ((match l with
  | [] -> [e]
  | x :: xs -> if cmp x e then x :: (insertBy cmp e xs) else (e :: (x :: xs))
))

let insertSortBy cmp l = (List.fold_left (fun l e -> insertBy cmp e l) [] l)


(* ----------------------- *)
(* general sorting         *)
(* ----------------------- *) 

(*val sort: forall 'a. Ord 'a => list 'a -> list 'a*)
(*val sortBy: forall 'a. ('a -> 'a -> bool) -> list 'a -> list 'a*)
(*val sortByOrd: forall 'a. ('a -> 'a -> ordering) -> list 'a -> list 'a*)


