!===============================================================================
!
! clover_mul12t.F90
!
!-------------------------------------------------------------------------------
!
! Copyright (C) 1998-2011 Hinnerk Stueben
!               2008,2012,2014 Yoshifumi Nakamura
! 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 CLOVER_AS_COMPLEX_ARRAY
# include "defs.h"
# include "clover12.h"

!-------------------------------------------------------------------------------
subroutine clover_mult_a12(out, a, in, volh)  ! x := A x
  use typedef_clover
  implicit none

  integer                             :: volh
  type(type_clover12), dimension(volh):: a
  COMPLEX, dimension(12)              :: x, y
#ifdef FLIPSC
  COMPLEX, dimension(NCOL, NDIRAC, *) :: out, in
#else
  COMPLEX, dimension(NDIRAC, NCOL, *) :: out, in
#endif

  integer :: i, j, k

  !$omp parallel do private(x, y, j, k)
  do i = 1, volh
  x(1)= in(SC1, i)
  x(2)= in(SC2, i)
  x(3)= in(SC3, i)
  x(4)= in(SC4, i)
  x(5)= in(SC5, i)
  x(6)= in(SC6, i)
  x(7)= in(SC7, i)
  x(8)= in(SC8, i)
  x(9)= in(SC9, i)
  x(10)= in(SC10, i)
  x(11)= in(SC11, i)
  x(12)= in(SC12, i)

  do j = 1, 12
     y(j) = ZERO
     do k = 1, 12
        y(j) = y(j) + a(i)%i(j,k)*x(k)
     enddo
  enddo

  out(SC1, i) = y(1)
  out(SC2, i) = y(2)
  out(SC3, i) = y(3)
  out(SC4, i) = y(4)
  out(SC5, i) = y(5)
  out(SC6, i) = y(6)
  out(SC7, i) = y(7)
  out(SC8, i) = y(8)
  out(SC9, i) = y(9)
  out(SC10, i) = y(10)
  out(SC11, i) = y(11)
  out(SC12, i) = y(12)
  enddo

end

!-------------------------------------------------------------------------------
subroutine clover_mult_ao12(a, inout, volh)  ! x := A x
  use typedef_clover
  implicit none

  integer                             :: volh
  type(type_clover12), dimension(volh):: a
  COMPLEX, dimension(12)              :: x, y
#ifdef FLIPSC
  COMPLEX, dimension(NCOL, NDIRAC, *) :: inout
#else
  COMPLEX, dimension(NDIRAC, NCOL, *) :: inout
#endif

  integer :: i, j, k

  !$omp parallel do private(x, y, j, k)
  do i = 1, volh
  x(1)= inout(SC1, i)
  x(2)= inout(SC2, i)
  x(3)= inout(SC3, i)
  x(4)= inout(SC4, i)
  x(5)= inout(SC5, i)
  x(6)= inout(SC6, i)
  x(7)= inout(SC7, i)
  x(8)= inout(SC8, i)
  x(9)= inout(SC9, i)
  x(10)= inout(SC10, i)
  x(11)= inout(SC11, i)
  x(12)= inout(SC12, i)

  do j = 1, 12
     y(j) = ZERO
     do k = 1, 12
        y(j) = y(j) + a(i)%i(j,k)*x(k)
     enddo
  enddo

  inout(SC1, i) = y(1)
  inout(SC2, i) = y(2)
  inout(SC3, i) = y(3)
  inout(SC4, i) = y(4)
  inout(SC5, i) = y(5)
  inout(SC6, i) = y(6)
  inout(SC7, i) = y(7)
  inout(SC8, i) = y(8)
  inout(SC9, i) = y(9)
  inout(SC10, i) = y(10)
  inout(SC11, i) = y(11)
  inout(SC12, i) = y(12)
  enddo

end

!-------------------------------------------------------------------------------
subroutine clover_mult_a12_block(out, b, a, in, i1, i2)  ! out := A in
  use typedef_clover
  implicit none

  REAL                                :: b
  type(type_clover12), dimension(*)   :: a
  COMPLEX, dimension(12)              :: x, y
#ifdef FLIPSC
  COMPLEX, dimension(NCOL, NDIRAC, *) :: out, in
#else
  COMPLEX, dimension(NDIRAC, NCOL, *) :: out, in
