!===============================================================================
!
! cg_copy_gauge.F90
!
!-------------------------------------------------------------------------------
!
! Copyright (C) 2012-2015 Hinnerk Stueben
!
! This file is part of BQCD -- Berlin Quantum ChromoDynamics program
!
! BQCD is free software: you can redistribute it and/or modify
! it under the terms of the GNU General Public License as published by
! the Free Software Foundation, either version 3 of the License, or
! (at your option) any later version.
!
! BQCD is distributed in the hope that it will be useful,
! but WITHOUT ANY WARRANTY; without even the implied warranty of
! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
! GNU General Public License for more details.
!
! You should have received a copy of the GNU General Public License
! along with BQCD.  If not, see <http://www.gnu.org/licenses/>.
!
!-------------------------------------------------------------------------------
# define LANGUAGE_FORTRAN
# include "defs.h"
# include "cg_defs.h"
# include "simd.h"

FOR rkind in 4 8
SET _rr = _r %% rkind
SET _rrs = _rr %% s
SET SIMD_WIDTH = SIMD_WIDTH %% $(toupper _rr)
!-------------------------------------------------------------------------------
# undef TRACE_NAME
# define TRACE_NAME cg_copyin_g1%%_rr
!-------------------------------------------------------------------------------
subroutine cg_copyin_g1%%_rr(out, in)

  use module_vol
  implicit none
  complex(8), intent(in)      ::  in(NCOL, NCOL, volh_tot, EVEN:ODD, DIM)
  complex(rkind), intent(out) :: out(NCOL, NCOL, volh_tot, EVEN:ODD, DIM)
  integer :: mu, eo, i
  real(8) :: factor

  TRACE_ENTRY

  ! two loops => 'first touch'

  FOR j1 in 1 volh+1
  SET j2 = $(ifthenelse '[[ j1 = 1 ]]' 'volh' 'volh_tot')

  do mu = 1, DIM
     if (mu == 4) then
        factor = TWO
     else
        factor = ONE
     endif     
     do eo = EVEN, ODD
        !$omp parallel do
        do i = j1, j2
        DO c2 = 1, 3
        DO c1 = 1, 3
           out(c1, c2, i, eo, mu) = factor * in(c1, c2, i, eo, mu)
        ENDDO
        ENDDO
        enddo
     enddo
  enddo
  ENDSET
  ENDFOR

  TRACE_RETURN
end

!-------------------------------------------------------------------------------
# undef TRACE_NAME
# define TRACE_NAME cg_copyin_g1%%_rrs
!-------------------------------------------------------------------------------
subroutine cg_copyin_g1%%_rrs(out, in)

  use typedef_simd
  use module_vol
  use module_cg_vol
  use module_nn
  implicit none
  complex(8), intent(in)               ::  in(NCOL, NCOL, volh_tot, EVEN:ODD, DIM)
  type(simd_complex%%_rr), intent(out) :: out(NCOL, NCOL, volh_tot%%_rrs, EVEN:ODD, DIM+1)
  integer :: mu, eo, i, j, w, oe, jb
  real(8) :: factor

  TRACE_ENTRY

  ! two loops => 'first touch'

  FOR j1 in 0 volh%%_rrs
  SET j2 = $(ifthenelse '[[ j1 = 0 ]]' 'volh%%_rrs - 1' 'volh_tot%%_rrs - 1')

  do mu = 1, DIM
     if (mu == 4) then
        factor = TWO
     else
        factor = ONE
     endif     
     do eo = EVEN, ODD
        !$omp parallel do private (i, w)
        do j = j1, j2
           i = j * SIMD_WIDTH
           do w = 1, SIMD_WIDTH
           DO c2 = 1, 3
           DO c1 = 1, 3
              out(c1, c2, j+1, eo, mu)%r(w) = factor * real(in(c1, c2, i+w, eo, mu))
              out(c1, c2, j+1, eo, mu)%i(w) = factor * aimag(in(c1, c2, i+w, eo, mu))
           ENDDO
           ENDDO
           enddo
        enddo
     enddo
  enddo
  ENDSET
  ENDFOR

  do eo = EVEN, ODD
     oe = EVEN + ODD - eo
     !$omp parallel do private (i, w, jb)
     do j = 0, volh%%_rrs - 1
        i = j * SIMD_WIDTH
        do w = 1, SIMD_WIDTH
           jb = nn(i+w, eo, 1, BWD)
           !!write(6,*) "cg_copyin_g1%%_rrs", j+1, jb, volh
           DO c2 = 1, 3
              DO c1 = 1, 3
                 out(c1, c2, j+1, eo, DIM+1)%r(w) = real(in(c1, c2, jb, oe, 1))
                 out(c1, c2, j+1, eo, DIM+1)%i(w) = aimag(in(c1, c2, jb, oe, 1))
              ENDDO
           ENDDO
        enddo
     enddo
  enddo
  
  TRACE_RETURN
