!===============================================================================
!
! dsf_ddd.F90
!
!-------------------------------------------------------------------------------
!
! Copyright (C) 2009-2010 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/>.
!
!-------------------------------------------------------------------------------
# include "defs.h"

!-------------------------------------------------------------------------------
subroutine dsf_mtdagmt_dd(p, step, a, b, mid)
  use module_vol
  use module_dd
  implicit none

  GENERATOR_FIELD, intent(inout) :: p
  REAL,            intent(in)    :: step
  COMPLEX, dimension (4,3,ld%lat%volh, 0:ld%lat%num_ip-1),intent(in) :: a,b
  integer,         intent(in)    :: mid

  COMPLEX, allocatable :: w(:, :, :, :, :)
  COMPLEX, allocatable :: w1(:, :, :, :, :)
  COMPLEX, allocatable :: w2(:, :, :, :, :)
  integer :: ierr

  allocate(w(NCOL, NCOL, volh_tot, EVEN:ODD, DIM), STAT = ierr)
  if (ierr /= 0) then
     call stderr2_int("allocation failed", 1, ierr)
     call die("dsf: allocation failed w")
  endif
  allocate(w1(NCOL, NCOL, volh_tot, EVEN:ODD, DIM), STAT = ierr)
  if (ierr /= 0) then
     call stderr2_int("allocation failed", 1, ierr)
     call die("dsf: allocation failed w1")
  endif
  allocate(w2(NCOL, NCOL, volh_tot, EVEN:ODD, DIM), STAT = ierr)
  if (ierr /= 0) then
     call stderr2_int("allocation failed", 1, ierr)
     call die("dsf: allocation failed w2")
  endif

  w  = ZERO
  w1 = ZERO
  w2 = ZERO
  call dsf_sum_dd(w, w1, w2, step, a, b, mid)
  call dsf_w2gen(p, w, w1, w2, mid)

  deallocate(w,  STAT = ierr)
  if (ierr /= 0) then
     call stderr2_int("deallocation failed", 1, ierr)
     call die("dsf: deallocation failed w")
  endif
  deallocate(w1, STAT = ierr)
  if (ierr /= 0) then
     call stderr2_int("deallocation failed", 1, ierr)
     call die("dsf: deallocation failed w1")
  endif
  deallocate(w2, STAT = ierr)
  if (ierr /= 0) then
     call stderr2_int("deallocation failed", 1, ierr)
     call die("dsf: deallocation failed w2")
  endif
end

!-------------------------------------------------------------------------------
subroutine dsf_sum_dd(w, w1, w2, step, a, b, id)
  use module_field
  use module_action
  use module_vol
  use module_dd

  use module_usc_dd
  implicit none

  GAUGE_FIELD,     intent(inout) :: w, w1, w2
  REAL,            intent(in)    :: step
  COMPLEX, dimension (4,3,ld%lat%volh, 0:ld%lat%num_ip-1):: a,b,at,bt,tmp
  integer,intent(in) :: id
  REAL                           :: s, s1, s2
  integer :: e, ip

  TIMING_START(timing_bin_dsf_sum)
  DEBUG2S("Start: dsf_sum_dd")


  e=EVEN  !!! BQCD
  at = ZERO
  bt = ZERO

  s = -step * TWO *   action%mtilde(id)%kappa**2 / (ONE + action%mtilde(id)%h**2)
  s1 = -step * TWO * (action%mtilde(id)%cswkappa / EIGHT)
  s2 = -step * TWO * (action%mtilde(id)%cswkappa / EIGHT) * action%mtilde(id)%kappa**2

  tmp = b
  if (s1 /= ZERO) then
     do ip = 0,ld%lat%num_ip-1
     call clover_mult_ao(clover_dd(action%mtilde(id)%cid,ip)%i(1,1,e ),tmp(1,1,1,ip), ld%lat%volh)
     enddo
  endif

  call dsf_at_bt_dd(at, bt, a, tmp, action%mtilde(id)%kappa, &
                               action%mtilde(id)%cswkappa, &
                               action%mtilde(id)%h, &
                               action%mtilde(id)%cid, &
                               e)
  !!                                      the rightmost 2 means doing both domain
  call dsf_xyztfb_dd_w(w, gauge(2)%u(1,1,1,0,1), s, a, tmp, at, bt, e ,0)
  call dsf_xyztfb_dd_w(w, gauge(2)%u(1,1,1,0,1), s, a, tmp, at, bt, e ,1)

  call clover_bsa_dd_w(w2, s2, bt, at, 1-e ,0)
  call clover_bsa_dd_w(w2, s2, bt, at, 1-e ,1)

  if (s1 /= ZERO) then
     do ip = 0,ld%lat%num_ip-1
     call d_dd(e , 1-e, bt(1,1,1,ip), at(1,1,1,ip), ip)
     call clover_mult_ao(clover_dd(action%mtilde(id)%cid,ip)%i(1,1,e ),bt(1,1,1,ip), ld%lat%volh)
     enddo
  endif

  !                            b     a
  call clover_bsa_dd_w(w1, s2, tmp,  bt ,e ,0)
  call clover_bsa_dd_w(w1, s2, tmp,  bt ,e ,1)

  DEBUG2S("End: dsf_sum_dd")
  TIMING_STOP(timing_bin_dsf_sum)
