!
subroutine uvsort_uv (np,nv,ntrail,vin,vout,xy,cs,uvmax,uvmin,error)
  use gildas_def
  use gkernel_interfaces
  use mapping_interfaces, except_this=> uvsort_uv
  !---------------------------------------------------------------------
  ! @ public
  !
  ! MAPPING
  !     Rotate, Shift and Sort a UV table for map making
  !     Differential precession should have been applied before.
  !---------------------------------------------------------------------
  integer, intent(in) :: np        ! Size of a visibility
  integer, intent(in) :: nv        ! Number of visibilities
  integer, intent(in) :: ntrail    ! Number of trailing daps
  real, intent(in) :: vin(np,nv)   ! Input visibilities
  real, intent(out) :: vout(np,nv) ! Output visibilities
  real, intent(in) :: xy(2)        ! Phase shift
  real, intent(in) :: cs(2)        ! Frame Rotation
  real, intent(out) :: uvmax       ! Max UV value
  real, intent(out) :: uvmin       ! Min UV value
  logical, intent(out) :: error    !
  ! Local
  logical, allocatable :: ips(:)       ! Sign of visibility
  real, allocatable :: ipu(:), ipv(:)  ! U,V coordinates
  integer, allocatable :: ipi(:)       ! Index
  logical :: sorted
  integer :: ier
  !
  ! Load U,V coordinates, applying possible rotation (CS), and
  ! making all V negative
  allocate (ips(nv),ipu(nv),ipv(nv),ipi(nv),stat=ier)
  error = ier.ne.0
  if (error) return
  call loaduv (vin,np,nv,cs,ipu,ipv,ips,uvmax,uvmin)
  !
  ! Sort if needed
  call chksuv (nv,ipv,ipi,sorted)
  if (.not.sorted) then
    call gr4_trie (ipv,ipi,nv,error)
    if (error) return
  endif
  !
  ! Apply phase shift and copy to output visibilities
  call sortuv (vin,vout,np,nv,ntrail,xy,ipu,ipv,ips,ipi)
  !
  deallocate (ips,ipu,ipv,ipi,stat=ier)
  call gagout('I-UVSORT,  Successful completion')
end subroutine uvsort_uv
!
subroutine loaduv (visi,np,nv,cs,u,v,s,uvmax,uvmin)
  !---------------------------------------------------------------------
  ! @ public
  !
  ! MAPPING    UVSORT routines
  !     Load new U,V coordinates and sign indicator into work arrays
  !     for sorting.
  !---------------------------------------------------------------------
  integer, intent(in) :: np       ! Size of a visibility
  integer, intent(in) :: nv       ! Number of visibilities
  real, intent(in) :: visi(np,nv) ! Input visibilities
  real, intent(in) :: cs(2)       ! Rotation parameter
  real, intent(out) :: u(nv)      ! Output U and V coordinates
  real, intent(out) :: v(nv)      ! Output U and V coordinates
  logical, intent(out) :: s(nv)   ! V Sign indicator
  real, intent(inout) :: uvmax    ! Maximum length
  real, intent(inout) :: uvmin    ! Minimum baseline
  ! Local
  integer :: iv
  real :: uv
  !
  uv = 0
  do iv=1,nv
    uv = visi(1,iv)**2 + visi(2,iv)**2
    if (uv.ne.0) exit
  enddo
  uvmax = uv
  uvmin = uv
  !
  if (cs(2).eq.0.0) then
    do iv=1,nv
      v(iv) = visi(2,iv)
      if (v(iv).gt.0) then
        u(iv) = -visi(1,iv)
        v(iv) = -v(iv)
        s(iv) = .false.
      else
        u(iv) = visi(1,iv)
        s(iv) = .true.
      endif
      uv = u(iv)*u(iv)+v(iv)*v(iv)
      if (uv.gt.uvmax) then
        uvmax = uv
      else if (uv.lt.uvmin .and. uv.ne.0) then
        uvmin = uv
      endif
    enddo
  else
    do iv=1,nv
      u(iv) = cs(1)*visi(1,iv) - cs(2)*visi(2,iv)
      v(iv) = cs(2)*visi(1,iv) + cs(1)*visi(2,iv)
      if (v(iv).gt.0) then
        u(iv) = -u(iv)
        v(iv) = -v(iv)
        s(iv) = .false.
      else
        s(iv) = .true.
      endif
      uv = u(iv)*u(iv)+v(iv)*v(iv)
      if (uv.gt.uvmax) then
        uvmax = uv
      else if (uv.lt.uvmin .and. uv.ne.0) then
        uvmin = uv
      endif
    enddo
  endif
  uvmax = sqrt(uvmax)
  uvmin = sqrt(uvmin)