#endif
  integer                             :: i1, i2

  integer :: i, j, k

  do i = i1, i2
  x(1) = in(SC1, i)
  x(2) = in(SC2, i)
  x(3) = in(SC3, i)
  x(4) = in(SC4, i)
  x(5) = in(SC5, i)
  x(6) = in(SC6, i)
  x(7) = in(SC7, i)
  x(8) = in(SC8, i)
  x(9) = in(SC9, i)
  x(10) = in(SC10, i)
  x(11) = in(SC11, i)
  x(12) = in(SC12, i)

  do j = 1, 12
     y(j) = ZERO
     do k = 1, 12
        y(j) = y(j) + a(i)%i(j,k)*x(k)
     enddo
  enddo

  out(SC1, i) = b * out(SC1, i) +  y(1)
  out(SC2, i) = b * out(SC2, i) +  y(2)
  out(SC3, i) = b * out(SC3, i) +  y(3)
  out(SC4, i) = b * out(SC4, i) +  y(4)
  out(SC5, i) = b * out(SC5, i) +  y(5)
  out(SC6, i) = b * out(SC6, i) +  y(6)
  out(SC7, i) = b * out(SC7, i) +  y(7)
  out(SC8, i) = b * out(SC8, i) +  y(8)
  out(SC9, i) = b * out(SC9, i) +  y(9)
  out(SC10, i) = b * out(SC10, i) +  y(10)
  out(SC11, i) = b * out(SC11, i) +  y(11)
  out(SC12, i) = b * out(SC12, i) +  y(12)
  enddo

end

!-------------------------------------------------------------------------------
subroutine clover_mult_ao12_block(a, inout, i1, i2)  ! out := A in
  use typedef_clover
  implicit none

  type(type_clover12), dimension(*)   :: a
  COMPLEX, dimension(12)              :: x, y
#ifdef FLIPSC
  COMPLEX, dimension(NCOL, NDIRAC, *) :: inout
#else
  COMPLEX, dimension(NDIRAC, NCOL, *) :: inout
#endif
  integer                             :: i1, i2

  integer :: i, j, k

  do i = i1, i2
  x(1) = inout(SC1, i)
  x(2) = inout(SC2, i)
  x(3) = inout(SC3, i)
  x(4) = inout(SC4, i)
  x(5) = inout(SC5, i)
  x(6) = inout(SC6, i)
  x(7) = inout(SC7, i)
  x(8) = inout(SC8, i)
  x(9) = inout(SC9, i)
  x(10) = inout(SC10, i)
  x(11) = inout(SC11, i)
  x(12) = inout(SC12, i)

  do j = 1, 12
     y(j) = ZERO
     do k = 1, 12
        y(j) = y(j) + a(i)%i(j,k)*x(k)
     enddo
  enddo

  inout(SC1, i) = y(1)
  inout(SC2, i) = y(2)
  inout(SC3, i) = y(3)
  inout(SC4, i) = y(4)
  inout(SC5, i) = y(5)
  inout(SC6, i) = y(6)
  inout(SC7, i) = y(7)
  inout(SC8, i) = y(8)
  inout(SC9, i) = y(9)
  inout(SC10, i) = y(10)
  inout(SC11, i) = y(11)
  inout(SC12, i) = y(12)
  enddo

end

!-------------------------------------------------------------------------------
subroutine clover_mult_ao122_block(out, a, in, i1, i2)  ! out := A in
  use typedef_clover
  implicit none

  type(type_clover12), dimension(*)   :: a
  COMPLEX, dimension(12)              :: x, y
#ifdef FLIPSC
  COMPLEX, dimension(NCOL, NDIRAC, *) :: out, in
#else
  COMPLEX, dimension(NDIRAC, NCOL, *) :: out, in
#endif
  integer                             :: i1, i2

  integer :: i, j, k

  do i = i1, i2
  x(1) = in(SC1, i)
  x(2) = in(SC2, i)
  x(3) = in(SC3, i)
  x(4) = in(SC4, i)
  x(5) = in(SC5, i)
  x(6) = in(SC6, i)
  x(7) = in(SC7, i)
  x(8) = in(SC8, i)
  x(9) = in(SC9, i)
  x(10) = in(SC10, i)
  x(11) = in(SC11, i)
  x(12) = in(SC12, i)

  do j = 1, 12
     y(j) = ZERO
     do k = 1, 12
        y(j) = y(j) + a(i)%i(j,k)*x(k)
     enddo
  enddo

  out(SC1, i) = y(1)
  out(SC2, i) = y(2)
  out(SC3, i) = y(3)
  out(SC4, i) = y(4)
  out(SC5, i) = y(5)
  out(SC6, i) = y(6)
  out(SC7, i) = y(7)
  out(SC8, i) = y(8)
  out(SC9, i) = y(9)
  out(SC10, i) = y(10)
  out(SC11, i) = y(11)
  out(SC12, i) = y(12)
  enddo

