/*****************  grow4wvecs.c  (in su3.a) ****************************
*									*
*  If sum=0,								*
*  Grow and add four wilson_vectors 					*
*  If sum=1,								*
*  Grow and sum four wilson_vectors to another wilson_vector		*
* void grow_four_wvecs(a,b1,b2,b3,b4,sign,sum)				*
* wilson_vector *a; half_wilson_vector *b1,*b2,*b3,*b4;			*
* int sign,sum;								*
* A  <-  B1 + B2 + B3 + B4   or						*
* A  <-  A + B1 + B2 + B3 + B4						*
* B1 is expanded using gamma_x, B2 using gamma_y, etc. 			*
*/
#include "../include/config.h"
#include "../include/complex.h"
#include "../include/su3.h"
#include "../include/dirs.h"
#include "../include/macros.h"

extern __targetConst__ int t_sites_on_node;

__targetHost__ __target__ void grow_add_four_wvecs( wilson_vector * a, half_wilson_vector * b1,
			  half_wilson_vector * b2, half_wilson_vector * b3, half_wilson_vector * b4, int sign, int sum )
{
    int i;
    if( sum == 0 )
    {
	/* wp_grow( b1,a,XUP,sign); */

	/* case XUP: */
	if( sign == PLUS )
	{
	    for ( i = 0; i < 3; i++ )
	    {
		a->COLORSPINOR( i, 0 ) = b1->h[0].c[i];
		a->COLORSPINOR( i, 1 ) = b1->h[1].c[i];
		TIMESMINUSI( b1->h[0].c[i], a->COLORSPINOR( i, 3 ) );
		TIMESMINUSI( b1->h[1].c[i], a->COLORSPINOR( i, 2 ) );
	    }
	}
	else
	{
	    /* case XDOWN: */
	    for ( i = 0; i < 3; i++ )
	    {
		a->COLORSPINOR( i, 0 ) = b1->h[0].c[i];
		a->COLORSPINOR( i, 1 ) = b1->h[1].c[i];
		TIMESPLUSI( b1->h[0].c[i], a->COLORSPINOR( i, 3 ) );
		TIMESPLUSI( b1->h[1].c[i], a->COLORSPINOR( i, 2 ) );
	    }
	}
    }
    else
    {
	/* wp_grow_add( b1,a,XUP,sign); */

	/* case XUP: */
	if( sign == PLUS )
	{
	    for ( i = 0; i < 3; i++ )
	    {
		CSUM( a->COLORSPINOR( i, 0 ), b1->h[0].c[i] );
		CSUM( a->COLORSPINOR( i, 1 ), b1->h[1].c[i] );
		CSUM_TMI( a->COLORSPINOR( i, 2 ), b1->h[1].c[i] );
		CSUM_TMI( a->COLORSPINOR( i, 3 ), b1->h[0].c[i] );
	    }
	}
	else
	{
	    /* case XDOWN: */
	    for ( i = 0; i < 3; i++ )
	    {
		CSUM( a->COLORSPINOR( i, 0 ), b1->h[0].c[i] );
		CSUM( a->COLORSPINOR( i, 1 ), b1->h[1].c[i] );
		CSUM_TPI( a->COLORSPINOR( i, 2 ), b1->h[1].c[i] );
		CSUM_TPI( a->COLORSPINOR( i, 3 ), b1->h[0].c[i] );
	    }
	}
    }

    /* wp_grow_add( b2,a,YUP,sign); */

    if( sign == PLUS )
    {
	/*  case YUP: */
	for ( i = 0; i < 3; i++ )
	{
	    CSUM( a->COLORSPINOR( i, 0 ), b2->h[0].c[i] );
	    CSUM( a->COLORSPINOR( i, 1 ), b2->h[1].c[i] );
	    CSUM( a->COLORSPINOR( i, 2 ), b2->h[1].c[i] );
	    CSUB( a->COLORSPINOR( i, 3 ), b2->h[0].c[i], a->COLORSPINOR( i, 3 ) );
	}
    }
    else
    {
	/*  case YDOWN: */
	for ( i = 0; i < 3; i++ )
	{
	    CSUM( a->COLORSPINOR( i, 0 ), b2->h[0].c[i] );
	    CSUM( a->COLORSPINOR( i, 1 ), b2->h[1].c[i] );
	    CSUB( a->COLORSPINOR( i, 2 ), b2->h[1].c[i], a->COLORSPINOR( i, 2 ) );
	    CSUM( a->COLORSPINOR( i, 3 ), b2->h[0].c[i] );
	}
    }

    /*  wp_grow_add( b3,a,ZUP,sign); */

    if( sign == PLUS )
    {
	/*  case ZUP: */
	for ( i = 0; i < 3; i++ )
	{
	    CSUM( a->COLORSPINOR( i, 0 ), b3->h[0].c[i] );
	    CSUM( a->COLORSPINOR( i, 1 ), b3->h[1].c[i] );
	    CSUM_TMI( a->COLORSPINOR( i, 2 ), b3->h[0].c[i] );
	    CSUM_TPI( a->COLORSPINOR( i, 3 ), b3->h[1].c[i] );
	}
    }
    else
    {
	/*  case ZDOWN: */
	for ( i = 0; i < 3; i++ )
	{
	    CSUM( a->COLORSPINOR( i, 0 ), b3->h[0].c[i] );
	    CSUM( a->COLORSPINOR( i, 1 ), b3->h[1].c[i] );
	    CSUM_TPI( a->COLORSPINOR( i, 2 ), b3->h[0].c[i] );
	    CSUM_TMI( a->COLORSPINOR( i, 3 ), b3->h[1].c[i] );
	}
    }

    /*  wp_grow_add( b4,a,TUP,sign); */

    if( sign == PLUS )
    {
	/*  case TUP: */
	for ( i = 0; i < 3; i++ )
	{
	    CSUM( a->COLORSPINOR( i, 0 ), b4->h[0].c[i] );
	    CSUM( a->COLORSPINOR( i, 1 ), b4->h[1].c[i] );
	    CSUM( a->COLORSPINOR( i, 2 ), b4->h[0].c[i] );
	    CSUM( a->COLORSPINOR( i, 3 ), b4->h[1].c[i] );
	}
    }
    else
    {
	/*  case TDOWN: */
	for ( i = 0; i < 3; i++ )
	{
	    CSUM( a->COLORSPINOR( i, 0 ), b4->h[0].c[i] );
	    CSUM( a->COLORSPINOR( i, 1 ), b4->h[1].c[i] );
	    CSUB( a->COLORSPINOR( i, 2 ), b4->h[0].c[i], a->COLORSPINOR( i, 2 ) );
	    CSUB( a->COLORSPINOR( i, 3 ), b4->h[1].c[i], a->COLORSPINOR( i, 3 ) );
	}
    }


}

