module wei_fft_fftw_mod
  use wei_wavespace_type_mod
  use wei_step_mod
#ifdef FFTW
  implicit none
  integer, parameter   ::  FFTW_R2HC=0,FTW_HC2R=1,FFTW_DHT=2,FFTW_REDFT00=3,FFTW_REDFT01=4
  integer, parameter   ::  FFTW_REDFT10=5,FFTW_REDFT11=6,FFTW_RODFT00=7,FFTW_RODFT01=8,FFTW_RODFT10=9
  integer, parameter   ::  FFTW_RODFT11=10,FFTW_FORWARD=-1,FFTW_BACKWARD=+1,FFTW_DESTROY_INPUT=1
  integer, parameter   ::  FFTW_UNALIGNED=2,FFTW_CONSERVE_MEMORY=4,FFTW_EXHAUSTIVE=8,FTW_PRESERVE_INPUT=16
  integer, parameter   ::  FFTW_PATIENT=32,FFTW_ESTIMATE=64,FFTW_ESTIMATE_PATIENT=128
  integer, parameter   ::  FFTW_BELIEVE_PCOST=256,FFTW_DFT_R2HC_ICKY=512,FFTW_NONTHREADED_ICKY=1024
  integer, parameter   ::  FFTW_NO_BUFFERING=2048,FFTW_NO_INDIRECT_OP=4096,FFTW_ALLOW_LARGE_GENERIC=8192
  integer, parameter   ::  FFTW_NO_RANK_SPLITS=16384,FFTW_NO_VRANK_SPLITS=32768,FFTW_NO_VRECURSE=65536
  integer*8, pointer,private   :: planf(:),plani(:)
contains
  !----------------------------------------------------------------

  subroutine fftw_init_ser(wfld)
    complex :: wfld(:,:,:,:,:)
    integer :: i,j,k,ith
    integer :: ierr,n(4)
#ifdef DEBUG
    write(0,*) "IN FFTW INIT SET"
#endif


    n(1)=size(wfld,1);n(2)=size(wfld,2);n(3)=size(wfld,3);n(4)=size(wfld,4)


   allocate(planF(size(wfld,5)))
   allocate(planI(size(wfld,5)))
do i=1,size(wfld,5)
    call sfftw_plan_dft(planI(i),4,n,&
      wfld(1,1,1,1,i), &
      wfld(1,1,1,1,i),&
      ffTW_BACKWARD,fftW_PATIENT)
    call sfftw_plan_dft(planF(i),4,n,&
      wfld(1,1,1,1,i),&
      wfld(1,1,1,1,i),&
      ffTW_FORWARD,fftW_PATIENT)
end do

#ifdef DEBUG
    write(0,*) "OUT FFTW INIT SER"
#endif
  end subroutine 


  subroutine fftw_init_par(step)
    type(westep) :: step
    integer :: i,j,k,ith
    integer :: ierr,n(4)
#ifdef DEBUG
    write(0,*) "IN FFTW INIT PAR"
#endif

   step%planF=planF(step%ithread)
   step%planI=planI(step%ithread)


#ifdef DEBUG
    write(0,*) "OUT FFTW INIT PAR"
#endif
  end subroutine 








  !! forward FFT
  subroutine wei_ffft_fftw(data,step)
    complex, dimension(:,:,:,:,:) :: data
    type(westep)                  :: step

#ifdef DEBUG
    write(0,*) "IN FORWARD FFTW"
#endif

    call sfftw_execute(step%planF)

#ifdef DEBUG
    write(0,*) "OUT FORWARD FFTW"
#endif

 end subroutine



  !! inverse FFT
  subroutine wei_ifft_fftw(data,step)
    complex, dimension(:,:,:,:,:) :: data
    type(westep)                  :: step

#ifdef DEBUG
    write(0,*) "IN FORWARD FFTW"
#endif

    call sfftw_execute(step%planI)

#ifdef DEBUG
    write(0,*) "OUT FORWARD FFTW"
#endif
  end subroutine

#endif

end module

