program uv_getinterval
  use gildas_def
  use image_def
  use gkernel_interfaces
  !---------------------------------------------------------------------
  !
  !---------------------------------------------------------------------
  ! Local
  character(len=*), parameter :: rname='UV_GETINTERVAL'
  type(gildas) :: tab
  character(len=filename_length) :: filename
  logical :: error
  !
  error = .false.
  !
  call gildas_open
  call gildas_char('UVTABLE$',filename)
  call gildas_close
  !
  if (len_trim(filename).le.0) goto 99
  !
  ! Read all input file
  call gildas_null(tab,type='UVT')
  call gdf_read_gildas(tab,filename,'.uvt',error,data=.true.)
  if (gildas_error(tab,rname,error)) then
    write(6,*) 'F-UV_GETINTERVAL,  Cannot read input UV table'
    goto 99
  endif
  !
  call compute_eclass(tab,error)
  if (error)  goto 99
  !
  call gdf_close_image(tab,error)
  if (gildas_error(tab,rname,error))  goto 99
  !
  call gagout('S-UV_GETINTERVAL,  Successful completion')
  call sysexi(1)
  !
99 call sysexi(fatale)
  !
end program uv_getinterval
!
subroutine compute_eclass(tab,error)
  use gkernel_interfaces
  use gkernel_types
  !---------------------------------------------------------------------
  !
  !---------------------------------------------------------------------
  type(gildas), intent(in)    :: tab
  logical,      intent(inout) :: error
  ! Global
  logical, external :: eclass_time_eq
  ! Local
  character(len=*), parameter :: rname='UV_GETINTERVAL'
  real(kind=8), allocatable :: datetime(:)
  real(kind=8) :: prevdatetime
  integer(kind=4), allocatable :: idx(:),work(:)
  integer(kind=4) :: ier,nvisi,ivisi,iequ,nuniq
  type(eclass_dble_t) :: eclass
  real(kind=8), parameter :: tol=1.d0  ! [sec]
  !
  ! Read/compute date-time for all visibilities
  nvisi = tab%gil%nvisi
  allocate(datetime(nvisi),idx(tab%gil%nvisi),stat=ier)
  if (failed_allocate(rname,'date-time arrays',ier,error))  return
  ! ZZZ This is valid only for UV tables (not TUV)
  datetime(:) = tab%r2d(code_uvt_date,:)*86400.d0 + tab%r2d(code_uvt_time,:)
  !
  ! Sort date-times
  call gr8_trie(datetime,idx,nvisi,error)
  !
  ! Compress datetime list by removing duplicates (most likely when
  ! considering several baselines of the same datetime dump)
  nuniq = 1
  prevdatetime = datetime(1)
  do ivisi=2,nvisi
    if (abs(prevdatetime-datetime(ivisi)).gt.tol) then
      nuniq = nuniq+1
      prevdatetime = datetime(ivisi)
      datetime(nuniq) = prevdatetime
    endif
  enddo
  !
  ! Compute equivalence classes with some tolerance
  call reallocate_eclass_dble(eclass,nuniq-1,error)
  if (error)  return
  do ivisi=1,nuniq-1
    eclass%val(ivisi) = datetime(ivisi+1) - datetime(ivisi)
    eclass%cnt(ivisi) = 1
  enddo
  call eclass_dble(eclass_time_eq,eclass)
  !
  ! Sort by increasing values (NB: this breaks the 'bak' pointer, use it
  ! as the index array)
  call gr8_trie(eclass%val,eclass%bak,eclass%nequ,error)
  if (error)  return
  allocate(work(eclass%nequ))
  call gi4_sort(eclass%cnt,work,eclass%bak,eclass%nequ)
  !
  write(*,'(4(A,I0))') "Found ",eclass%nequ," different time intervals among ",  &
    nuniq," date-times for ",nvisi," visibilities:"
  do iequ=1,eclass%nequ
    write (*,'(I3,A,F20.10,A,I5,A)')  &
      iequ," : ",eclass%val(iequ),' seconds (',eclass%cnt(iequ),' occurences)'
  enddo
  !
  call free_eclass_dble(eclass,error)
  if (error)  return
  !
end subroutine compute_eclass
!
function eclass_time_eq(x1,x2)
  !---------------------------------------------------------------------
  ! Equality routine between two time intervals (real*8) with a
  ! tolerance of 1 second
  !---------------------------------------------------------------------
  logical :: eclass_time_eq
  real(kind=8), intent(in) :: x1,x2  ! [sec]
  real(kind=8), parameter :: tol=1.d0  ! [sec]
  !
  eclass_time_eq = abs(x1-x2).le.tol
  !
end function eclass_time_eq