end

!-------------------------------------------------------------------------------
subroutine dsf_at_bt_dd(at, bt, a, b, k, ck, h, cid, e)
  use module_dd
  use module_usc_dd
  implicit none

  COMPLEX, dimension (4,3,ld%lat%volh, 0:ld%lat%num_ip-1):: a,b,at,bt

  REAL,            intent(in)    :: k, ck, h
  integer,         intent(in)    :: e, cid
  integer                        :: o, ip

  if (k == ZERO) return

  TIMING_START(timing_bin_dsf_at_bt)
  DEBUG2S("Start: dsf_at_bt")
  o = 1 - e
  do ip = 0,ld%lat%num_ip-1
  call d_dd(    o , e, at(1,1,1,ip), a(1,1,1,ip), ip)
  call d_dag_dd(o , e, bt(1,1,1,ip), b(1,1,1,ip), ip)
  if (ck /= ZERO) then
     call clover_mult_ao(clover_dd(cid,ip)%i(1,1,o),at(1,1,1,ip), ld%lat%volh)
     call clover_mult_ao(clover_dd(cid,ip)%i(1,1,o),bt(1,1,1,ip), ld%lat%volh)
  endif
  enddo
  DEBUG2S("End: dsf_at_bt")
  TIMING_STOP(timing_bin_dsf_at_bt)
end

!-------------------------------------------------------------------------------
subroutine dsf_xyztfb_dd_w(w_add, u, s, a, b, at, bt, e, dm)
  use module_p_interface
  use module_action
!!  use module_nn
  use module_vol
  use module_dd
  implicit none

  GAUGE_FIELD,     intent(in)    :: u
  COMPLEX, dimension (4,3,ld%lat%volh, 0:ld%lat%num_ip-1):: a,b,at,bt
  REAL,            intent(in)    :: s
  integer,         intent(in)    :: e, dm
  GAUGE_FIELD,     intent(inout) :: w_add
  COMPLEX, allocatable :: w(:, :, :, :, :)
  SU3     :: v
  integer :: i, eo, mu, o, ierr

  if (s == ZERO) return

  TIMING_START(timing_bin_dsf_xyztfb_w)
  DEBUG2S("Start: dsf_xyztfb_w")

!!  ALLOCATE_G_FIELD(w)
  allocate(w(NCOL, NCOL, volh_tot, EVEN:ODD, DIM), STAT = ierr)
  if (ierr /= 0) then
     call stderr2_int("allocation failed", 1, ierr)
     call die("dsf_xyztfb_w: allocation failed w")
  endif

  o = 1 - e
#ifdef GAMMA_NOTATION_CHROMA
  call dsf_f_dcmp_1_p_gamma1_dd(w(1,1,1,e,1), b, at, e, dm)
  call dsf_f_dcmp_1_p_gamma1_dd(w(1,1,1,o,1), bt, a, o, dm)
  call dsf_f_dcmp_1_m_gamma2_dd(w(1,1,1,e,2), b, at, e, dm)
  call dsf_f_dcmp_1_m_gamma2_dd(w(1,1,1,o,2), bt, a, o, dm)
  call dsf_f_dcmp_1_p_gamma3_dd(w(1,1,1,e,3), b, at, e, dm)
  call dsf_f_dcmp_1_p_gamma3_dd(w(1,1,1,o,3), bt, a, o, dm)
  call dsf_f_dcmp_1_m_gammac_dd(w(1,1,1,e,4), b, at, e, dm)
  call dsf_f_dcmp_1_m_gammac_dd(w(1,1,1,o,4), bt, a, o, dm)