end

!-------------------------------------------------------------------------------
subroutine clover_mult_a12dag(out, a, in, volh)  ! x := A x
  use typedef_clover
  implicit none

  integer                             :: volh
  type(type_clover12), dimension(volh):: a
  COMPLEX, dimension(12)              :: x, y
#ifdef FLIPSC
  COMPLEX, dimension(NCOL, NDIRAC, *) :: out, in
#else
  COMPLEX, dimension(NDIRAC, NCOL, *) :: out, in
#endif

  integer :: i, j, k

  !$omp parallel do private(x, y, j, k)
  do i = 1, volh
  x(1)= in(SC1, i)
  x(2)= in(SC2, i)
  x(3)= in(SC3, i)
  x(4)= in(SC4, i)
  x(5)= in(SC5, i)
  x(6)= in(SC6, i)
  x(7)= in(SC7, i)
  x(8)= in(SC8, i)
  x(9)= in(SC9, i)
  x(10)= in(SC10, i)
  x(11)= in(SC11, i)
  x(12)= in(SC12, i)

  do j = 1, 12
     y(j) = ZERO
     do k = 1, 12
        y(j) = y(j) + conjg(a(i)%i(k,j))*x(k)
     enddo
  enddo

  out(SC1, i) = y(1)
  out(SC2, i) = y(2)
  out(SC3, i) = y(3)
  out(SC4, i) = y(4)
  out(SC5, i) = y(5)
  out(SC6, i) = y(6)
  out(SC7, i) = y(7)
  out(SC8, i) = y(8)
  out(SC9, i) = y(9)
  out(SC10, i) = y(10)
  out(SC11, i) = y(11)
  out(SC12, i) = y(12)
  enddo

end

!-------------------------------------------------------------------------------
subroutine clover_mult_ao12dag(a, inout, volh)  ! x := A x
  use typedef_clover
  implicit none

  integer                             :: volh
  type(type_clover12), dimension(volh):: a
  COMPLEX, dimension(12)              :: x, y
#ifdef FLIPSC
  COMPLEX, dimension(NCOL, NDIRAC, *) :: inout
#else
  COMPLEX, dimension(NDIRAC, NCOL, *) :: inout
#endif

  integer :: i, j, k

  !$omp parallel do private(x, y, j, k)
  do i = 1, volh
  x(1)= inout(SC1, i)
  x(2)= inout(SC2, i)
  x(3)= inout(SC3, i)
  x(4)= inout(SC4, i)
  x(5)= inout(SC5, i)
  x(6)= inout(SC6, i)
  x(7)= inout(SC7, i)
  x(8)= inout(SC8, i)
  x(9)= inout(SC9, i)
  x(10)= inout(SC10, i)
  x(11)= inout(SC11, i)
  x(12)= inout(SC12, i)

  do j = 1, 12
     y(j) = ZERO
     do k = 1, 12
        y(j) = y(j) + conjg(a(i)%i(k,j))*x(k)
     enddo
  enddo

  inout(SC1, i) = y(1)
  inout(SC2, i) = y(2)
  inout(SC3, i) = y(3)
  inout(SC4, i) = y(4)
  inout(SC5, i) = y(5)
  inout(SC6, i) = y(6)
  inout(SC7, i) = y(7)
  inout(SC8, i) = y(8)
  inout(SC9, i) = y(9)
  inout(SC10, i) = y(10)
  inout(SC11, i) = y(11)
  inout(SC12, i) = y(12)
  enddo

end

!-------------------------------------------------------------------------------
subroutine clover_mult_a12dag_block(out, b, a, in, i1, i2)  ! out := A in
  use typedef_clover
  implicit none

  REAL                                :: b
  type(type_clover12), dimension(*)   :: a
  COMPLEX, dimension(12)              :: x, y
#ifdef FLIPSC
  COMPLEX, dimension(NCOL, NDIRAC, *) :: out, in
#else
  COMPLEX, dimension(NDIRAC, NCOL, *) :: out, in
