subroutine gr8_trie_i4(x,it,n,error)
  use gbl_message
  use gmath_interfaces, except_this=>gr8_trie_i4
  !---------------------------------------------------------------------
  ! @ public-generic gr8_trie
  !  Sorting program that uses a quicksort algorithm.
  ! Applies for an input array of real*8 values. Also returns an array
  ! of indexes sorted for increasing order of X which can used in
  ! GR8_SORT to reorder other arrays
  ! ---
  !  This version for I*4 indices
  !---------------------------------------------------------------------
  integer(kind=4), intent(in)    :: n      ! Length of arrays
  real(kind=8),    intent(inout) :: x(n)   ! Unsorted array
  integer(kind=4), intent(out)   :: it(n)  ! Integer array of sorted indexes
  logical,         intent(out)   :: error  ! Error flag
  ! Local
  integer(kind=4), parameter :: maxstack=1000,nstop=15
  integer(kind=4) :: i,j,k,itemp
  integer(kind=4) :: l,r,m,lstack(maxstack),rstack(maxstack),sp
  real(kind=8) :: temp,key
  !
  include 'quicksort-index-numeric.inc'
end subroutine gr8_trie_i4
!
subroutine gr8_trie_i8(x,it,n,error)
  use gbl_message
  use gmath_interfaces, except_this=>gr8_trie_i8
  !---------------------------------------------------------------------
  ! @ public-generic gr8_trie
  !  Sorting program that uses a quicksort algorithm.
  ! Applies for an input array of real*8 values. Also returns an array
  ! of indexes sorted for increasing order of X which can used in
  ! GR8_SORT to reorder other arrays
  ! ---
  !  This version for I*8 indices
  !---------------------------------------------------------------------
  integer(kind=8), intent(in)    :: n      ! Length of arrays
  real(kind=8),    intent(inout) :: x(n)   ! Unsorted array
  integer(kind=8), intent(out)   :: it(n)  ! Integer array of sorted indexes
  logical,         intent(out)   :: error  ! Error flag
  ! Local
  integer(kind=8), parameter :: maxstack=1000,nstop=15
  integer(kind=8) :: i,j,k,itemp
  integer(kind=8) :: l,r,m,lstack(maxstack),rstack(maxstack),sp
  real(kind=8) :: temp,key
  !
  include 'quicksort-index-numeric.inc'
end subroutine gr8_trie_i8
!
subroutine gr8_sort(x,xwork,key,n)
  use gmath_interfaces, except_this=>gr8_sort
  !---------------------------------------------------------------------
  ! @ public-mandatory (because symbol is used elsewhere)
  !  Reorder a real*8 array by increasing order using the sorted indexes
  ! computed by a G*_TRIE subroutine
  !---------------------------------------------------------------------
  integer(kind=4), intent(in)    :: n         ! Length of arrays
  real(kind=8),    intent(inout) :: x(n)      ! Unsorted array
  real(kind=8)                   :: xwork(n)  ! Working buffer
  integer(kind=4), intent(in)    :: key(n)    ! Integer array of sorted indexes
  ! Local
  integer(kind=4) :: i
  !
  if (n.le.1) return
  do i=1,n
    xwork(i) = x(key(i))
  enddo
  do i=1,n
    x(i) = xwork(i)
  enddo
end subroutine gr8_sort
!
subroutine gr4_trie_i4(x,it,n,error)
  use gbl_message
  use gmath_interfaces, except_this=>gr4_trie_i4
  !---------------------------------------------------------------------
  ! @ public-generic gr4_trie
  !  Sorting program that uses a quicksort algorithm.
  !  Applies for an input array of real*4 values. Also returns an array
  ! of indexes sorted for increasing order of X which can used in
  ! GR4_SORT to reorder other arrays
  ! ---
  !  This version for I*4 indices
  !---------------------------------------------------------------------
  integer(kind=4), intent(in)    :: n      !
  real(kind=4),    intent(inout) :: x(n)   !
  integer(kind=4), intent(out)   :: it(n)  !
  logical,         intent(out)   :: error  !
  ! Local
  integer(kind=4), parameter :: maxstack=1000,nstop=15
  integer(kind=4) :: i,j,k,itemp,l,r,m
  integer(kind=4) :: lstack(maxstack),rstack(maxstack),sp
  real(kind=4) :: temp,key
  !
  include 'quicksort-index-numeric.inc'