end subroutine loaduv
!
subroutine chksuv (nv,v,it,sorted)
  !---------------------------------------------------------------------
  ! @ public
  !
  ! MAPPING    UVSORT routines
  !   Check if visibilities are sorted
  !---------------------------------------------------------------------
  integer, intent(in) :: nv      ! Number of visibilities
  real, intent(in) :: v(nv)      ! Visibilities
  integer, intent(out) :: it(nv) ! Sorting pointer
  logical, intent(out) :: sorted ! short cut
  ! Local
  integer :: iv
  real :: vmax
  !
  do iv=1,nv
    it(iv) = iv
  enddo
  !
  vmax = v(1)
  do iv = 1,nv
    if (v(iv).gt.0 .or. v(iv).lt.vmax) then
      sorted = .false.
      return
    endif
    vmax = v(iv)
  enddo
  sorted = .true.
end subroutine chksuv
!
subroutine sortuv (vin,vout,np,nv,ntrail,xy,u,v,s,it)
  !---------------------------------------------------------------------
  ! @ public
  !
  ! MAPPING    UVSORT routines
  !     Sort an input UV table into an output one.
  !     The output UV table is a rotated, phase shifted copy of
  !     the input one, with all V negative and increasing
  !---------------------------------------------------------------------
  integer, intent(in) :: np         ! Size of a visibility
  integer, intent(in) :: nv         ! Number of visibilities
  integer, intent(in) :: ntrail     ! Number of trailing daps
  real, intent(in) :: vin(np,nv)    ! Input visibilities
  real, intent(out) :: vout(np,nv)  ! Output visibilities
  real, intent(in) :: xy(2)         ! Phase shifting factors
  real, intent(in) :: u(nv)         ! New U coordinates
  real, intent(in) :: v(nv)         ! New V coordinates
  logical, intent(in) :: s(nv)      ! Sign of new visibility
  integer, intent(in) :: it(nv)     ! Pointer to old visibility
  ! Local
  integer :: ip,iv,kv,no
  real :: phi, cphi, sphi
  !
  ! There may be trailing columns in UV table
  no = np-ntrail
  !
  ! Simple case: no phase shift
  !$OMP PARALLEL &
  !$OMP & SHARED(u,v,vin,vout,no,np,xy) &
  !$OMP & PRIVATE(kv,iv,ip, phi,cphi,sphi)
  if (xy(1).eq.0 .and. xy(2).eq.0) then
    !$OMP DO
    do iv=1,nv
      kv = it(iv)
      vout(1,iv) = u(kv)
      vout(2,iv) = v(iv)       ! This one is sorted already
      vout(3,iv) = vin(3,kv)
      vout(4,iv) = vin(4,kv)
      vout(5,iv) = vin(5,kv)
      if (s(kv)) then
        vout(6,iv) = vin(6,kv)
        vout(7,iv) = vin(7,kv)
        do ip=8,np
          vout(ip,iv) = vin(ip,kv)
        enddo
      else
        vout(6,iv) = vin(7,kv)
        vout(7,iv) = vin(6,kv)
        do ip=8,no,3
          vout(ip,iv)   =  vin(ip,kv)
          vout(ip+1,iv) = -vin(ip+1,kv)
          vout(ip+2,iv) =  vin(ip+2,kv)
        enddo
      endif
      do ip=no+1,np
        vout(ip,iv)   =  vin(ip,kv)
      enddo
    enddo
    !$OMP END DO
  else
    !
    ! Complex case: phase center has been shifted
    !$OMP DO
    do iv=1,nv
      kv = it(iv)
      vout(1,iv) = u(kv)
      vout(2,iv) = v(iv)       ! This one is sorted already
      vout(3,iv) = vin(3,kv)
      vout(4,iv) = vin(4,kv)
      vout(5,iv) = vin(5,kv)
      phi = xy(1)*u(kv)+xy(2)*v(iv)
      cphi = cos(phi)
      sphi = sin(phi)
      if (s(kv)) then
        vout(6,iv) = vin(6,kv)
        vout(7,iv) = vin(7,kv)
        do ip=8,no,3
          vout(ip,iv) = vin(ip,kv)*cphi - vin(ip+1,kv)*sphi
          vout(ip+1,iv) = vin(ip,kv)*sphi + vin(ip+1,kv)*cphi
          vout(ip+2,iv) = vin(ip+2,kv)
        enddo
      else
        vout(6,iv) = vin(7,kv)
        vout(7,iv) = vin(6,kv)
        do ip=8,no,3
          vout(ip,iv) = vin(ip,kv)*cphi + vin(ip+1,kv)*sphi
          vout(ip+1,iv) = vin(ip,kv)*sphi - vin(ip+1,kv)*cphi
          vout(ip+2,iv) = vin(ip+2,kv)
        enddo
      endif
      do ip=no+1,np
        vout(ip,iv)   =  vin(ip,kv)
      enddo
    enddo
    !$OMP END DO
  endif
  !$OMP END PARALLEL
end subroutine sortuv