#endif
  integer                             :: i1, i2

  integer :: i, j, k

  do i = i1, i2
  x(1) = in(SC1, i)
  x(2) = in(SC2, i)
  x(3) = in(SC3, i)
  x(4) = in(SC4, i)
  x(5) = in(SC5, i)
  x(6) = in(SC6, i)
  x(7) = in(SC7, i)
  x(8) = in(SC8, i)
  x(9) = in(SC9, i)
  x(10) = in(SC10, i)
  x(11) = in(SC11, i)
  x(12) = in(SC12, i)

  do j = 1, 12
     y(j) = ZERO
     do k = 1, 12
        y(j) = y(j) + conjg(a(i)%i(k,j))*x(k)
     enddo
  enddo

  out(SC1, i) = b * out(SC1, i) +  y(1)
  out(SC2, i) = b * out(SC2, i) +  y(2)
  out(SC3, i) = b * out(SC3, i) +  y(3)
  out(SC4, i) = b * out(SC4, i) +  y(4)
  out(SC5, i) = b * out(SC5, i) +  y(5)
  out(SC6, i) = b * out(SC6, i) +  y(6)
  out(SC7, i) = b * out(SC7, i) +  y(7)
  out(SC8, i) = b * out(SC8, i) +  y(8)
  out(SC9, i) = b * out(SC9, i) +  y(9)
  out(SC10, i) = b * out(SC10, i) +  y(10)
  out(SC11, i) = b * out(SC11, i) +  y(11)
  out(SC12, i) = b * out(SC12, i) +  y(12)
  enddo

end

!-------------------------------------------------------------------------------
subroutine clover_mult_ao12dag_block(a, inout, i1, i2)  ! out := A in
  use typedef_clover
  implicit none

  type(type_clover12), dimension(*)   :: a
  COMPLEX, dimension(12)              :: x, y
#ifdef FLIPSC
  COMPLEX, dimension(NCOL, NDIRAC, *) :: inout
#else
  COMPLEX, dimension(NDIRAC, NCOL, *) :: inout
#endif
  integer                             :: i1, i2

  integer :: i, j, k

  do i = i1, i2
  x(1) = inout(SC1, i)
  x(2) = inout(SC2, i)
  x(3) = inout(SC3, i)
  x(4) = inout(SC4, i)
  x(5) = inout(SC5, i)
  x(6) = inout(SC6, i)
  x(7) = inout(SC7, i)
  x(8) = inout(SC8, i)
  x(9) = inout(SC9, i)
  x(10) = inout(SC10, i)
  x(11) = inout(SC11, i)
  x(12) = inout(SC12, i)

  do j = 1, 12
     y(j) = ZERO
     do k = 1, 12
        y(j) = y(j) + conjg(a(i)%i(k,j))*x(k)
     enddo
  enddo

  inout(SC1, i) = y(1)
  inout(SC2, i) = y(2)
  inout(SC3, i) = y(3)
  inout(SC4, i) = y(4)
  inout(SC5, i) = y(5)
  inout(SC6, i) = y(6)
  inout(SC7, i) = y(7)
  inout(SC8, i) = y(8)
  inout(SC9, i) = y(9)
  inout(SC10, i) = y(10)
  inout(SC11, i) = y(11)
  inout(SC12, i) = y(12)
  enddo

end

!-------------------------------------------------------------------------------
subroutine clover_mult_ao122dag_block(out, a, in, i1, i2)  ! out := A in
  use typedef_clover
  implicit none

  type(type_clover12), dimension(*)   :: a
  COMPLEX, dimension(12)              :: x, y
#ifdef FLIPSC
  COMPLEX, dimension(NCOL, NDIRAC, *) :: out, in
#else
  COMPLEX, dimension(NDIRAC, NCOL, *) :: out, in
#endif
  integer                             :: i1, i2

  integer :: i, j, k

  do i = i1, i2
  x(1) = in(SC1, i)
  x(2) = in(SC2, i)
  x(3) = in(SC3, i)
  x(4) = in(SC4, i)
  x(5) = in(SC5, i)
  x(6) = in(SC6, i)
  x(7) = in(SC7, i)
  x(8) = in(SC8, i)
  x(9) = in(SC9, i)
  x(10) = in(SC10, i)
  x(11) = in(SC11, i)
  x(12) = in(SC12, i)

  do j = 1, 12
     y(j) = ZERO
     do k = 1, 12
        y(j) = y(j) + conjg(a(i)%i(k,j))*x(k)
     enddo
  enddo

  out(SC1, i) = y(1)
  out(SC2, i) = y(2)
  out(SC3, i) = y(3)
  out(SC4, i) = y(4)
  out(SC5, i) = y(5)
  out(SC6, i) = y(6)
  out(SC7, i) = y(7)
  out(SC8, i) = y(8)
  out(SC9, i) = y(9)
  out(SC10, i) = y(10)
  out(SC11, i) = y(11)
  out(SC12, i) = y(12)
  enddo

end

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