subroutine dofft_test (np,nv,visi,jx,jy,jo   &
     &    ,nc,nx,ny,map,mapx,mapy,sup,cell,taper,we,vv   &
     &    ,ubias,vbias,ubuff,vbuff,ctype)
  !----------------------------------------------------------------------
  ! @  private
  !
  ! GILDAS  UV_MAP
  !   Compute FFT of image by gridding UV data
  !   Test version to compare speed of various methods
  !----------------------------------------------------------------------
  integer, intent(in) :: nv                   ! number of values
  integer, intent(in) :: np                   ! Number of "visibilities", normally 7+3*nc
  real, intent(in) :: visi(np,nv)             ! values
  integer, intent(in) :: nc                   ! number of channels
  integer, intent(in) :: jx                   ! X coord location in VISI
  integer, intent(in) :: jy                   ! Y coord location in VISI
  integer, intent(in) :: jo                   ! first channel to map
  integer, intent(in) :: nx                   ! X map size
  integer, intent(in) :: ny                   ! Y map size
  real, intent(out) :: map(2*(nc+1),nx,ny)    ! gridded visibilities
  real, intent(in) :: mapx(nx)                ! X Coordinates of grid
  real, intent(in) :: mapy(ny)                ! Y Coordinates of grid
  real, intent(in) :: sup(2)                  ! Support of convolving function in Meters
  real, intent(in) :: cell(2)                 ! cell size in Meters
  real, intent(in) :: taper(4)                ! 1/e taper in Meters + Angle in Radians
  real, intent(in) :: we(nv)                  ! Weight array
  real, intent(in) :: vv(nv)                  ! V Values
  real, intent(in) :: ubias                   ! U gridding offset
  real, intent(in) :: vbias                   ! V gridding offset
  real, intent(in) :: ubuff(4096)             ! U gridding buffer
  real, intent(in) :: vbuff(4096)             ! V gridding buffer
  integer, intent(in) :: ctype                ! type of gridding
  !
  !
  ! Initialize
  map = 0.0
  !
  if (ctype.eq.1) then
    print *,'DOFFT_FAST '
    call dofft_fast (np,nv,visi,jx,jy,jo,   &
     &      nc,nx,ny,map,mapx,mapy,sup,cell,taper,we,vv)
  elseif  (ctype.eq.5) then
    print *,'DOFFT_QUICK '
    call dofft_quick (np,nv,visi,jx,jy,jo,   &
     &      nc,nx,ny,map,mapx,mapy,sup,cell,taper,we,vv,   &
     &      ubias,vbias,ubuff,vbuff)
  else
    print *,'DOFFT_SLOW '
    call dofft_slow (np,nv,visi,jx,jy,jo,   &
     &      nc,nx,ny,map,mapx,mapy,sup,cell,taper,we,vv,   &
     &      ubias,vbias,ubuff,vbuff)
  endif
