!> Applies the magic filter matrix transposed  in periodic BC
!! The input array x is not overwritten
!! this routine is modified to accept the GPU convolution if it is the case
subroutine convolut_magic_t_per_test(n1,n2,n3,x,y)
  use liborbs_precisions
  use dynamic_memory
  implicit none
  integer, intent(in) :: n1,n2,n3
  real(wp), dimension(0:n1,0:n2,0:n3), intent(inout) :: x
  real(wp), dimension(0:n1,0:n2,0:n3), intent(out) :: y
  !local variables
  character(len=*), parameter :: subname='convolut_magic_t_per'
  !n(c) integer, parameter :: lowfil=-7,lupfil=8
  integer :: ndat
  real(wp), dimension(:,:,:), allocatable :: ww

  ww = f_malloc((/ 0.to.n1, 0.to.n2, 0.to.n3 /),id='ww')

  !  (I1,I2*I3) -> (I2*I3,i1)
  ndat=(n2+1)*(n3+1)
  call convrot_t_per_test(n1,ndat,x,y)
  !  (I2,I3*i1) -> (I3*i1,i2)
  ndat=(n3+1)*(n1+1)
  call convrot_t_per_test(n2,ndat,y,ww)
  !  (I3,i1*i2) -> (i1*i2,i3)
  ndat=(n1+1)*(n2+1)
  call convrot_t_per_test(n3,ndat,ww,y)

  call f_free(ww)

END SUBROUTINE convolut_magic_t_per_test

subroutine convrot_t_per_test(n1,ndat,x,y)
  use liborbs_precisions
  implicit none

!dee
!  integer :: iend_test,count_rate_test,count_max_test,istart_test

  integer,parameter::lowfil=-7,lupfil=8
  !  dimension x(lowfil:n1+lupfil,ndat),y(ndat,0:n1)
  integer, intent(in) :: n1,ndat
  real(wp), dimension(0:n1,ndat), intent(in) :: x
  real(wp), dimension(ndat,0:n1), intent(out) :: y
  ! the filtered output data structure has shrunk by the filter length

  !          THE MAGIC FILTER FOR DAUBECHIES-16
  real(wp) :: fil(lowfil:lupfil)
  DATA fil / &
       2.72734492911979659657715313017228D-6,&
       -0.5185986881173432922848639136911487D-4,&
       0.49443227688689919192282259476750972D-3,&
       -0.344128144493493857280881509686821861D-2,&
       0.1337263414854794752733423467013220997D-1,&
       -0.2103025160930381434955489412839065067D-1,&
       -0.604895289196983516002834636D-1,&
       0.9940415697834003993178616713D0,&
       0.612625895831207982195380597D-1,&
       0.2373821463724942397566389712597274535D-1,&
       -0.942047030201080385922711540948195075D-2,&
       0.174723713672993903449447812749852942D-2,&
       -0.30158038132690463167163703826169879D-3,&
       0.8762984476210559564689161894116397D-4,&
       -0.1290557201342060969516786758559028D-4,&
       8.4334247333529341094733325815816D-7 /

  integer :: i,j,l,k
  integer :: mod_arr(lowfil:n1+lupfil)   
  real(wp) :: fill,tt1,tt2,tt3,tt4,tt5,tt6,tt7,tt8,tt9,tt10,tt11,tt12,tt

  call fill_mod_arr(mod_arr,lowfil,n1+lupfil,n1+1)

!dee
!call system_clock(istart_test,count_rate_test,count_max_test)

!$omp parallel default (private) shared(x,y,fil,ndat,n1,mod_arr)
!$omp do 
  do j=0,ndat/12-1

     do i=0,n1

        tt1=0.e0_wp
        tt2=0.e0_wp
        tt3=0.e0_wp
        tt4=0.e0_wp
        tt5=0.e0_wp
        tt6=0.e0_wp
        tt7=0.e0_wp
        tt8=0.e0_wp
        tt9 =0.e0_wp
        tt10=0.e0_wp
        tt11=0.e0_wp
        tt12=0.e0_wp

        do l=lowfil,lupfil
           k=mod_arr(i+l)   
           fill=fil(l)

           tt1=tt1+x(  k,j*12+1)*fill
           tt2=tt2+x(  k,j*12+2)*fill
           tt3=tt3+x(  k,j*12+3)*fill
           tt4=tt4+x(  k,j*12+4)*fill
           tt5=tt5+x(  k,j*12+5)*fill
           tt6=tt6+x(  k,j*12+6)*fill
           tt7=tt7+x(  k,j*12+7)*fill
           tt8=tt8+x(  k,j*12+8)*fill

           tt9 =tt9 +x(  k,j*12+9 )*fill
           tt10=tt10+x(  k,j*12+10)*fill
           tt11=tt11+x(  k,j*12+11)*fill
           tt12=tt12+x(  k,j*12+12)*fill
        end do
        y(j*12+1,i)=tt1
        y(j*12+2,i)=tt2
        y(j*12+3,i)=tt3
        y(j*12+4,i)=tt4
        y(j*12+5,i)=tt5
        y(j*12+6,i)=tt6
        y(j*12+7,i)=tt7
        y(j*12+8,i)=tt8

        y(j*12+9 ,i)=tt9 
        y(j*12+10,i)=tt10
        y(j*12+11,i)=tt11
        y(j*12+12,i)=tt12

     end do
  end do

  !$omp end do

  !$omp do
  do j=(ndat/12)*12+1,ndat
     do i=0,n1

        tt=0.e0_wp
        do l=lowfil,lupfil
           k=mod_arr(i+l)   
           tt=tt+x(  k,j)*fil(l)
        end do
        y(j,i)=tt

     end do
  end do
  !$omp end do

  !$omp end parallel

!dee
!call system_clock(iend_test,count_rate_test,count_max_test)
!write(*,*) 'elapsed time on comb',(iend_test-istart_test)/(1.d0*count_rate_test)

END SUBROUTINE convrot_t_per_test