end subroutine gr4_trie_i4
!
subroutine gr4_trie_i8(x,it,n,error)
  use gbl_message
  use gmath_interfaces, except_this=>gr4_trie_i8
  !---------------------------------------------------------------------
  ! @ public-generic gr4_trie
  !  Sorting program that uses a quicksort algorithm.
  !  Applies for an input array of real*4 values. Also returns an array
  ! of indexes sorted for increasing order of X which can used in
  ! GR4_SORT to reorder other arrays
  ! ---
  !  This version for I*8 indices
  !---------------------------------------------------------------------
  integer(kind=8), intent(in)    :: n      !
  real(kind=4),    intent(inout) :: x(n)   !
  integer(kind=8), intent(out)   :: it(n)  !
  logical,         intent(out)   :: error  !
  ! Local
  integer(kind=4), parameter :: maxstack=1000,nstop=15
  integer(kind=4) :: i,j,k,itemp,l,r,m
  integer(kind=4) :: lstack(maxstack),rstack(maxstack),sp
  real(kind=4) :: temp,key
  !
  include 'quicksort-index-numeric.inc'
end subroutine gr4_trie_i8
!
subroutine gr4_sort(x,xwork,key,n)
  use gmath_interfaces, except_this=>gr4_sort
  !---------------------------------------------------------------------
  ! @ public-mandatory (because symbol is used elsewhere)
  !  Reorder a real*4 array by increasing order using the sorted indexes
  ! computed by a G*_TRIE subroutine
  !---------------------------------------------------------------------
  integer(kind=4), intent(in)    :: n         !
  real(kind=4),    intent(inout) :: x(n)      !
  real(kind=4)                   :: xwork(n)  ! Working buffer
  integer(kind=4), intent(in)    :: key(n)    !
  ! Local
  integer(kind=4) :: i
  !
  if (n.le.1) return
  do i=1,n
    xwork(i) = x(key(i))
  enddo
  do i=1,n
    x(i) = xwork(i)
  enddo
end subroutine gr4_sort
!
subroutine gi4_trie_i4(x,it,n,error)
  use gbl_message
  use gmath_interfaces, except_this=>gi4_trie_i4
  !---------------------------------------------------------------------
  ! @ public-generic gi4_trie
  !  Sorting program that uses a quicksort algorithm.
  !  Applies for an input array of integer*4 values. Also returns an
  ! array of indexes sorted for increasing order of X which can used in
  ! GI4_SORT to reorder other arrays
  ! ---
  !  This version for I*4 indices
  !---------------------------------------------------------------------
  integer(kind=4), intent(in)    :: n      ! Length of arrays
  integer(kind=4), intent(inout) :: x(n)   ! Unsorted array
  integer(kind=4), intent(out)   :: it(n)  ! Integer array of sorted indexes
  logical,         intent(out)   :: error  ! Error flag
  ! Local
  integer(kind=4), parameter :: maxstack=1000,nstop=15
  integer(kind=4) :: i,j,k,itemp,l,r,m
  integer(kind=4) :: lstack(maxstack),rstack(maxstack),sp
  integer(kind=4) :: temp,key
  !
  include 'quicksort-index-numeric.inc'