end subroutine dofft_test
!
subroutine dofft_quick1 (np,nv,visi,jx,jy,jo   &
     &    ,nc,nx,ny,map,mapx,mapy,sup,cell,taper,we,vv,   &
     &    ubias,vbias,ubuff,vbuff)
  !----------------------------------------------------------------------
  ! @ private
  !
  ! GILDAS  MAP_FAST
  !   Compute FFT of image by gridding UV data
  !   For any gridding support
  !   Taper before gridding
  !   Does not use symmetry
  !----------------------------------------------------------------------
  integer, intent(in) :: nv                   ! number of values
  integer, intent(in) :: np                   ! Number of "visibilities", normally 7+3*nc
  real, intent(in) :: visi(np,nv)             ! values
  integer, intent(in) :: nc                   ! number of channels
  integer, intent(in) :: jx                   ! X coord location in VISI
  integer, intent(in) :: jy                   ! Y coord location in VISI
  integer, intent(in) :: jo                   ! first channel to map
  integer, intent(in) :: nx                   ! X map size
  integer, intent(in) :: ny                   ! Y map size
  real, intent(out) :: map(2*(nc+1),nx,ny)    ! gridded visibilities
  real, intent(in) :: mapx(nx)                ! X Coordinates of grid
  real, intent(in) :: mapy(ny)                ! Y Coordinates of grid
  real, intent(in) :: sup(2)                  ! Support of convolving function in Meters
  real, intent(in) :: cell(2)                 ! cell size in Meters
  real, intent(in) :: taper(4)                ! 1/e taper in Meters + Angle in Radians
  real, intent(in) :: we(nv)                  ! Weight array
  real, intent(in) :: vv(nv)                  ! V Values
  real, intent(in) :: ubias                   ! U gridding offset
  real, intent(in) :: vbias                   ! V gridding offset
  real, intent(in) :: ubuff(4096)             ! U gridding buffer
  real, intent(in) :: vbuff(4096)             ! V gridding buffer
  ! Global
  real(8), parameter :: pi=3.141592653589793d0
  ! Local
  integer ix,iy,ic,i,iin,iou,io,k
  integer ixm,ixp,iym,iyp,iu,iv
  real result,resima,staper,etaper,res
  real u,v,du,dv,ufac,vfac
  real cx,cy,sx,sy
  real(8) xinc,xref,yinc,yref
  logical do_taper
  !
  ! Compute IO from first channel number
  io = 7+3*jo-2
  ufac = 100.d0/cell(1)
  vfac = 100.d0/cell(2)
  !
  if (taper(1).ne.0. .and. taper(2).ne.0.) then
    do_taper = .true.
    staper = taper(3)*pi/180.0
    if (taper(1).ne.0) then
      cx = cos(staper)/taper(1)
      sy = sin(staper)/taper(1)
    else
      cx = 0.0
      sy = 0.0
    endif
    if (taper(2).ne.0) then
      cy = cos(staper)/taper(2)
      sx = sin(staper)/taper(2)
    else
      cy = 0.0
      sx = 0.0
    endif
    if (taper(4).ne.0.) then
      etaper = taper(4)/2.0
    else
      etaper = 1
    endif
  else
    do_taper = .false.
  endif
  xinc = mapx(2)-mapx(1)
  xref = nx/2+1
  yinc = mapy(2)-mapy(1)
  yref = ny/2+1
  staper = 1.0
  !
  ! Start with loop on observed visibilities
  do i=1,nv
    u = visi(jx,i)
    v = visi(jy,i)
    !
    if (do_taper) then
      staper = (u*cx + v*sy)**2 + (-u*sx + v*cy)**2
      if (etaper.ne.1) staper = staper**etaper
      if (staper.gt.64.0) then
        staper = 0.0
      else
        staper = exp(-staper)
      endif
    endif
    !
    ! Weight and taper
    result = staper*we(i)
    ! Channels
    ! Define map cell
    do k=1,2
      if (k.eq.1) then
        resima = result
      else
        u = -u
        v = -v
        resima = -result
      endif
      !
      ixp = int((u-sup(1))/xinc+xref+1.0)
      ixm = int((u+sup(1))/xinc+xref)
      iym = int((v-sup(2))/yinc+yref)
      iyp = int((v+sup(2))/yinc+yref+1.0)
      if (ixm.lt.1.or.ixp.gt.nx.or.iym.lt.1.or.iyp.gt.ny) then
        print *,'Visi ',i,' pixels ',ixm,ixp,iym,iyp
      else
        do iy=iym,iyp
          dv = v-mapy(iy)
          if (abs(dv).le.sup(2)) then
            iv = nint(dv*vfac+vbias)
            do ix=ixm,ixp
              du = u-mapx(ix)
              if (abs(du).le.sup(1)) then
                iu = nint(du*ufac+ubias)
                res = ubuff(iu)*vbuff(iv)
                iou = 1
                iin = io
                do ic=1,nc
                  map (iou,ix,iy) = map (iou,ix,iy) +   &
     &                    visi(iin,i)*result*res
                  iou = iou+1
                  iin = iin+1
                  map (iou,ix,iy) = map (iou,ix,iy) +   &
     &                    visi(iin,i)*resima*res
                  iou = iou+1
                  iin = iin+2
                enddo
                ! Beam
                map (iou,ix,iy) = map(iou,ix,iy) +   &
     &                  res*result
              endif
            enddo
          endif
        enddo
      endif
    enddo
  enddo
  !
  ! Missing row is left empty (assume proper coverage of the UV plane)
  do iy = 1,ny
    if (map(2*nc-1,1,iy).ne.0) then
      print *,'Invalid beam ',iy
    endif
  enddo
