!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
subroutine wifisyn_uvsort_command(line,error)
  use wifisyn_interfaces, except_this=>wifisyn_uvsort_command
  use wifisyn_sort_types
  !----------------------------------------------------------------------
  ! @ private
  ! Support routine for command
  !	UVSORT [U|V|X|Y]
  !----------------------------------------------------------------------
  character(len=*), intent(in)    :: line
  logical,          intent(inout) :: error
  !
  integer :: args(m_tot_key)
  !
  call wifisyn_sort_getargs(line,args,error)
  if (error) return
  !
!!$  call wifisyn_sort_uvrt(args,error)
!!$  if (error) return
  !
end subroutine wifisyn_uvsort_command
!
subroutine wifisyn_sort_getargs(line,args,error)
  use gbl_message
  use gio_params
  use gkernel_interfaces
  use wifisyn_interfaces, except_this=>wifisyn_sort_getargs
  use wifisyn_gridding_types
  use wifisyn_sort_types
  !---------------------------------------------------------------------
  ! @ private
  !---------------------------------------------------------------------
  character(len=*), intent(in)    :: line
  integer,          intent(out)   :: args(m_tot_key)
  logical,          intent(inout) :: error
  !
  integer :: narg,iarg,larg,num
  character(len=6) :: key,arg
  character(len=*), parameter :: rname = 'SORT'
  !
  ! Sanity check
  narg = sic_narg(0)
  if (narg.gt.m_tot_key) then
     call wifisyn_message(seve%e,rname,'Too many arguments for command SORT')
     error = .true.
     return
  endif
  !
  ! Nullify
  args = code_null
  !
  ! Get them
  if (narg.eq.0) then
     ! Default
     args(1) = code_axis_u
     args(2) = code_axis_v
     args(3) = code_axis_x
     args(4) = code_axis_y
  else
     ! User defined
     do iarg=1,narg
        call sic_ke(line,0,iarg,arg,larg,.true.,error)
        if (error) return
        call sic_ambigs(rname,arg,key,num,known_keys,m_tot_key,error)
        if (error) return
        args(iarg) = num
     enddo
  endif
  !
end subroutine wifisyn_sort_getargs
!
!!$subroutine wifisyn_sort_uvrt(args,error)
!!$  use gbl_message
!!$  use wifisyn_uv_buffer
!!$  use wifisyn_sort_types
!!$  !---------------------------------------------------------------------
!!$  ! @ private
!!$  !---------------------------------------------------------------------
!!$  integer,    intent(in)  :: args(m_tot_key) !
!!$  logical,    intent(out) :: error ! Error status
!!$  !
!!$  integer :: idata
!!$  character(len=80) :: mess
!!$  character(len=*), parameter :: rname = 'SORT/RT'
!!$  !
!!$  ! Sanity check
!!$  if (no_data(rname,uvr%head,error)) return
!!$  !
!!$  ! Swap UVR into UVT buffer
!!$  call wifisyn_uvrt_swap(error)
!!$  if (error) return
!!$  !
!!$  call wifisyn_allocate_inte_1d('idx',uvr%head%type%ndata,sort%idx,error)
!!$  if (error) return
!!$  call wifisyn_allocate_inte_1d('iu',uvr%head%type%ndata,sort%iu,error)
!!$  if (error) return
!!$  call wifisyn_allocate_inte_1d('iv',uvr%head%type%ndata,sort%iv,error)
!!$  if (error) return
!!$  !
!!$  !
!!$  ! Loop on observed data point
!!$  do idata=1,sort%iu%n ! should check iv%n and idx%n
!!$     sort%iu%val(idata) = nint(uref+(htab%u(idata)-uval)/uinc)
!!$     sort%iv%val(idata) = nint(vref+(htab%v(idata)-vval)/vinc)
!!$  enddo
!!$  !
!!$  call wifisyn_sort_index(args,sort,error)
!!$  if (error) return
!!$  !
!!$  ! Sort UVT buffer into UVR buffer using the previously computed INDEX
!!$  call wifisyn_sort_head(sort,uvt,uvr,error)
!!$  if (error) return
!!$  call wifisyn_sort_data(sort,uvt,uvr,error)
!!$  if (error) return
!!$  !
!!$  ! Clean
!!$  call wifisyn_free_inte_1d(sort%idx,error)
!!$  call wifisyn_free_inte_1d(sort%iu,error)
!!$  call wifisyn_free_inte_1d(sort%iv,error)
!!$  !
!!$end subroutine wifisyn_sort_uvrt
!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
subroutine wifisyn_set_index(ndata,sort,error)
  use gbl_message
  use wifisyn_interfaces, except_this=>wifisyn_set_index
  use wifisyn_gridding_types
  !---------------------------------------------------------------------
  ! @ private
  !---------------------------------------------------------------------
  integer,      intent(in)    :: ndata
  type(sort_t), intent(out)   :: sort
  logical,      intent(inout) :: error ! Error status
  !
  integer :: idata
  character(len=*), parameter :: rname='SET/INDEX'
  !
  call wifisyn_message(seve%t,rname,'Welcome')
  !
  call wifisyn_allocate_inte_1d('idx',ndata,sort%idx,error)
  if (error) return
  !
  do idata=1,ndata
     sort%idx%val(idata) = idata
  enddo
  !
