!===============================================================================
!
! cg_test.F90 - for testing SIMD routines
!
!-------------------------------------------------------------------------------
!
! Copyright (C) 2013-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 "simd.h"
# include "defs.h"

!-------------------------------------------------------------------------------
subroutine cg_test(out, in, u, clover_a, clover_i)

  use typedef_clover
  use module_vol
  use module_nn
  use module_cg_vol
  use module_cg_nn
  use module_cg_arrays
  use module_cg_conf
  use module_cg_procs

  implicit none

  SPINCOL_FIELD :: out
  SPINCOL_FIELD :: in
  GAUGE_FIELD :: u
  CLOVER_FIELD_A :: clover_a, clover_i
 
  REAL, parameter :: b = 3.14
  integer, parameter :: e = EVEN
  integer, parameter :: o = ODD
  integer :: d, c, i, ierr


  !call clover_mult_ao(clover_a(1, 1, EVEN), in, volh)
  !call cg_procs%co(cg_conf%c_even, cg_conf%in, volh_tot_r8s, volh_r8s)
  !call cg_procs%copyout_spincol(out, cg_conf%in)

  !call clover_mult_ao(clover_i(1, 1, ODD), in, volh)
  !call cg_procs%co(cg_conf%c_odd, cg_conf%in, volh_tot_r8s, volh_r8s)
  !call cg_procs%copyout_spincol(out, cg_conf%in)


  !call clover_mult_a2(out, b, clover_a(1, 1, EVEN), in, volh)
  !call cg_procs%c2(cg_conf%out, b, cg_conf%c_even, cg_conf%in, volh_tot_r8s, volh_r8s)
  !call cg_procs%copyout_spincol(in, cg_conf%out)

  !call clover_mult_a2(out, b, clover_i(1, 1, ODD), in, volh)
  !call cg_procs%c2(cg_conf%out, b, cg_conf%c_odd, cg_conf%in, volh_tot_r8s, volh_r8s)
  !call cg_procs%copyout_spincol(in, cg_conf%out)

  !call d_t (out, in, u(1,1,1,e,4), u(1,1,1,o,4), nn(1,e,4,FWD), nn(1,e,4,BWD), volh)
  !call d_zf(out, in, u(1,1,1,e,3), u(1,1,1,o,3), nn(1,e,3,FWD), nn(1,e,3,BWD), volh)
  !call d_yf(out, in, u(1,1,1,e,2), u(1,1,1,o,2), nn(1,e,2,FWD), nn(1,e,2,BWD), volh)
  call d_xf(out, in, u(1,1,1,e,1), u(1,1,1,o,1), nn(1,e,1,FWD), nn(1,e,1,BWD), volh)

  !call cg_test_d(cg_conf%out, cg_conf%in, cg_conf%u, nn_r8s(1,e,4,FWD), nn_r8s(1,e,4,BWD), volh_tot_r8s, volh_r8s)
  !call cg_test_d(cg_conf%out, cg_conf%in, cg_conf%u, nn_r8s(1,e,3,FWD), nn_r8s(1,e,3,BWD), volh_tot_r8s, volh_r8s)
  !call cg_test_d(cg_conf%out, cg_conf%in, cg_conf%u, nn_r8s(1,e,2,FWD), nn_r8s(1,e,2,BWD), volh_tot_r8s, volh_r8s)
  call cg_test_d(cg_conf%out, cg_conf%in, cg_conf%u, nn_r8s(1,e,1,FWD), nn_r8s(1,e,1,BWD), volh_tot_r8s, volh_r8s)

  call cg_procs%copyout_spincol(in, cg_conf%out)

  do i = 1, volh
     do c = 1, NCOL
        do d = 1, NDIRAC
           write(0,*) d, c, i
           !!CHECK(Re(out(d, c, i)) == Re(in(d, c, i)))
           !!CHECK(Im(out(d, c, i)) == Im(in(d, c, i)))

           CHECK(abs(Re(out(d, c, i)) - Re(in(d, c, i))) < 1.0d-13)
           CHECK(abs(Im(out(d, c, i)) - Im(in(d, c, i))) < 1.0d-13)

        enddo
     enddo
  enddo

  write(0,*) "cg_test(): passed"
  call mpi_finalize(ierr)
  stop

end

!-------------------------------------------------------------------------------
subroutine cg_test_d(out, in, u, nn_fwd, nn_bwd, volh_tot, volh)

  implicit none
  integer :: nn_fwd(*), nn_bwd(*), volh_tot, volh
  !REAL :: out(*), in(*), u(SIMD_WIDTH_R8, 2, NCOL * FWD_BWD, NCOL, volh, EVEN:ODD, DIM)
  REAL :: out(*), in(*), u(SIMD_WIDTH_R8, 2, NCOL, NCOL, volh_tot, EVEN:ODD, DIM)
  integer, parameter :: e = EVEN
  integer, parameter :: o = ODD

  !call cg_d102_t1_sc_r8s(out, in, u(1,1,1,1,1,e,4), nn_fwd, nn_bwd, volh_tot, volh)
  !call cg_d102_z_sc_r8s (out, in, u(1,1,1,1,1,e,3), nn_fwd, nn_bwd, volh_tot, volh)
  !call cg_d102_y_sc_r8s (out, in, u(1,1,1,1,1,e,2), nn_fwd, nn_bwd, volh_tot, volh)
  !call cg_d102_x_sc_r8s (out, in, u(1,1,1,1,1,e,1), nn_fwd, nn_bwd, volh_tot, volh)

  !call cg_d2_t1_sc_r8s(out, in, u(1,1,1,1,1,e,4), u(1,1,1,1,1,o,4), nn_fwd, nn_bwd, volh_tot, volh)
  !call cg_d2_z_sc_r8s (out, in, u(1,1,1,1,1,e,3), u(1,1,1,1,1,o,3), nn_fwd, nn_bwd, volh_tot, volh)
  !call cg_d2_y_sc_r8s (out, in, u(1,1,1,1,1,e,2), u(1,1,1,1,1,o,2), nn_fwd, nn_bwd, volh_tot, volh)
  call cg_d2_x_sc_r8s (out, in, u(1,1,1,1,1,e,1), u(1,1,1,1,1,o,1), nn_fwd, nn_bwd, volh_tot, volh)

end

!===============================================================================
