module gmath_quicksort_types
  use gmath_messaging
  !---------------------------------------------------------------------
  !
  !---------------------------------------------------------------------
  !
  public :: gi4_quicksort_t,gi8_quicksort_t
  private
  !
  type, abstract :: gi4_quicksort_t
  contains
    procedure(gi4_compare_interface), public, deferred :: compare
    procedure,                        public           :: sort => gi4_quicksort_index_with_user_type
  end type gi4_quicksort_t
  !
  type, abstract :: gi8_quicksort_t
  contains
    procedure(gi8_compare_interface), public, deferred :: compare
    procedure,                        public           :: sort => gi8_quicksort_index_with_user_type
  end type gi8_quicksort_t
  !
  abstract interface
    function gi4_compare_interface(self,m,l)
      import :: gi4_quicksort_t
      !-----------------------------------------------------------------
      ! Return -1, 0, or +1 if the m-th value is lower, equal, or
      ! greater than the l-th one.
      !-----------------------------------------------------------------
      integer(kind=4) :: gi4_compare_interface
      class(gi4_quicksort_t), intent(in) :: self
      integer(kind=4),        intent(in) :: m,l
    end function gi4_compare_interface
  end interface
  !
  abstract interface
    function gi8_compare_interface(self,m,l)
      import :: gi8_quicksort_t
      !-----------------------------------------------------------------
      ! Return -1, 0, or +1 if the m-th value is lower, equal, or
      ! greater than the l-th one.
      !-----------------------------------------------------------------
      integer(kind=4) :: gi8_compare_interface
      class(gi8_quicksort_t), intent(in) :: self
      integer(kind=8),        intent(in) :: m,l
    end function gi8_compare_interface
  end interface
  !
contains
  !
  subroutine gi4_quicksort_index_with_user_type(self,x,n,error)
    !---------------------------------------------------------------------
    ! Sort an integer*4 index array according to an external comparison
    ! criteria. The index array can then be used by gi4_quicksort_array
    ! to sort an associated array.
    !---------------------------------------------------------------------
    class(gi4_quicksort_t), intent(in)    :: self   !
    integer(kind=4),        intent(in)    :: n      ! Length of index array
    integer(kind=4),        intent(inout) :: x(n)   ! Index array to be sorted
    logical,                intent(out)   :: error  ! Error status
    ! Local
    integer(kind=4), parameter :: maxstack=1000, nstop=15
    integer(kind=4) :: temp,key
    integer(kind=4) :: i,j,k,l,r,m
    integer(kind=4) :: lstack(maxstack),rstack(maxstack),sp
    !
    include 'quicksort-index-with-user-type.inc'
   end subroutine gi4_quicksort_index_with_user_type
  !
  subroutine gi8_quicksort_index_with_user_type(self,x,n,error)
    !---------------------------------------------------------------------
    ! Sort an integer*8 index array according to an external comparison
    ! criteria. The index array can then be used by gi8_quicksort_array
    ! to sort an associated array.
    !---------------------------------------------------------------------
    class(gi8_quicksort_t), intent(in)    :: self   !
    integer(kind=8),        intent(in)    :: n      ! Length of index array
    integer(kind=8),        intent(inout) :: x(n)   ! Index array to be sorted
    logical,                intent(out)   :: error  ! Error status
    ! Local
    integer(kind=4), parameter :: maxstack=1000, nstop=15
    integer(kind=8) :: temp,key
    integer(kind=8) :: i,j,k,l,r,m
    integer(kind=8) :: lstack(maxstack),rstack(maxstack),sp
    !
    include 'quicksort-index-with-user-type.inc'
   end subroutine gi8_quicksort_index_with_user_type
end module gmath_quicksort_types