end subroutine wifisyn_set_index
!
subroutine wifisyn_sort_index(args,sort,error)
  use gbl_message
  use gio_params
  use wifisyn_interfaces, except_this=>wifisyn_sort_index
  use wifisyn_gridding_types
  use wifisyn_sort_buffer
  !---------------------------------------------------------------------
  ! @ private
  !---------------------------------------------------------------------
  integer,              intent(in)    :: args(m_tot_key)
  type(sort_t), target, intent(inout) :: sort
  logical,              intent(inout) :: error
  !
  integer :: idata,iselect,iarg
  character(len=*), parameter :: rname='SORT/INDEX'
  !
  call wifisyn_message(seve%t,rname,'Welcome')
  !
  ! Sanity check (not generic yet *** JP)
  if (inconsistent_size(rname,'iu',sort%iu%n,'idx',sort%idx%n,error)) return
  if (inconsistent_size(rname,'iv',sort%iv%n,'idx',sort%idx%n,error)) return
  !
  keys(code_axis_u)%ipointer%type => sort%iu%val
  keys(code_axis_v)%ipointer%type => sort%iv%val
  keys(code_axis_x)%ipointer%type => sort%ix%val
  keys(code_axis_y)%ipointer%type => sort%iy%val
  !
  n_inte_key = 0
  do iarg=1,m_tot_key
     iselect = args(iarg)
     if (iselect.eq.code_null) then
        exit
     endif
     n_inte_key = n_inte_key+1
     inte_keys(n_inte_key)%type => keys(iselect)%ipointer%type
  enddo
  !
  do idata=1,sort%idx%n
     sort%idx%val(idata) = idata
  enddo
  !
  call gi4_quicksort_index_with_user_gtge(sort%idx,wifisyn_gt,wifisyn_ge,error)
  if (error) return
  !
end subroutine wifisyn_sort_index
!
function wifisyn_eq(m,l)
  use wifisyn_sort_buffer
  !---------------------------------------------------------------------
  ! @ private
  ! This routine is optimized because it is called many times
  ! Do not modify
  !---------------------------------------------------------------------
  logical             :: wifisyn_eq
  integer, intent(in) :: m ! Data #m
  integer, intent(in) :: l ! Data #l
  !
  integer :: ikey
  !
  wifisyn_eq = .true.
  do ikey=1,n_inte_key
     if (inte_keys(ikey)%type(m).ne.inte_keys(ikey)%type(l)) then
        wifisyn_eq = .false.
        return
     endif
  enddo
  !
end function wifisyn_eq
!
function wifisyn_ge(m,l)
  use wifisyn_sort_buffer
  !---------------------------------------------------------------------
  ! @ private
  ! This routine is optimized because it is called many times
  ! Do not modify
  !---------------------------------------------------------------------
  logical             :: wifisyn_ge
  integer, intent(in) :: m ! Data #m
  integer, intent(in) :: l ! Data #l
  !
  integer :: ikey
  !
  wifisyn_ge = .true.
  do ikey=1,n_inte_key
     if (inte_keys(ikey)%type(m).gt.inte_keys(ikey)%type(l)) then
        return
     else if (inte_keys(ikey)%type(m).lt.inte_keys(ikey)%type(l)) then
        wifisyn_ge = .false.
        return
     endif
  enddo
  !