#elif defined GAMMA_NOTATION_CHIRAL
  call dsf_f_dcmp_1_m_gamma1_dd(w(1,1,1,e,1), b, at, e, dm)
  call dsf_f_dcmp_1_m_gamma1_dd(w(1,1,1,o,1), bt, a, o, dm)
  call dsf_f_dcmp_1_m_gamma2_dd(w(1,1,1,e,2), b, at, e, dm)
  call dsf_f_dcmp_1_m_gamma2_dd(w(1,1,1,o,2), bt, a, o, dm)
  call dsf_f_dcmp_1_m_gamma3_dd(w(1,1,1,e,3), b, at, e, dm)
  call dsf_f_dcmp_1_m_gamma3_dd(w(1,1,1,o,3), bt, a, o, dm)
  call dsf_f_dcmp_1_m_gammac_dd(w(1,1,1,e,4), b, at, e, dm)
  call dsf_f_dcmp_1_m_gammac_dd(w(1,1,1,o,4), bt, a, o, dm)
#elif defined GAMMA_NOTATION_DDHMC
  call dsf_f_dcmp_1_m_gamma1_dd(w(1,1,1,e,1), b, at, e, dm)
  call dsf_f_dcmp_1_m_gamma1_dd(w(1,1,1,o,1), bt, a, o, dm)
  call dsf_f_dcmp_1_m_gamma2_dd(w(1,1,1,e,2), b, at, e, dm)
  call dsf_f_dcmp_1_m_gamma2_dd(w(1,1,1,o,2), bt, a, o, dm)
  call dsf_f_dcmp_1_m_gamma3_dd(w(1,1,1,e,3), b, at, e, dm)
  call dsf_f_dcmp_1_m_gamma3_dd(w(1,1,1,o,3), bt, a, o, dm)
  call dsf_f_dcmp_1_p_gammac_dd(w(1,1,1,e,4), b, at, e, dm)
  call dsf_f_dcmp_1_p_gammac_dd(w(1,1,1,o,4), bt, a, o, dm)
#elif defined GAMMA_NOTATION_BQCD
  call dsf_f_dcmp_1_p_gamma1_dd(w(1,1,1,e,1), b, at, e, dm)
  call dsf_f_dcmp_1_p_gamma1_dd(w(1,1,1,o,1), bt, a, o, dm)
  call dsf_f_dcmp_1_p_gamma2_dd(w(1,1,1,e,2), b, at, e, dm)
  call dsf_f_dcmp_1_p_gamma2_dd(w(1,1,1,o,2), bt, a, o, dm)
  call dsf_f_dcmp_1_p_gamma3_dd(w(1,1,1,e,3), b, at, e, dm)
  call dsf_f_dcmp_1_p_gamma3_dd(w(1,1,1,o,3), bt, a, o, dm)
  call dsf_f_dcmp_1_m_gamman_dd(w(1,1,1,e,4), b, at, e, dm)
  call dsf_f_dcmp_1_m_gamman_dd(w(1,1,1,o,4), bt, a, o, dm)
#endif

  call flip_bc(w)
  do mu = 1, DIM
     do eo = EVEN, ODD
        !$omp parallel do
        do i = 1, volh
           call u_scale(w(1, 1, i, eo, mu), s)
           call u_add(w_add(1, 1, i, eo, mu), w(1, 1, i, eo, mu))
        enddo
     enddo
  enddo

#ifdef GAMMA_NOTATION_CHROMA
  call dsf_b_dcmp_1_m_gamma1_dd(w(1,1,1,e,1), bt, a, e, dm)
  call dsf_b_dcmp_1_m_gamma1_dd(w(1,1,1,o,1), b, at, o, dm)
  call dsf_b_dcmp_1_p_gamma2_dd(w(1,1,1,e,2), bt, a, e, dm)
  call dsf_b_dcmp_1_p_gamma2_dd(w(1,1,1,o,2), b, at, o, dm)
  call dsf_b_dcmp_1_m_gamma3_dd(w(1,1,1,e,3), bt, a, e, dm)
  call dsf_b_dcmp_1_m_gamma3_dd(w(1,1,1,o,3), b, at, o, dm)
  call dsf_b_dcmp_1_p_gammac_dd(w(1,1,1,e,4), bt, a, e, dm)
  call dsf_b_dcmp_1_p_gammac_dd(w(1,1,1,o,4), b, at, o, dm)