end subroutine gi4_trie_i4
!
subroutine gi4_trie_i8(x,it,n,error)
  use gbl_message
  use gmath_interfaces, except_this=>gi4_trie_i8
  !---------------------------------------------------------------------
  ! @ public-generic gi4_trie
  !  Sorting program that uses a quicksort algorithm.
  !  Applies for an input array of integer*4 values. Also returns an
  ! array of indexes sorted for increasing order of X which can used in
  ! GI4_SORT to reorder other arrays
  ! ---
  !  This version for I*8 indices
  !---------------------------------------------------------------------
  integer(kind=8), intent(in)    :: n      ! Length of arrays
  integer(kind=4), intent(inout) :: x(n)   ! Unsorted array
  integer(kind=8), intent(out)   :: it(n)  ! Integer array of sorted indexes
  logical,         intent(out)   :: error  ! Error flag
  ! Local
  integer(kind=8), parameter :: maxstack=1000,nstop=15
  integer(kind=8) :: i,j,k,itemp,l,r,m
  integer(kind=8) :: lstack(maxstack),rstack(maxstack),sp
  integer(kind=4) :: temp,key
  !
  include 'quicksort-index-numeric.inc'
end subroutine gi4_trie_i8
!
subroutine gi4_sort(x,xwork,key,n)
  use gmath_interfaces, except_this=>gi4_sort
  !---------------------------------------------------------------------
  ! @ public-mandatory (because symbol is used elsewhere)
  !  Reorder an integer*4 array by increasing order using the sorted
  ! indexes computed by a G*_TRIE subroutine
  !---------------------------------------------------------------------
  integer(kind=4), intent(in)    :: n         ! Length of arrays
  integer(kind=4), intent(inout) :: x(n)      ! Unsorted array
  integer(kind=4)                :: xwork(n)  ! Working buffer
  integer(kind=4), intent(in)    :: key(n)    ! Integer array of sorted indexes
  ! Local
  integer(kind=4) :: i
  !
  if (n.le.1) return
  do i=1,n
    xwork(i) = x(key(i))
  enddo
  do i=1,n
    x(i) = xwork(i)
  enddo
end subroutine gi4_sort
!
subroutine gi8_trie_i4(x,it,n,error)
  use gbl_message
  use gmath_interfaces, except_this=>gi8_trie_i4
  !---------------------------------------------------------------------
  ! @ public-generic gi8_trie
  !  Sorting program that uses a quicksort algorithm.
  !  Applies for an input array of integer*8 values. Also returns an
  ! array of indexes sorted for increasing order of X which can used in
  ! GI8_SORT to reorder other arrays
  ! ---
  !  This version for I*4 indices
  !---------------------------------------------------------------------
  integer(kind=4), intent(in)    :: n      ! Length of arrays
  integer(kind=8), intent(inout) :: x(n)   ! Unsorted array
  integer(kind=4), intent(out)   :: it(n)  ! Integer array of sorted indexes
  logical,         intent(out)   :: error  ! Error flag
  ! Local
  integer(kind=4), parameter :: maxstack=1000,nstop=15
  integer(kind=4) :: i,j,k,itemp,l,r,m
  integer(kind=4) :: lstack(maxstack),rstack(maxstack),sp
  integer(kind=8) :: temp,key
  !
  include 'quicksort-index-numeric.inc'
end subroutine gi8_trie_i4
!
subroutine gi8_trie_i8(x,it,n,error)
  use gbl_message
  use gmath_interfaces, except_this=>gi8_trie_i8
  !---------------------------------------------------------------------
  ! @ public-generic gi8_trie
  !  Sorting program that uses a quicksort algorithm.
  !  Applies for an input array of integer*8 values. Also returns an
  ! array of indexes sorted for increasing order of X which can used in
  ! GI8_SORT to reorder other arrays
  ! ---
  !  This version for I*8 indices
  !---------------------------------------------------------------------
  integer(kind=8), intent(in)    :: n      ! Length of arrays
  integer(kind=8), intent(inout) :: x(n)   ! Unsorted array
  integer(kind=8), intent(out)   :: it(n)  ! Integer array of sorted indexes
  logical,         intent(out)   :: error  ! Error flag
  ! Local
  integer(kind=8), parameter :: maxstack=1000,nstop=15
  integer(kind=8) :: i,j,k,itemp,l,r,m
  integer(kind=8) :: lstack(maxstack),rstack(maxstack),sp
  integer(kind=8) :: temp,key
  !
  include 'quicksort-index-numeric.inc'