end function wifisyn_ge
!
function wifisyn_gt(m,l)
  use wifisyn_sort_buffer
  !---------------------------------------------------------------------
  ! @ private
  ! This routine is optimized because it is called many times
  ! Do not modify
  !---------------------------------------------------------------------
  logical             :: wifisyn_gt
  integer, intent(in) :: m ! Data #m
  integer, intent(in) :: l ! Data #l
  !
  integer :: ikey
  !
  wifisyn_gt = .false.
  do ikey=1,n_inte_key
     if (inte_keys(ikey)%type(m).gt.inte_keys(ikey)%type(l)) then
        wifisyn_gt = .true.
        return
     else if (inte_keys(ikey)%type(m).lt.inte_keys(ikey)%type(l)) then
        return
     endif
  enddo
  !
end function wifisyn_gt
!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
subroutine wifisyn_sort_head(sort,table,error)
  use gbl_message
  use wifisyn_interfaces, except_this=>wifisyn_sort_head
  use wifisyn_gridding_types
  use wifisyn_uv_types
  !---------------------------------------------------------------------
  ! @ private
  !---------------------------------------------------------------------
  type(sort_t), intent(in)    :: sort
  type(uv_t),   intent(inout) :: table
  logical,      intent(inout) :: error
  !
  type(uv_t) :: temp
  integer :: idata,ndata
  character(len=*), parameter :: rname='SORT/HEAD'
  !
  call wifisyn_message(seve%t,rname,'Welcome')
  !
  ! Sanity check
  ndata = table%head%type%ndata
  if (inconsistent_size(rname,'table',ndata,'index',sort%idx%n,error)) return
  !
  call wifisyn_reallocate_uv_header(temp,ndata,error)
  if (error) return
  !
  do idata=1,ndata
     temp%buff%uvp1(idata,:) = table%buff%uvp1(idata,:)
     temp%buff%uvp2(idata,:) = table%buff%uvp2(idata,:)
  enddo
  do idata=1,ndata
     table%buff%uvp1(idata,:) = temp%buff%uvp1(sort%idx%val(idata),:)
     table%buff%uvp2(idata,:) = temp%buff%uvp2(sort%idx%val(idata),:)
  enddo
  !
  call wifisyn_free_uv(temp,error)
  if (error) return
  !
end subroutine wifisyn_sort_head
!
subroutine wifisyn_sort_data(sort,tabin,tabout,error)
  use gbl_message
  use wifisyn_interfaces, except_this=>wifisyn_sort_data
  use wifisyn_gridding_types
  use wifisyn_uv_types
  !---------------------------------------------------------------------
  ! @ private
  !---------------------------------------------------------------------
  type(sort_t), intent(in)    :: sort
  type(uv_t),   intent(in)    :: tabin
  type(uv_t),   intent(inout) :: tabout
  logical,      intent(inout) :: error
  !
  integer :: ndata,idata
  character(len=*), parameter :: rname='SORT/DATA'
  !
  call wifisyn_message(seve%t,rname,'Welcome')
  !
  ! Sanity check
  ndata = tabin%head%type%ndata
  if (inconsistent_size(rname,'tabin',ndata,'index',sort%idx%n,error)) return
  if (inconsistent_size(rname,'tabout',ndata,'index',sort%idx%n,error)) return
  !
  ! Table data only
  do idata=1,ndata
     tabout%buff%uvp3(idata,:,:) = tabin%buff%uvp3(sort%idx%val(idata),:,:)
  enddo
  !
end subroutine wifisyn_sort_data
!
!!$subroutine wifisyn_sort_check(nent,index,leq)
!!$  use gbl_message
!!$  use wifisyn_uv_types
!!$  !---------------------------------------------------------------------
!!$  ! @ private
!!$  ! Check if visibilities are negative and increasing
!!$  !---------------------------------------------------------------------
!!$  integer, intent(in)    :: nent  !
!!$  integer, intent(in)    :: index(nent)
!!$  !
!!$  integer :: ient
!!$  !
!!$  do ient = 2,nent
!!$     if (leq(ient-1,ient)) then
!!$        sorted = .false.
!!$        return
!!$     endif
!!$  enddo
!!$  sorted = .true.
!!$  !
!!$end subroutine wifisyn_sort_check
!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