#elif defined GAMMA_NOTATION_CHIRAL
  call dsf_b_dcmp_1_p_gamma1_dd(w(1,1,1,e,1), bt, a, e, dm)
  call dsf_b_dcmp_1_p_gamma1_dd(w(1,1,1,o,1), b, at, o, dm)
  call dsf_b_dcmp_1_p_gamma2_dd(w(1,1,1,e,2), bt, a, e, dm)
  call dsf_b_dcmp_1_p_gamma2_dd(w(1,1,1,o,2), b, at, o, dm)
  call dsf_b_dcmp_1_p_gamma3_dd(w(1,1,1,e,3), bt, a, e, dm)
  call dsf_b_dcmp_1_p_gamma3_dd(w(1,1,1,o,3), b, at, o, dm)
  call dsf_b_dcmp_1_p_gammac_dd(w(1,1,1,e,4), bt, a, e, dm)
  call dsf_b_dcmp_1_p_gammac_dd(w(1,1,1,o,4), b, at, o, dm)
#elif defined GAMMA_NOTATION_DDHMC
  call dsf_b_dcmp_1_p_gamma1_dd(w(1,1,1,e,1), bt, a, e, dm)
  call dsf_b_dcmp_1_p_gamma1_dd(w(1,1,1,o,1), b, at, o, dm)
  call dsf_b_dcmp_1_p_gamma2_dd(w(1,1,1,e,2), bt, a, e, dm)
  call dsf_b_dcmp_1_p_gamma2_dd(w(1,1,1,o,2), b, at, o, dm)
  call dsf_b_dcmp_1_p_gamma3_dd(w(1,1,1,e,3), bt, a, e, dm)
  call dsf_b_dcmp_1_p_gamma3_dd(w(1,1,1,o,3), b, at, o, dm)
  call dsf_b_dcmp_1_m_gammac_dd(w(1,1,1,e,4), bt, a, e, dm)
  call dsf_b_dcmp_1_m_gammac_dd(w(1,1,1,o,4), b, at, o, dm)
#elif defined GAMMA_NOTATION_BQCD
  call dsf_b_dcmp_1_m_gamma1_dd(w(1,1,1,e,1), bt, a, e, dm)
  call dsf_b_dcmp_1_m_gamma1_dd(w(1,1,1,o,1), b, at, o, dm)
  call dsf_b_dcmp_1_m_gamma2_dd(w(1,1,1,e,2), bt, a, e, dm)
  call dsf_b_dcmp_1_m_gamma2_dd(w(1,1,1,o,2), b, at, o, dm)
  call dsf_b_dcmp_1_m_gamma3_dd(w(1,1,1,e,3), bt, a, e, dm)
  call dsf_b_dcmp_1_m_gamma3_dd(w(1,1,1,o,3), b, at, o, dm)
  call dsf_b_dcmp_1_p_gamman_dd(w(1,1,1,e,4), bt, a, e, dm)
  call dsf_b_dcmp_1_p_gamman_dd(w(1,1,1,o,4), b, at, o, dm)
#endif

  do mu = 1, DIM
     do eo = EVEN, ODD
        !$omp parallel do private(v)
        do i = 1, volh
           call uud(v, w(1, 1, i, eo, mu), u(1, 1, i, eo, mu))
           call udu(w(1, 1, i, eo, mu), u(1, 1, i, eo, mu), v)
        enddo
     enddo
  enddo

  call flip_bc(w)

  do mu = 1, DIM
     do eo = EVEN, ODD
        !$omp parallel do
        do i = 1, volh
           call u_scale(w(1, 1, i, eo, mu), -s)
           call u_add(w_add(1, 1, i, eo, mu), w(1, 1, i, eo, mu))
        enddo
     enddo
  enddo

  deallocate(w, STAT = ierr)
  if (ierr /= 0) then
     call stderr2_int("deallocation failed", 1, ierr)
     call die("dsf_xyztfb_w: deallocation failed w")
  endif

  DEBUG2S("End: dsf_xyztfb_w")
  TIMING_STOP(timing_bin_dsf_xyztfb_w)