end subroutine gi8_trie_i8
!
subroutine gi8_sort(x,xwork,key,n)
  use gmath_interfaces, except_this=>gi8_sort
  !---------------------------------------------------------------------
  ! @ public-mandatory (because symbol is used elsewhere)
  !  Reorder an integer*8 array by increasing order using the sorted
  ! indexes computed by a G*_TRIE subroutine
  !---------------------------------------------------------------------
  integer(kind=4), intent(in)    :: n         ! Length of arrays
  integer(kind=8), intent(inout) :: x(n)      ! Unsorted array
  integer(kind=8)                :: xwork(n)  ! Working buffer
  integer(kind=4), intent(in)    :: key(n)    ! Integer array of sorted indexes
  ! Local
  integer(kind=4) :: i
  !
  if (n.le.1) return
  do i=1,n
    xwork(i) = x(key(i))
  enddo
  do i=1,n
    x(i) = xwork(i)
  enddo
end subroutine gi8_sort
!
subroutine gch_trie_i4(x,it,n,nc,error)
  use gbl_message
  use gmath_interfaces, except_this=>gch_trie_i4
  !---------------------------------------------------------------------
  ! @ public-generic gch_trie
  !  Sorting program that uses a quicksort algorithm.
  !  Applies for an input array of CHARACTER(len=*) values. Also returns
  ! an array of indexes sorted for increasing order of X which can used
  ! in GCH_SORT to reorder other arrays
  ! ---
  !  This version for I*4 indices
  !---------------------------------------------------------------------
  integer(kind=4),   intent(in)    :: n      ! Length of arrays
  integer(kind=4),   intent(in)    :: nc     ! Size of strings
  character(len=nc), intent(inout) :: x(n)   ! Unsorted array
  integer(kind=4),   intent(out)   :: it(n)  ! Integer array of sorted indexes
  logical,           intent(out)   :: error  ! Error flag
  ! Local
  integer(kind=4), parameter :: maxstack=1000,nstop=15
  integer(kind=4) :: i,j,k,itemp,l,r,m
  integer(kind=4) :: lstack(maxstack),rstack(maxstack),sp
  character(len=nc) :: temp,key
  !
  include 'quicksort-index-character.inc'
end subroutine gch_trie_i4
!
subroutine gch_trie_i8(x,it,n,nc,error)
  use gbl_message
  use gmath_interfaces, except_this=>gch_trie_i8
  !---------------------------------------------------------------------
  ! @ public-generic gch_trie
  !  Sorting program that uses a quicksort algorithm.
  !  Applies for an input array of CHARACTER(len=*) values. Also returns
  ! an array of indexes sorted for increasing order of X which can used
  ! in GCH_SORT to reorder other arrays
  ! ---
  !  This version for I*8 indices
  !---------------------------------------------------------------------
  integer(kind=8),   intent(in)    :: n      ! Length of arrays
  integer(kind=4),   intent(in)    :: nc     ! Size of strings
  character(len=nc), intent(inout) :: x(n)   ! Unsorted array
  integer(kind=8),   intent(out)   :: it(n)  ! Integer array of sorted indexes
  logical,           intent(out)   :: error  ! Error flag
  ! Local
  integer(kind=8), parameter :: maxstack=1000,nstop=15
  integer(kind=8) :: i,j,k,itemp,l,r,m
  integer(kind=8) :: lstack(maxstack),rstack(maxstack),sp
  character(len=nc) :: temp,key
  !
  include 'quicksort-index-character.inc'