end

!-------------------------------------------------------------------------------
# undef TRACE_NAME
# define TRACE_NAME cg_copyin_g2%%_rr
!-------------------------------------------------------------------------------
subroutine cg_copyin_g2%%_rr(out, in)

  use module_vol
  use module_nn
  implicit none
  complex(8), intent(in)      ::  in(NCOL, NCOL, volh_tot, EVEN:ODD, DIM)
  complex(rkind), intent(out) :: out(NCOL * FWD_BWD, NCOL, volh, EVEN:ODD, DIM)
  integer :: mu, e, o, i, jb
  real(8) :: factor

  TRACE_ENTRY

  do mu = 1, DIM
     if (mu == 4) then
        factor = TWO
     else
        factor = ONE
     endif     
     do e = EVEN, ODD
        o = EVEN + ODD - e
        !$omp parallel do private(jb)
        do i = 1, volh
           jb = nn(i, e, mu, BWD)
        DO c = 1, 3
           out(1, c, i, e, mu) = factor * conjg(in(c, 1, jb, o, mu))  
           out(2, c, i, e, mu) = factor * conjg(in(c, 2, jb, o, mu))  
           out(3, c, i, e, mu) = factor * conjg(in(c, 3, jb, o, mu))  
           out(4, c, i, e, mu) = factor *       in(1, c, i, e, mu)
           out(5, c, i, e, mu) = factor *       in(2, c, i, e, mu)
           out(6, c, i, e, mu) = factor *       in(3, c, i, e, mu)
        ENDDO
        enddo
     enddo
  enddo

  TRACE_RETURN
end

!-------------------------------------------------------------------------------
# undef TRACE_NAME
# define TRACE_NAME cg_copyin_g2%%_rrs
!-------------------------------------------------------------------------------
subroutine cg_copyin_g2%%_rrs(out, in)

  use typedef_simd
  use module_nn
  use module_vol
  use module_cg_vol
  implicit none
  complex(8), intent(in)               ::  in(NCOL, NCOL, volh_tot, EVEN:ODD, DIM)
  type(simd_complex%%_rr), intent(out) :: out(NCOL * FWD_BWD, NCOL, volh%%_rrs, EVEN:ODD, DIM)
  integer :: mu, e, o, i, j, w, jb
  real(8) :: factor

  TRACE_ENTRY

  do mu = 1, DIM
     if (mu == 4) then
        factor = TWO
     else
        factor = ONE
     endif     
     do e = EVEN, ODD
        o = EVEN + ODD - e
        !$omp parallel do private (i, w, jb)
        do j = 0, volh%%_rrs - 1
           i = j * SIMD_WIDTH
           do w = 1, SIMD_WIDTH
           jb = nn(i+w, e, mu, BWD)
           DO c = 1, 3
              out(1, c, j+1, e, mu)%r(w) =  factor *  real(in(c, 1, jb, o, mu))
              out(1, c, j+1, e, mu)%i(w) = -factor * aimag(in(c, 1, jb, o, mu))
              out(2, c, j+1, e, mu)%r(w) =  factor *  real(in(c, 2, jb, o, mu))
              out(2, c, j+1, e, mu)%i(w) = -factor * aimag(in(c, 2, jb, o, mu))
              out(3, c, j+1, e, mu)%r(w) =  factor *  real(in(c, 3, jb, o, mu))
              out(3, c, j+1, e, mu)%i(w) = -factor * aimag(in(c, 3, jb, o, mu))

              out(4, c, j+1, e, mu)%r(w) =  factor *  real(in(1, c, i+w, e, mu))
              out(4, c, j+1, e, mu)%i(w) =  factor * aimag(in(1, c, i+w, e, mu))
              out(5, c, j+1, e, mu)%r(w) =  factor *  real(in(2, c, i+w, e, mu))
              out(5, c, j+1, e, mu)%i(w) =  factor * aimag(in(2, c, i+w, e, mu))
              out(6, c, j+1, e, mu)%r(w) =  factor *  real(in(3, c, i+w, e, mu))
              out(6, c, j+1, e, mu)%i(w) =  factor * aimag(in(3, c, i+w, e, mu))
           ENDDO
           enddo
        enddo
     enddo
  enddo

  TRACE_RETURN
end

ENDSET
ENDSET
ENDSET
ENDFOR
!===============================================================================