end

!-------------------------------------------------------------------------------
subroutine dsf_xyztfb_bb_w(w_add, u, s, a, b, at, bt, e, dm)
  use module_p_interface
  use module_action
!!  use module_nn
  use module_vol
  use module_dd
  implicit none

  GAUGE_FIELD,     intent(in)    :: u
  COMPLEX, dimension (4,3,ld%lat%volh, 0:ld%lat%num_ip-1):: a,b,at,bt
  REAL,            intent(in)    :: s
  integer,         intent(in)    :: e, dm
  GAUGE_FIELD,     intent(inout) :: w_add
  COMPLEX, allocatable :: w(:, :, :, :, :)
  SU3     :: v
  integer :: i, eo, mu, o, ierr

  if (s == ZERO) return

  TIMING_START(timing_bin_dsf_xyztfb_w)
  DEBUG2S("Start: dsf_xyztfb_w")

!!  ALLOCATE_G_FIELD(w)
  allocate(w(NCOL, NCOL, volh_tot, EVEN:ODD, DIM), STAT = ierr)
  if (ierr /= 0) then
     call stderr2_int("allocation failed", 1, ierr)
     call die("dsf_xyztfb_w: allocation failed w")
  endif

  o = 1 - e
#ifdef GAMMA_NOTATION_CHROMA
  call dsf_f_dcmp_1_p_gamma1_eo(w(1,1,1,e,1), b, at, e, dm)
  call dsf_f_dcmp_1_p_gamma1_eo(w(1,1,1,o,1), bt, a, o, dm)
  call dsf_f_dcmp_1_m_gamma2_eo(w(1,1,1,e,2), b, at, e, dm)
  call dsf_f_dcmp_1_m_gamma2_eo(w(1,1,1,o,2), bt, a, o, dm)
  call dsf_f_dcmp_1_p_gamma3_eo(w(1,1,1,e,3), b, at, e, dm)
  call dsf_f_dcmp_1_p_gamma3_eo(w(1,1,1,o,3), bt, a, o, dm)
  call dsf_f_dcmp_1_m_gammac_eo(w(1,1,1,e,4), b, at, e, dm)
  call dsf_f_dcmp_1_m_gammac_eo(w(1,1,1,o,4), bt, a, o, dm)
#elif defined GAMMA_NOTATION_CHIRAL
  call dsf_f_dcmp_1_m_gamma1_eo(w(1,1,1,e,1), b, at, e, dm)
  call dsf_f_dcmp_1_m_gamma1_eo(w(1,1,1,o,1), bt, a, o, dm)
  call dsf_f_dcmp_1_m_gamma2_eo(w(1,1,1,e,2), b, at, e, dm)
  call dsf_f_dcmp_1_m_gamma2_eo(w(1,1,1,o,2), bt, a, o, dm)
  call dsf_f_dcmp_1_m_gamma3_eo(w(1,1,1,e,3), b, at, e, dm)
  call dsf_f_dcmp_1_m_gamma3_eo(w(1,1,1,o,3), bt, a, o, dm)
  call dsf_f_dcmp_1_m_gammac_eo(w(1,1,1,e,4), b, at, e, dm)
  call dsf_f_dcmp_1_m_gammac_eo(w(1,1,1,o,4), bt, a, o, dm)
#elif defined GAMMA_NOTATION_DDHMC
  call dsf_f_dcmp_1_m_gamma1_eo(w(1,1,1,e,1), b, at, e, dm)
  call dsf_f_dcmp_1_m_gamma1_eo(w(1,1,1,o,1), bt, a, o, dm)
  call dsf_f_dcmp_1_m_gamma2_eo(w(1,1,1,e,2), b, at, e, dm)
  call dsf_f_dcmp_1_m_gamma2_eo(w(1,1,1,o,2), bt, a, o, dm)
  call dsf_f_dcmp_1_m_gamma3_eo(w(1,1,1,e,3), b, at, e, dm)
  call dsf_f_dcmp_1_m_gamma3_eo(w(1,1,1,o,3), bt, a, o, dm)
  call dsf_f_dcmp_1_p_gammac_eo(w(1,1,1,e,4), b, at, e, dm)
  call dsf_f_dcmp_1_p_gammac_eo(w(1,1,1,o,4), bt, a, o, dm)