end subroutine gch_trie_i8
!
subroutine gch_sort(x,xwork,key,nc,n)
  use gmath_interfaces, except_this=>gch_sort
  !---------------------------------------------------------------------
  ! @ public-mandatory (because symbol is used elsewhere)
  !   Reorder a character array by increasing order using the sorted
  ! indexes computed by a G*_TRIE subroutine
  !---------------------------------------------------------------------
  integer(kind=4),   intent(in)    :: nc        ! Size of strings
  character(len=nc), intent(inout) :: x(*)      ! The array
  character(len=nc)                :: xwork(*)  ! Work buffer
  integer(kind=4),   intent(in)    :: key(*)    ! Integer array of sorted indexes
  integer(kind=4),   intent(in)    :: n         ! Length of arrays
  ! Local
  integer(kind=4) :: i
  !
  if (n.le.1) return
  do i=1,n
    xwork(i) = x(key(i))
  enddo
  do i=1,n
    x(i) = xwork(i)
  enddo
end subroutine gch_sort
!
subroutine gl_sort(x,xwork,key,n)
  use gmath_interfaces, except_this=>gl_sort
  !---------------------------------------------------------------------
  ! @ public-mandatory (because symbol is used elsewhere)
  !  Reorder a logical*4 array by increasing order using the sorted
  ! indexes computed by a G*_TRIE subroutine
  !---------------------------------------------------------------------
  integer(kind=4), intent(in)    :: n         ! Length of arrays
  logical,         intent(inout) :: x(n)      ! Unsorted array
  logical                        :: xwork(n)  ! Working buffer
  integer(kind=4), intent(in)    :: key(n)    ! Integer array of sorted indexes
  ! Local
  integer(kind=4) :: i
  !
  if (n.le.1) return
  do i=1,n
    xwork(i) = x(key(i))
  enddo
  do i=1,n
    x(i) = xwork(i)
  enddo
end subroutine gl_sort
!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
subroutine gi4_quicksort_index_with_user_gtge(x,n,ugt,uge,error)
  use gmath_interfaces, except_this=>gi4_quicksort_index_with_user_gtge
  use gbl_message
  !---------------------------------------------------------------------
  ! @ public-generic gi0_quicksort_index_with_user_gtge
  ! 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.
  !---------------------------------------------------------------------
  integer(kind=4), intent(in)    :: n      ! Length of index array
  integer(kind=4), intent(inout) :: x(n)   ! Index array to be sorted
  logical,         external      :: ugt    ! User greater than
  logical,         external      :: uge    ! User greater than or equal
  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-gtge.inc'
end subroutine gi4_quicksort_index_with_user_gtge
!
subroutine gi8_quicksort_index_with_user_gtge(x,n,ugt,uge,error)
  use gmath_interfaces, except_this=>gi8_quicksort_index_with_user_gtge
  use gbl_message
  !---------------------------------------------------------------------
  ! @ public-generic gi0_quicksort_index_with_user_gtge
  ! Sort an integer*8 index array according to an external comparison
  ! criteria. The index array can then be used by gi4_quicksort_array
  ! to sort an associated array.
  !---------------------------------------------------------------------
  integer(kind=8), intent(in)    :: n      ! Length of index array
  integer(kind=8), intent(inout) :: x(n)   ! Index array to be sorted
  logical,         external      :: ugt    ! User greater than
  logical,         external      :: uge    ! User greater than or equal
  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-gtge.inc'
end subroutine gi8_quicksort_index_with_user_gtge
!
subroutine gi4_quicksort_array(array,work,index,n,error)
  use gmath_interfaces, except_this=>gi4_quicksort_array
  use gbl_message
  !---------------------------------------------------------------------
  ! @ private
  ! Reorder an integer(4) array by increasing order using the sorted
  ! index computed by gi4_quicksort_index
  !---------------------------------------------------------------------
  integer(kind=4), intent(in)    :: n         ! Length of arrays
  integer(kind=4), intent(inout) :: array(n)  ! Array
  integer(kind=4), intent(inout) :: work(n)   ! Work space
  integer(kind=4), intent(in)    :: index(n)  ! index array
  logical,         intent(out)   :: error     ! Error status
  ! Local
  integer(kind=4) :: i
  !
  error = .false.
  if (n.le.1) then
     call gmath_message(seve%e,'SORT','Input array dimension < 1')
     error = .true.
     return
  endif
  do i=1,n
    work(i) = array(index(i))
  enddo
  do i=1,n
    array(i) = work(i)
  enddo
