/*********************************************************
 * Generic gauge link smoothing routine
 * Kari Rummukainen 1998-2002
 */

/* d1 are the directions of the links to be smeared, d2 are the
 * orthogonal smearing directions
 */

void smooth_link_MATRIX(MATRIX *link[NDIM],  int d1[NDIM], int d2[NDIM],
			double c_mul_0, double c_mul_1)
{
  int i,dir1,dir2,odir;
  MATRIX *newl[NDIM], *staple, tm1, tm2;
  msg_tag *tag1,*tag2;

  staple = tmp_latfield( MATRIX );
  foralldir(dir1) if (d1[dir1]) {
    
    newl[dir1] = tmp_latfield( MATRIX );

    forallsites(i) zero_MATRIX( staple[i] );

    foralldir(dir2) if (d2[dir2] && dir2 != dir1) {
      
      odir = opp_dir(dir2);

      /* get links from up-directions */
      tag1 = start_get( link[dir2], dir1, EVENODD );
      tag2 = start_get( link[dir1], dir2, EVENODD );

      forallsites_wait(i,tag1) {
	/* multiply bottom bracket */
	mult_MATRIX_an( link[dir2][i], link[dir1][i], tm1 );
	mult_MATRIX_nn( tm1, link[dir2][nb(dir1,i)], newl[dir1][i] );
      }
      /* and move up */
      tag1 = start_get( newl[dir1], odir, EVENODD );
      
      /* and sum staples */
      forallsites_wait2(i,tag2,tag1) {
	mult_MATRIX_nn( link[dir2][i], link[dir1][nb(dir2,i)], tm1 );
	mult_MATRIX_na( tm1, link[dir2][nb(dir1,i)], tm2 );

	add_MATRIX( tm2, staple[i], staple[i] );
	add_MATRIX( staple[i], newl[dir1][nb(odir,i)], staple[i] );
      }
    }

    forallsites(i) {
      scalar_mul_MATRIX( staple[i], c_mul_1, staple[i] );
      scalar_mul_MATRIX( link[dir1][i], c_mul_0, newl[dir1][i] );
      add_MATRIX( newl[dir1][i], staple[i], newl[dir1][i] );
    }

  }

  foralldir(dir1) if (d1[dir1]) {
    forallsites(i) link[dir1][i] = newl[dir1][i];
    free_tmp( newl[dir1] );
  }
  
  free_tmp( staple );
}