#elif defined GAMMA_NOTATION_BQCD
  call dsf_f_dcmp_1_p_gamma1_eo(w(1,1,1,e,1), b, at, e, dm)
  call dsf_f_dcmp_1_p_gamma1_eo(w(1,1,1,o,1), bt, a, o, dm)
  call dsf_f_dcmp_1_p_gamma2_eo(w(1,1,1,e,2), b, at, e, dm)
  call dsf_f_dcmp_1_p_gamma2_eo(w(1,1,1,o,2), bt, a, o, dm)
  call dsf_f_dcmp_1_p_gamma3_eo(w(1,1,1,e,3), b, at, e, dm)
  call dsf_f_dcmp_1_p_gamma3_eo(w(1,1,1,o,3), bt, a, o, dm)
  call dsf_f_dcmp_1_m_gamman_eo(w(1,1,1,e,4), b, at, e, dm)
  call dsf_f_dcmp_1_m_gamman_eo(w(1,1,1,o,4), bt, a, o, dm)
#endif

  call flip_bc(w)
  do mu = 1, DIM
     do eo = EVEN, ODD
        !$omp parallel do
        do i = 1, volh
           call u_scale(w(1, 1, i, eo, mu), s)
           call u_add(w_add(1, 1, i, eo, mu), w(1, 1, i, eo, mu))
        enddo
     enddo
  enddo

#ifdef GAMMA_NOTATION_CHROMA
  call dsf_b_dcmp_1_m_gamma1_eo(w(1,1,1,e,1), bt, a, e, dm)
  call dsf_b_dcmp_1_m_gamma1_eo(w(1,1,1,o,1), b, at, o, dm)
  call dsf_b_dcmp_1_p_gamma2_eo(w(1,1,1,e,2), bt, a, e, dm)
  call dsf_b_dcmp_1_p_gamma2_eo(w(1,1,1,o,2), b, at, o, dm)
  call dsf_b_dcmp_1_m_gamma3_eo(w(1,1,1,e,3), bt, a, e, dm)
  call dsf_b_dcmp_1_m_gamma3_eo(w(1,1,1,o,3), b, at, o, dm)
  call dsf_b_dcmp_1_p_gammac_eo(w(1,1,1,e,4), bt, a, e, dm)
  call dsf_b_dcmp_1_p_gammac_eo(w(1,1,1,o,4), b, at, o, dm)
#elif defined GAMMA_NOTATION_CHIRAL
  call dsf_b_dcmp_1_p_gamma1_eo(w(1,1,1,e,1), bt, a, e, dm)
  call dsf_b_dcmp_1_p_gamma1_eo(w(1,1,1,o,1), b, at, o, dm)
  call dsf_b_dcmp_1_p_gamma2_eo(w(1,1,1,e,2), bt, a, e, dm)
  call dsf_b_dcmp_1_p_gamma2_eo(w(1,1,1,o,2), b, at, o, dm)
  call dsf_b_dcmp_1_p_gamma3_eo(w(1,1,1,e,3), bt, a, e, dm)
  call dsf_b_dcmp_1_p_gamma3_eo(w(1,1,1,o,3), b, at, o, dm)
  call dsf_b_dcmp_1_p_gammac_eo(w(1,1,1,e,4), bt, a, e, dm)
  call dsf_b_dcmp_1_p_gammac_eo(w(1,1,1,o,4), b, at, o, dm)
#elif defined GAMMA_NOTATION_DDHMC
  call dsf_b_dcmp_1_p_gamma1_eo(w(1,1,1,e,1), bt, a, e, dm)
  call dsf_b_dcmp_1_p_gamma1_eo(w(1,1,1,o,1), b, at, o, dm)
  call dsf_b_dcmp_1_p_gamma2_eo(w(1,1,1,e,2), bt, a, e, dm)
  call dsf_b_dcmp_1_p_gamma2_eo(w(1,1,1,o,2), b, at, o, dm)
  call dsf_b_dcmp_1_p_gamma3_eo(w(1,1,1,e,3), bt, a, e, dm)
  call dsf_b_dcmp_1_p_gamma3_eo(w(1,1,1,o,3), b, at, o, dm)
  call dsf_b_dcmp_1_m_gammac_eo(w(1,1,1,e,4), bt, a, e, dm)
  call dsf_b_dcmp_1_m_gammac_eo(w(1,1,1,o,4), b, at, o, dm)