end subroutine gi4_quicksort_array
!
function gr8_in (x0,y0,ngon,gons,bound)
  use gmath_interfaces, except_this=>gr8_in
  !---------------------------------------------------------------------
  ! @ public
  ! Find if a point is within a n-gon.
  !
  ! This uses the Ray casting algorithm, counting how many times a ray
  ! starting from the point crosses the polygon boundaries. Note that
  ! there are critical conditions to be taken into account when the
  ! point is on a vertex or on a boundary or when the ray strikes
  ! through a vertex.
  ! References:
  !  https://en.wikipedia.org/wiki/Point_in_polygon
  !  https://rosettacode.org/wiki/Ray-casting_algorithm
  !---------------------------------------------------------------------
  logical :: gr8_in  ! Function value on return
  real(kind=8),    intent(in) :: x0,y0      ! Coordinate of point to test
  integer(kind=4), intent(in) :: ngon       ! Current number of summits
  real(kind=8),    intent(in) :: gons(:,:)  ! Description of polygon
  real(kind=8),    intent(in) :: bound(5)   ! Polygon boundary
  ! Local
  integer(kind=4) :: index,i
  real(kind=8) :: d,x,y,xx
  logical :: yin
  !
  ! Quick check.
  if (x0.lt.bound(2) .or. x0.gt.bound(3) .or.  &
      y0.lt.bound(4) .or. y0.gt.bound(5)) then
    gr8_in = .false.
    return
  endif
  gr8_in = .true.
  !
  ! Count intersection.
  x = x0
  y = y0
  index = 0
  do i=1,ngon
    !
    if (x0.eq.gons(i,1) .and. y0.eq.gons(i,2)) then
      return                   ! Summit is in
    endif
    !
    ! Ray on vertex?
    if (y0.eq.gons(i,2) .or. y0.eq.gons(i+1,2)) then
      ! To avoid the "ray on vertex" problem, the point is moved upward
      ! of a small quantity. Otherwise it would always be considered to
      ! cross the 2 segments connected to the vertex and might mess the
      ! intersection count.
      y = y0+(bound(5)-bound(4))*1.d-9
    else
      y = y0
    endif
    !
    ! Check Y range
    if (y.le.gons(i,2) .and. y.ge.gons(i+1,2)) then
      yin = .true.
    elseif (y.ge.gons(i,2) .and. y.le.gons(i+1,2)) then
      yin = .true.
    else
      yin = .false.
    endif
    !
    ! If Y is OK, check X
    if (yin) then
      !
      ! Polygon side is normal
      if (gons(i,3).ne.0) then
        d = gons(i,4)/gons(i,3)
        ! Lines intersect
        if (d.ne.0d0) then
          xx =  (y-gons(i,2))/d + gons(i,1)
          if (xx.lt.x) then
            index = index+1
          elseif (xx.eq.x) then
            return
          endif
          ! Lines have same slope (i.e. Horizontal)
        else
          if (x.ge.gons(i,1) .and. x.le.gons(i+1,1) ) then
            return             ! On edge
          elseif (x.le.gons(i,1) .and. x.ge.gons(i+1,1) ) then
            return             ! On edge
          endif
        endif
      else
        !
        ! Polygon side is vertical
        if (gons(i,1).lt.x) then
          index = index+1      ! Crosses
        elseif (gons(i,1).eq.x) then
          return               ! On edge
        endif
      endif
    endif
  enddo
  !
  gr8_in = mod(index,2).eq.1
end function gr8_in