end subroutine dofft_quick1
!
subroutine dofft_fast1 (np,nv,visi,jx,jy,jo   &
     &    ,nc,nx,ny,map,mapx,mapy,sup,cell,taper,we,vv)
  !----------------------------------------------------------------------
  ! @ private
  !
  ! GILDAS  MAP_FAST
  !   Compute FFT of image by gridding UV data
  !   Only for "visibility in cell"
  !   Taper before gridding
  !   Do not use symmetry
  !----------------------------------------------------------------------
  integer, intent(in) :: nv                   ! number of values
  integer, intent(in) :: np                   ! Number of "visibilities", normally 7+3*nc
  real, intent(in) :: visi(np,nv)             ! values
  integer, intent(in) :: nc                   ! number of channels
  integer, intent(in) :: jx                   ! X coord location in VISI
  integer, intent(in) :: jy                   ! Y coord location in VISI
  integer, intent(in) :: jo                   ! first channel to map
  integer, intent(in) :: nx                   ! X map size
  integer, intent(in) :: ny                   ! Y map size
  real, intent(out) :: map(2*(nc+1),nx,ny)    ! gridded visibilities
  real, intent(in) :: mapx(nx)                ! X Coordinates of grid
  real, intent(in) :: mapy(ny)                ! Y Coordinates of grid
  real, intent(in) :: sup(2)                  ! Support of convolving function in Meters
  real, intent(in) :: cell(2)                 ! cell size in Meters
  real, intent(in) :: taper(4)                ! 1/e taper in Meters + Angle in Radians
  real, intent(in) :: we(nv)                  ! Weight array
  real, intent(in) :: vv(nv)                  ! V Values
  !
  real(8), parameter :: pi=3.141592653589793d0
  ! Local
  integer ix,iy,ic,i,iin,iou,io,k
  real result,resima,staper,etaper
  real u,v
  real cx,cy,sx,sy
  real(8) xinc,xref,yinc,yref
  logical do_taper
  !
  ! Compute IO from first channel number
  io = 7+3*jo-2
  !
  if (taper(1).ne.0. .and. taper(2).ne.0.) then
    do_taper = .true.
    staper = taper(3)*pi/180.0
    if (taper(1).ne.0) then
      cx = cos(staper)/taper(1)
      sy = sin(staper)/taper(1)
    else
      cx = 0.0
      sy = 0.0
    endif
    if (taper(2).ne.0) then
      cy = cos(staper)/taper(2)
      sx = sin(staper)/taper(2)
    else
      cy = 0.0
      sx = 0.0
    endif
    if (taper(4).ne.0.) then
      etaper = taper(4)/2.0
    else
      etaper = 1
    endif
  else
    do_taper = .false.
  endif
  xinc = mapx(2)-mapx(1)
  xref = nx/2+1
  yinc = mapy(2)-mapy(1)
  yref = ny/2+1
  staper = 1.0
  !
  ! Start with loop on observed visibilities
  do i=1,nv
    u = visi(jx,i)
    v = visi(jy,i)
    !
    if (do_taper) then
      staper = (u*cx + v*sy)**2 + (-u*sx + v*cy)**2
      if (etaper.ne.1) staper = staper**etaper
      if (staper.gt.64.0) then
        staper = 0.0
      else
        staper = exp(-staper)
      endif
    endif
    !
    ! Weight and taper
    result = staper*we(i)
    ! Channels
    ! Define map cell
    do k=1,2
      if (k.eq.1) then
        ix = nint(u/xinc+xref)
        iy = nint(v/yinc+yref)
        resima = result
      else
        ix = nint(-u/xinc+xref)
        iy = nint(-v/yinc+yref)
        resima = -result
      endif
      if (ix.lt.1.or.ix.gt.nx.or.iy.lt.1.or.iy.gt.ny) then
        print *,'Visi ',i,' pixels ',ix,iy
      else
        iou = 1
        iin = io
        do ic=1,nc
          map (iou,ix,iy) = map (iou,ix,iy) +   &
     &            visi(iin,i)*result
          iou = iou+1
          iin = iin+1
          map (iou,ix,iy) = map (iou,ix,iy) +   &
     &            visi(iin,i)*resima
          iou = iou+1
          iin = iin+2
        enddo
        ! Beam
        map (iou,ix,iy) = map(iou,ix,iy) + result
      endif
    enddo
  enddo                        ! Visibility loop
end subroutine dofft_fast1