#elif defined GAMMA_NOTATION_BQCD
  call dsf_b_dcmp_1_m_gamma1_eo(w(1,1,1,e,1), bt, a, e, dm)
  call dsf_b_dcmp_1_m_gamma1_eo(w(1,1,1,o,1), b, at, o, dm)
  call dsf_b_dcmp_1_m_gamma2_eo(w(1,1,1,e,2), bt, a, e, dm)
  call dsf_b_dcmp_1_m_gamma2_eo(w(1,1,1,o,2), b, at, o, dm)
  call dsf_b_dcmp_1_m_gamma3_eo(w(1,1,1,e,3), bt, a, e, dm)
  call dsf_b_dcmp_1_m_gamma3_eo(w(1,1,1,o,3), b, at, o, dm)
  call dsf_b_dcmp_1_p_gamman_eo(w(1,1,1,e,4), bt, a, e, dm)
  call dsf_b_dcmp_1_p_gamman_eo(w(1,1,1,o,4), b, at, o, dm)
#endif

  do mu = 1, DIM
     do eo = EVEN, ODD
        !$omp parallel do private(v)
        do i = 1, volh
           call uud(v, w(1, 1, i, eo, mu), u(1, 1, i, eo, mu))
           call udu(w(1, 1, i, eo, mu), u(1, 1, i, eo, mu), v)
        enddo
     enddo
  enddo

  call flip_bc(w)

  do mu = 1, DIM
     do eo = EVEN, ODD
        !$omp parallel do
        do i = 1, volh
           call u_scale(w(1, 1, i, eo, mu), -s)
           call u_add(w_add(1, 1, i, eo, mu), w(1, 1, i, eo, mu))
        enddo
     enddo
  enddo

  deallocate(w, STAT = ierr)
  if (ierr /= 0) then
     call stderr2_int("deallocation failed", 1, ierr)
     call die("dsf_xyztfb_w: deallocation failed w")
  endif

  DEBUG2S("End: dsf_xyztfb_w")
  TIMING_STOP(timing_bin_dsf_xyztfb_w)

end

!-------------------------------------------------------------------------------
subroutine clover_bsa_dd_w(w_add, s, ddb, dda, eo, dm)
  use module_action
  use module_vol
  use module_dd
  use module_function_decl
  implicit none
  GAUGE_FIELD,     intent(inout) :: w_add
  COMPLEX, dimension (4,3,ld%lat%volh, 0:ld%lat%num_ip-1), intent(in):: ddb, dda
  REAL,    intent(in) :: s
  integer, intent(in) :: eo, dm
  integer             :: i, mu, col, di, dp
  COMPLEX, dimension (4,3,volh_tot):: a,b

  if (s == ZERO) return
  a=0
  b=0

  do i = 1, volh
     di = ddi( i,eo)
     dp = ddip(i,eo)
     if (dm == 2 .or.  eo_dm(dp) == dm) then
        do col = 1, NCOL
        do mu = 1, DIM
           a(mu,col,i)=dda(mu,col,di,dp)
        enddo
        enddo
     else
        do col = 1, NCOL
        do mu = 1, DIM
           a(mu,col,i)=ZERO
        enddo
        enddo
     endif
  enddo
  do i = 1, volh
     di = ddi( i,eo)
     dp = ddip(i,eo)
     if (dm == 2 .or.  eo_dm(dp) == dm) then
        do col = 1, NCOL
        do mu = 1, DIM
           b(mu,col,i)=ddb(mu,col,di,dp)
        enddo
        enddo
     else
        do col = 1, NCOL
        do mu = 1, DIM
           b(mu,col,i)=ZERO
        enddo
        enddo
     endif
  enddo
  call xbound_sc_field(a)
  call xbound_sc_field(b)
call clover_bsa_w(w_add, s, b, a)
  call sc_zero_halo(a)
  call sc_zero_halo(b)
end

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