// version of the above ported to targetDP
__target__ void grow_add_four_wvecs_tdp( double * a,  double* b1,
					 double* b2, double* b3, double* b4, int isite,int sign, int sum )
{
  int i;
  int iv=0;




    for ( i = 0; i < 3; i++ )
      {


	double a0re[VVL];
	double a0im[VVL];
	
	double a1re[VVL];
	double a1im[VVL];
	
	double a2re[VVL];
	double a2im[VVL];
	
	double a3re[VVL];
	double a3im[VVL];

	__targetILP__(iv) {
	  a0re[iv]=0.;
	  a0im[iv]=0.;
	  a1re[iv]=0.;
	  a1im[iv]=0.;
	  a2re[iv]=0.;
	  a2im[iv]=0.;
	  a3re[iv]=0.;
	  a3im[iv]=0.;

	}
	
	
	if( sum == 0 )
	  {
	    /* wp_grow( b1,a,XUP,sign); */
	    
	    /* case XUP: */
	    if( sign == PLUS )
	      {
		
		__targetILP__(iv) a0re[iv]= b1[HWVI(isite+iv,i,0,REPART)];
		__targetILP__(iv) a0im[iv]= b1[HWVI(isite+iv,i,0,IMPART)];
		
		__targetILP__(iv) a1re[iv]= b1[HWVI(isite+iv,i,1,REPART)];
		__targetILP__(iv) a1im[iv]= b1[HWVI(isite+iv,i,1,IMPART)];
		
		__targetILP__(iv) a3re[iv]=b1[HWVI(isite+iv,i,0,IMPART)];
		__targetILP__(iv) a3im[iv]=-b1[HWVI(isite+iv,i,0,REPART)];
		
		__targetILP__(iv) a2re[iv]=b1[HWVI(isite+iv,i,1,IMPART)];
		__targetILP__(iv) a2im[iv]=-b1[HWVI(isite+iv,i,1,REPART)];
		
	      }
	    else
	      {
		/* case XDOWN: */
		
		__targetILP__(iv) a0re[iv]= b1[HWVI(isite+iv,i,0,REPART)];
		__targetILP__(iv) a0im[iv]= b1[HWVI(isite+iv,i,0,IMPART)];
		
		__targetILP__(iv) a1re[iv]= b1[HWVI(isite+iv,i,1,REPART)];
		__targetILP__(iv) a1im[iv]= b1[HWVI(isite+iv,i,1,IMPART)];
		
		__targetILP__(iv) a3re[iv]=-b1[HWVI(isite+iv,i,0,IMPART)];
		__targetILP__(iv) a3im[iv]=b1[HWVI(isite+iv,i,0,REPART)];
		
		__targetILP__(iv) a2re[iv]=-b1[HWVI(isite+iv,i,1,IMPART)];
		__targetILP__(iv) a2im[iv]=b1[HWVI(isite+iv,i,1,REPART)];
		
		
	      }
	  }
	else
	  {
	    
	    
	    //read a
	    __targetILP__(iv) a0re[iv]=a[WVI(isite+iv,i,0,REPART)];
	    __targetILP__(iv) a0im[iv]=a[WVI(isite+iv,i,0,IMPART)];
	    __targetILP__(iv) a1re[iv]=a[WVI(isite+iv,i,1,REPART)];
	    __targetILP__(iv) a1im[iv]=a[WVI(isite+iv,i,1,IMPART)];
	    __targetILP__(iv) a2re[iv]=a[WVI(isite+iv,i,2,REPART)];
	    __targetILP__(iv) a2im[iv]=a[WVI(isite+iv,i,2,IMPART)];
	    __targetILP__(iv) a3re[iv]=a[WVI(isite+iv,i,3,REPART)];
	    __targetILP__(iv) a3im[iv]=a[WVI(isite+iv,i,3,IMPART)];
	    
	    
	    
	    /* wp_grow_add( b1,a,XUP,sign); */
	    
	    /* case XUP: */
	    if( sign == PLUS )
	      {
		
		__targetILP__(iv) a0re[iv]+=b1[HWVI(isite+iv,i,0,REPART)];
		__targetILP__(iv)a0im[iv]+=b1[HWVI(isite+iv,i,0,IMPART)];
		
		__targetILP__(iv) a1re[iv]+=b1[HWVI(isite+iv,i,1,REPART)];
		__targetILP__(iv) a1im[iv]+=b1[HWVI(isite+iv,i,1,IMPART)];
		
		__targetILP__(iv) a2re[iv]+=b1[HWVI(isite+iv,i,1,IMPART)];
		__targetILP__(iv) a2im[iv]-=b1[HWVI(isite+iv,i,1,REPART)];
		
		__targetILP__(iv) a3re[iv]+=b1[HWVI(isite+iv,i,0,IMPART)];
		__targetILP__(iv) a3im[iv]-=b1[HWVI(isite+iv,i,0,REPART)];
		
		
	      }
	    else
	      {
		/* case XDOWN: */
		
		__targetILP__(iv) a0re[iv]+=b1[HWVI(isite+iv,i,0,REPART)];
		__targetILP__(iv) a0im[iv]+=b1[HWVI(isite+iv,i,0,IMPART)];
		
		__targetILP__(iv) a1re[iv]+=b1[HWVI(isite+iv,i,1,REPART)];
		__targetILP__(iv) a1im[iv]+=b1[HWVI(isite+iv,i,1,IMPART)];
		
		__targetILP__(iv) a2re[iv]-=b1[HWVI(isite+iv,i,1,IMPART)];
		__targetILP__(iv) a2im[iv]+=b1[HWVI(isite+iv,i,1,REPART)];
		
		__targetILP__(iv) a3re[iv]-=b1[HWVI(isite+iv,i,0,IMPART)];
		__targetILP__(iv) a3im[iv]+=b1[HWVI(isite+iv,i,0,REPART)];
		
		
		
	      }
	  }
	
	/* wp_grow_add( b2,a,YUP,sign); */
	
	if( sign == PLUS )
	  {
	    /*  case YUP: */
	    
	    __targetILP__(iv) a0re[iv]+=b2[HWVI(isite+iv,i,0,REPART)];
	    __targetILP__(iv) a0im[iv]+=b2[HWVI(isite+iv,i,0,IMPART)];
	    
	    __targetILP__(iv) a1re[iv]+=b2[HWVI(isite+iv,i,1,REPART)];
	    __targetILP__(iv) a1im[iv]+=b2[HWVI(isite+iv,i,1,IMPART)];
	    
	    __targetILP__(iv) a2re[iv]+=b2[HWVI(isite+iv,i,1,REPART)];
	    __targetILP__(iv) a2im[iv]+=b2[HWVI(isite+iv,i,1,IMPART)];
	    
	    __targetILP__(iv) a3re[iv]-= b2[HWVI(isite+iv,i,0,REPART)];
	    __targetILP__(iv) a3im[iv]-= b2[HWVI(isite+iv,i,0,IMPART)];
	    
	    
	  }
	else
	  {
	    /*  case YDOWN: */
	    
	    __targetILP__(iv) a0re[iv]+=b2[HWVI(isite+iv,i,0,REPART)];
	    __targetILP__(iv) a0im[iv]+=b2[HWVI(isite+iv,i,0,IMPART)];
	    
	    __targetILP__(iv) a1re[iv]+=b2[HWVI(isite+iv,i,1,REPART)];
	    __targetILP__(iv) a1im[iv]+=b2[HWVI(isite+iv,i,1,IMPART)];
	    
	    __targetILP__(iv) a2re[iv]-=  b2[HWVI(isite+iv,i,1,REPART)];
	    __targetILP__(iv) a2im[iv]-=  b2[HWVI(isite+iv,i,1,IMPART)];
	    
	    __targetILP__(iv) a3re[iv]+=b2[HWVI(isite+iv,i,0,REPART)];
	    __targetILP__(iv) a3im[iv]+=b2[HWVI(isite+iv,i,0,IMPART)];
	    
	  }
	
	/*  wp_grow_add( b3,a,ZUP,sign); */
	
	if( sign == PLUS )
	  {
	    /*  case ZUP: */
	    
	    __targetILP__(iv) a0re[iv]+=b3[HWVI(isite+iv,i,0,REPART)];
	    __targetILP__(iv) a0im[iv]+=b3[HWVI(isite+iv,i,0,IMPART)];
	    
	    __targetILP__(iv) a1re[iv]+=b3[HWVI(isite+iv,i,1,REPART)];
	    __targetILP__(iv) a1im[iv]+=b3[HWVI(isite+iv,i,1,IMPART)];
	    
	    __targetILP__(iv) a2re[iv]+=b3[HWVI(isite+iv,i,0,IMPART)];
	    __targetILP__(iv) a2im[iv]-=b3[HWVI(isite+iv,i,0,REPART)];
	    
	    __targetILP__(iv) a3re[iv]-=b3[HWVI(isite+iv,i,1,IMPART)];
	    __targetILP__(iv) a3im[iv]+=b3[HWVI(isite+iv,i,1,REPART)];
	    
	  }
	else
	  {
	    /*  case ZDOWN: */
	    
	    __targetILP__(iv) a0re[iv]+=b3[HWVI(isite+iv,i,0,REPART)];
	    __targetILP__(iv) a0im[iv]+=b3[HWVI(isite+iv,i,0,IMPART)];
	    
	    __targetILP__(iv) a1re[iv]+=b3[HWVI(isite+iv,i,1,REPART)];
	    __targetILP__(iv) a1im[iv]+=b3[HWVI(isite+iv,i,1,IMPART)];
	    
	    __targetILP__(iv) a2re[iv]-=b3[HWVI(isite+iv,i,0,IMPART)];
	    __targetILP__(iv) a2im[iv]+=b3[HWVI(isite+iv,i,0,REPART)];
	    
	    __targetILP__(iv) a3re[iv]+=b3[HWVI(isite+iv,i,1,IMPART)];
	    __targetILP__(iv) a3im[iv]-=b3[HWVI(isite+iv,i,1,REPART)];
	    
	    
	  }
	
	/*  wp_grow_add( b4,a,TUP,sign); */
	
	if( sign == PLUS )
	  {
	    /*  case TUP: */
	    
	    __targetILP__(iv) a0re[iv]+=b4[HWVI(isite+iv,i,0,REPART)];
	    __targetILP__(iv) a0im[iv]+=b4[HWVI(isite+iv,i,0,IMPART)];
	    
	    __targetILP__(iv) a1re[iv]+=b4[HWVI(isite+iv,i,1,REPART)];
	    __targetILP__(iv) a1im[iv]+=b4[HWVI(isite+iv,i,1,IMPART)];
	    
	    __targetILP__(iv) a2re[iv]+=b4[HWVI(isite+iv,i,0,REPART)];
	    __targetILP__(iv) a2im[iv]+=b4[HWVI(isite+iv,i,0,IMPART)];
	    
	    __targetILP__(iv) a3re[iv]+=b4[HWVI(isite+iv,i,1,REPART)];
	    __targetILP__(iv) a3im[iv]+=b4[HWVI(isite+iv,i,1,IMPART)];
	    
	    
	  }
	else
	  {
	    /*  case TDOWN: */
	    
	    __targetILP__(iv) a0re[iv]+=b4[HWVI(isite+iv,i,0,REPART)];
	    __targetILP__(iv) a0im[iv]+=b4[HWVI(isite+iv,i,0,IMPART)];
	    
	    __targetILP__(iv) a1re[iv]+=b4[HWVI(isite+iv,i,1,REPART)];
	    __targetILP__(iv) a1im[iv]+=b4[HWVI(isite+iv,i,1,IMPART)];
	    
	    __targetILP__(iv) a2re[iv]-= b4[HWVI(isite+iv,i,0,REPART)];
	    __targetILP__(iv) a2im[iv]-= b4[HWVI(isite+iv,i,0,IMPART)];
	    
	    __targetILP__(iv) a3re[iv]-= b4[HWVI(isite+iv,i,1,REPART)];
	    __targetILP__(iv) a3im[iv]-= b4[HWVI(isite+iv,i,1,IMPART)];
	    
	  }
	
	
	//write back 
	__targetILP__(iv) a[WVI(isite+iv,i,0,REPART)]=a0re[iv];
	__targetILP__(iv) a[WVI(isite+iv,i,0,IMPART)]=a0im[iv];
	__targetILP__(iv) a[WVI(isite+iv,i,1,REPART)]=a1re[iv];
	__targetILP__(iv) a[WVI(isite+iv,i,1,IMPART)]=a1im[iv];
	__targetILP__(iv) a[WVI(isite+iv,i,2,REPART)]=a2re[iv];
	__targetILP__(iv) a[WVI(isite+iv,i,2,IMPART)]=a2im[iv];
	__targetILP__(iv) a[WVI(isite+iv,i,3,REPART)]=a3re[iv];
	__targetILP__(iv) a[WVI(isite+iv,i,3,IMPART)]=a3im[iv];
	




      }
}



void grow_add_four_wvecs_hch( wilson_vector * a, half_wilson_vector * b1,
			      half_wilson_vector * b2, half_wilson_vector * b3, half_wilson_vector * b4, int sign, int sum )
{

    if( sum == 0 )
    {
	wp_grow_hch( b1, a, XUP, sign );

    }
    else
    {
	wp_grow_add_hch( b1, a, XUP, sign );

    }

    wp_grow_add_hch( b2, a, YUP, sign );

    wp_grow_add_hch( b3, a, ZUP, sign );

    wp_grow_add_hch( b4, a, TUP, sign );


}
