
/*******************************************************************************
*
* File blk_solv.c
*
* Copyright (C) 2005 Martin Luescher
*
* This software is distributed under the terms of the GNU General Public
* License (GPL)
*
* Fast single-precision block solver for Dhat*psi=eta
*
* The externally accessible functions is
*
*   void blk_mres(block_t *b,int nmr)
*     Approximate solution of the equation Dhat*b.s[0]=b.s[1] for given
*     source b.s[1]. The solution is obtained by applying nmr minimal
*     residual steps using b.s[2] and b.s[1] as workspace. On output the
*     latter contains the residual vector of the solution
*
* Notes:
*
* This program acts locally on the specified block. It is taken for granted
* that at least 3 single-precision spinor fields are allocated on the block
* and that the gauge and sw fields are in the proper condition for the
* application of Qhat
*
*******************************************************************************/

#define BLK_SOLV_C

#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <float.h>
#include "su3.h"
#include "start.h"
#include "linalg.h"
#include "block.h"
#include "dirac.h"

#if (defined SSE)
#include "sse.h"

#if (defined SSE3)

static sse_float tmp1,tmp2;


static void scalar_prods(int nsp,spinor *psr,spinor *psar,
                         float *rn,complex *z)
{
   double x,y,r;
   spinor *psm;

   x=0.0;
   y=0.0;
   r=0.0;
   psm=psr+nsp;

   for (;psr<psm;)
   {
      __asm__ __volatile__ ("movaps %0, %%xmm0 \n\t"
                            "movaps %1, %%xmm2 \n\t"
                            "movsldup %2, %%xmm3 \n\t"
                            "movsldup %3, %%xmm4 \n\t"
                            "movshdup %2, %%xmm5 \n\t"
                            "movshdup %3, %%xmm7"
                            :
                            :
                            "m" ((*psar).c1.c1),
                            "m" ((*psar).c1.c3),
                            "m" ((*psr).c1.c1),
                            "m" ((*psr).c1.c3)
                            :
                            "xmm0", "xmm2", "xmm3", "xmm4", "xmm5", "xmm7");
                            
      psar+=4;
      _prefetch_spinor(psar);
      psar-=4;

      __asm__ __volatile__ ("mulps %%xmm0, %%xmm3 \n\t"
                            "mulps %%xmm2, %%xmm4 \n\t"
                            "mulps %%xmm0, %%xmm5 \n\t"
                            "mulps %%xmm2, %%xmm7 \n\t"
                            "shufps $0xb1, %%xmm3, %%xmm3 \n\t"
                            "shufps $0xb1, %%xmm4, %%xmm4 \n\t"
                            "mulps %%xmm0, %%xmm0 \n\t"
                            "mulps %%xmm2, %%xmm2 \n\t"
                            "addsubps %%xmm3, %%xmm5 \n\t"
                            "addsubps %%xmm4, %%xmm7 \n\t"
                            "addps %%xmm0, %%xmm2 \n\t"
                            "addps %%xmm5, %%xmm7"
                            :
                            :
                            :
                            "xmm0", "xmm2", "xmm3", "xmm4", "xmm5", "xmm7");

      __asm__ __volatile__ ("movaps %0, %%xmm0 \n\t"
                            "movaps %1, %%xmm1 \n\t"
                            "movsldup %2, %%xmm3 \n\t"
                            "movsldup %3, %%xmm4 \n\t"
                            "movshdup %2, %%xmm5 \n\t"
                            "movshdup %3, %%xmm6"
                            :
                            :
                            "m" ((*psar).c2.c2),
                            "m" ((*psar).c3.c1),
                            "m" ((*psr).c2.c2),
                            "m" ((*psr).c3.c1)
                            :
                            "xmm0", "xmm1", "xmm3", "xmm4", "xmm5", "xmm6");

      psr+=4;
      _prefetch_spinor(psr);
      psr-=4;
      
      __asm__ __volatile__ ("mulps %%xmm0, %%xmm3 \n\t"
                            "mulps %%xmm1, %%xmm4 \n\t"
                            "mulps %%xmm0, %%xmm5 \n\t"
                            "mulps %%xmm1, %%xmm6 \n\t"
                            "shufps $0xb1, %%xmm3, %%xmm3 \n\t"
                            "shufps $0xb1, %%xmm4, %%xmm4 \n\t"
                            "mulps %%xmm0, %%xmm0 \n\t"
                            "mulps %%xmm1, %%xmm1 \n\t"
                            "addsubps %%xmm3, %%xmm5 \n\t"
                            "addsubps %%xmm4, %%xmm6 \n\t"
                            "addps %%xmm0, %%xmm2 \n\t"
                            "addps %%xmm5, %%xmm7 \n\t"
                            "addps %%xmm1, %%xmm2 \n\t"
                            "subps %%xmm6, %%xmm7"
                            :
                            :
                            :
                            "xmm0", "xmm1", "xmm3", "xmm4",
                            "xmm5", "xmm6", "xmm7");
      
      __asm__ __volatile__ ("movaps %0, %%xmm0 \n\t"
                            "movaps %1, %%xmm1 \n\t"
                            "movsldup %2, %%xmm3 \n\t"
                            "movsldup %3, %%xmm4 \n\t"
                            "movshdup %2, %%xmm5 \n\t"
                            "movshdup %3, %%xmm6"
                            :
                            :
                            "m" ((*psar).c3.c3),
                            "m" ((*psar).c4.c2),
                            "m" ((*psr).c3.c3),
                            "m" ((*psr).c4.c2)
                            :
                            "xmm0", "xmm1", "xmm3", "xmm4", "xmm5", "xmm6");
                            
      __asm__ __volatile__ ("mulps %%xmm0, %%xmm3 \n\t"
                            "mulps %%xmm1, %%xmm4 \n\t"
                            "mulps %%xmm0, %%xmm5 \n\t"
                            "mulps %%xmm1, %%xmm6 \n\t"
                            "shufps $0xb1, %%xmm3, %%xmm3 \n\t"
                            "shufps $0xb1, %%xmm4, %%xmm4 \n\t"
                            "mulps %%xmm0, %%xmm0 \n\t"
                            "mulps %%xmm1, %%xmm1 \n\t"
                            "addsubps %%xmm3, %%xmm5 \n\t"
                            "addsubps %%xmm4, %%xmm6 \n\t"
                            "addps %%xmm0, %%xmm2 \n\t"
                            "subps %%xmm5, %%xmm7 \n\t"
                            "addps %%xmm1, %%xmm2 \n\t"
                            "subps %%xmm6, %%xmm7"
                            :
                            :
                            :
                            "xmm0", "xmm1", "xmm3", "xmm4",
                            "xmm5", "xmm6", "xmm7");

      __asm__ __volatile__ ("movaps %%xmm2, %0 \n\t"
                            "movaps %%xmm7, %1"
                            :
                            "=m" (tmp1),
                            "=m" (tmp2));

      r+=(double)(tmp1.c1+tmp1.c2+tmp1.c3+tmp1.c4);
      x+=(double)(tmp2.c2+tmp2.c4);
      y+=(double)(tmp2.c1+tmp2.c3);

      psr+=1;
      psar+=1;
   }

   (*rn)=(float)(r);
   (*z).re=(float)(x);
   (*z).im=(float)(y);
}

#else

static sse_float tmp1,tmp2,tmp3;


static void scalar_prods(int nsp,spinor *psr,spinor *psar,
                         float *rn,complex *z)
{
   double x,y,r;
   spinor *psm;

   x=0.0;
   y=0.0;
   r=0.0;

   psm=psr+nsp;
   
   for (;psr<psm;)
   {
      __asm__ __volatile__ ("movaps %0, %%xmm0 \n\t"
                            "movaps %1, %%xmm1 \n\t"
                            "movaps %2, %%xmm2 \n\t"
                            "movaps %3, %%xmm3 \n\t"
                            "movaps %4, %%xmm4 \n\t"
                            "movaps %5, %%xmm5"
                            :
                            :
                            "m" ((*psar).c1.c1),
                            "m" ((*psar).c1.c3),
                            "m" ((*psar).c2.c2),
                            "m" ((*psar).c3.c1),
                            "m" ((*psar).c3.c3),
                            "m" ((*psar).c4.c2)
                            :
                            "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5");

      psar+=4;
      _prefetch_spinor(psar);
      psar-=4;
      
      __asm__ __volatile__ ("mulps %%xmm0, %%xmm0 \n\t"
                            "mulps %%xmm1, %%xmm1 \n\t"
                            "mulps %%xmm2, %%xmm2 \n\t"
                            "mulps %%xmm3, %%xmm3 \n\t"
                            "mulps %%xmm4, %%xmm4 \n\t"
                            "mulps %%xmm5, %%xmm5"
                            :
                            :
                            :
                            "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5");

      psr+=4;
      _prefetch_spinor(psr);
      psr-=4;
      
      __asm__ __volatile__ ("addps %%xmm0, %%xmm1 \n\t"
                            "addps %%xmm2, %%xmm3 \n\t"
                            "addps %%xmm4, %%xmm5 \n\t"
                            "addps %%xmm1, %%xmm3 \n\t"
                            "addps %%xmm3, %%xmm5"
                            :
                            :
                            :
                            "xmm1", "xmm3", "xmm5");

      __asm__ __volatile__ ("movaps %0, %%xmm0 \n\t"
                            "movaps %1, %%xmm1 \n\t"
                            "movaps %2, %%xmm2 \n\t"
                            "movaps %3, %%xmm3 \n\t"
                            "movaps %4, %%xmm4 \n\t"
                            "movaps %5, %%xmm6"
                            :
                            :
                            "m" ((*psar).c1.c1),
                            "m" ((*psar).c1.c3),
                            "m" ((*psar).c2.c2),
                            "m" ((*psar).c3.c1),
                            "m" ((*psar).c3.c3),
                            "m" ((*psar).c4.c2)
                            :
                            "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm6");

      __asm__ __volatile__ ("mulps %0, %%xmm0 \n\t"
                            "mulps %1, %%xmm1 \n\t"
                            "mulps %2, %%xmm2 \n\t"
                            "mulps %3, %%xmm3 \n\t"
                            "mulps %4, %%xmm4 \n\t"
                            "mulps %5, %%xmm6"
                            :
                            :
                            "m" ((*psr).c1.c1),
                            "m" ((*psr).c1.c3),
                            "m" ((*psr).c2.c2),
                            "m" ((*psr).c3.c1),
                            "m" ((*psr).c3.c3),
                            "m" ((*psr).c4.c2)
                            :
                            "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm6");
                            
      __asm__ __volatile__ ("addps %%xmm0, %%xmm1 \n\t"
                            "subps %%xmm2, %%xmm3 \n\t"
                            "addps %%xmm4, %%xmm6 \n\t"
                            "subps %%xmm1, %%xmm3 \n\t"
                            "addps %%xmm3, %%xmm6"
                            :
                            :
                            :
                            "xmm1", "xmm3", "xmm6");

      __asm__ __volatile__ ("movaps %0, %%xmm0 \n\t"
                            "movaps %1, %%xmm1 \n\t"
                            "movaps %2, %%xmm2 \n\t"
                            "movaps %3, %%xmm3 \n\t"
                            "movaps %4, %%xmm4 \n\t"
                            "movaps %5, %%xmm7"
                            :
                            :
                            "m" ((*psar).c1.c1),
                            "m" ((*psar).c1.c3),
                            "m" ((*psar).c2.c2),
                            "m" ((*psar).c3.c1),
                            "m" ((*psar).c3.c3),
                            "m" ((*psar).c4.c2)
                            :
                            "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm7");

      __asm__ __volatile__ ("shufps $0xb1, %%xmm0, %%xmm0 \n\t"
                            "shufps $0xb1, %%xmm1, %%xmm1 \n\t"
                            "shufps $0xb1, %%xmm2, %%xmm2 \n\t"
                            "shufps $0xb1, %%xmm3, %%xmm3 \n\t"
                            "shufps $0xb1, %%xmm4, %%xmm4 \n\t"
                            "shufps $0xb1, %%xmm7, %%xmm7"
                            :
                            :
                            :
                            "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm7");
                            
      __asm__ __volatile__ ("mulps %0, %%xmm0 \n\t"
                            "mulps %1, %%xmm1 \n\t"
                            "mulps %2, %%xmm2 \n\t"
                            "mulps %3, %%xmm3 \n\t"
                            "mulps %4, %%xmm4 \n\t"
                            "mulps %5, %%xmm7"
                            :
                            :
                            "m" ((*psr).c1.c1),
                            "m" ((*psr).c1.c3),
                            "m" ((*psr).c2.c2),
                            "m" ((*psr).c3.c1),
                            "m" ((*psr).c3.c3),
                            "m" ((*psr).c4.c2)
                            :
                            "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm7");
      
      __asm__ __volatile__ ("addps %%xmm0, %%xmm1 \n\t"
                            "subps %%xmm2, %%xmm3 \n\t"
                            "addps %%xmm4, %%xmm7 \n\t"
                            "subps %%xmm1, %%xmm3 \n\t"
                            "addps %%xmm3, %%xmm7 \n\t"
                            "movaps %%xmm5, %0 \n\t"
                            "movaps %%xmm6, %1 \n\t"
                            "movaps %%xmm7, %2"                            
                            :
                            "=m" (tmp1),
                            "=m" (tmp2),
                            "=m" (tmp3)
                            :
                            :
                            "xmm1", "xmm3", "xmm7");
      
      r+=(double)(tmp1.c1+tmp1.c2+tmp1.c3+tmp1.c4);
      x-=(double)(tmp2.c1+tmp2.c2+tmp2.c3+tmp2.c4);      
      y+=(double)(tmp3.c1-tmp3.c2+tmp3.c3-tmp3.c4);

      psr+=1;
      psar+=1;
   }

   (*rn)=(float)(r);
   (*z).re=(float)(x);
   (*z).im=(float)(y);
}

#endif

static void upd_xr(int nsp,complex *z,spinor *psx,spinor *psr,spinor *psar)
{
   spinor *psm;

   __asm__ __volatile__ ("movss %0, %%xmm0 \n\t"
                         "movss %1, %%xmm1 \n\t"
                         "shufps $0x0, %%xmm0, %%xmm0 \n\t"
                         "shufps $0x0, %%xmm1, %%xmm1 \n\t"
                         "mulps %2, %%xmm0 \n\t"
                         "mulps %3, %%xmm1"
                         :
                         :
                         "m" ((*z).re),
                         "m" ((*z).im),
                         "m" (_sse_sgn),
                         "m" (_sse_sgn24)
                         :
                         "xmm0", "xmm1");

   psm=psr+nsp;

   for (;psr<psm;)
   {
      __asm__ __volatile__ ("movaps %0, %%xmm2 \n\t"
                            "movaps %1, %%xmm3 \n\t"
                            "movaps %2, %%xmm6 \n\t"
                            "movaps %3, %%xmm7 \n\t"
                            "movaps %%xmm2, %%xmm4 \n\t"
                            "movaps %%xmm3, %%xmm5"
                            :
                            :
                            "m" ((*psar).c1.c1),
                            "m" ((*psar).c1.c3),
                            "m" ((*psr).c1.c1),
                            "m" ((*psr).c1.c3)
                            :
                            "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7");

      psar+=4;
      _prefetch_spinor(psar);
      psar-=4;
      
      __asm__ __volatile__ ("mulps %%xmm1, %%xmm2 \n\t"
                            "mulps %%xmm1, %%xmm3 \n\t"
                            "mulps %%xmm0, %%xmm4 \n\t"
                            "mulps %%xmm0, %%xmm5 \n\t"
                            "shufps $0xb1, %%xmm2, %%xmm2 \n\t"
                            "shufps $0xb1, %%xmm3, %%xmm3 \n\t"
                            "subps %%xmm2, %%xmm4 \n\t"
                            "subps %%xmm3, %%xmm5 \n\t"
                            "addps %%xmm6, %%xmm4 \n\t"
                            "addps %%xmm7, %%xmm5 \n\t"
                            "movaps %%xmm4, %0 \n\t"
                            "movaps %%xmm5, %1"
                            :
                            "=m" ((*psr).c1.c1),
                            "=m" ((*psr).c1.c3)
                            :
                            :
                            "xmm2", "xmm3", "xmm4","xmm5");

      __asm__ __volatile__ ("movaps %%xmm6, %%xmm2 \n\t"
                            "movaps %%xmm7, %%xmm3 \n\t"
                            "movaps %0, %%xmm4 \n\t"
                            "movaps %1, %%xmm5"
                            :
                            :
                            "m" ((*psar).c2.c2),
                            "m" ((*psar).c3.c1)
                            :
                            "xmm2","xmm3", "xmm4", "xmm5");

      psr+=4;
      _prefetch_spinor(psr);
      psr-=4;
      
      __asm__ __volatile__ ("mulps %%xmm1, %%xmm6 \n\t"
                            "mulps %%xmm1, %%xmm7 \n\t"
                            "mulps %%xmm0, %%xmm2 \n\t"
                            "mulps %%xmm0, %%xmm3 \n\t"
                            "shufps $0xb1, %%xmm6, %%xmm6 \n\t"
                            "shufps $0xb1, %%xmm7, %%xmm7 \n\t"
                            "subps %%xmm2, %%xmm6 \n\t"
                            "subps %%xmm3, %%xmm7 \n\t"
                            "addps %2, %%xmm6 \n\t"
                            "addps %3, %%xmm7 \n\t"
                            "movaps %%xmm6, %0 \n\t"
                            "movaps %%xmm7, %1"
                            :
                            "=m" ((*psx).c1.c1),
                            "=m" ((*psx).c1.c3)
                            :
                            "m" ((*psx).c1.c1),
                            "m" ((*psx).c1.c3)
                            :
                            "xmm2", "xmm3", "xmm6", "xmm7");
      
      __asm__ __volatile__ ("movaps %0, %%xmm2 \n\t"
                            "movaps %1, %%xmm3 \n\t"
                            "movaps %%xmm4, %%xmm6 \n\t"
                            "movaps %%xmm5, %%xmm7"
                            :
                            :
                            "m" ((*psr).c2.c2),
                            "m" ((*psr).c3.c1)
                            :
                            "xmm2", "xmm3", "xmm6", "xmm7");

      psx+=4;
      _prefetch_spinor(psx);
      psx-=4;
      
      __asm__ __volatile__ ("mulps %%xmm1, %%xmm4 \n\t"
                            "mulps %%xmm0, %%xmm5 \n\t"
                            "mulps %%xmm0, %%xmm6 \n\t"
                            "mulps %%xmm1, %%xmm7 \n\t"
                            "shufps $0xb1, %%xmm4, %%xmm4 \n\t"
                            "shufps $0xb1, %%xmm7, %%xmm7 \n\t"
                            "subps %%xmm4, %%xmm6 \n\t"
                            "subps %%xmm5, %%xmm7 \n\t"
                            "addps %%xmm2, %%xmm6 \n\t"
                            "addps %%xmm3, %%xmm7 \n\t"
                            "movaps %%xmm6, %0 \n\t"
                            "movaps %%xmm7, %1"
                            :
                            "=m" ((*psr).c2.c2),
                            "=m" ((*psr).c3.c1)
                            :
                            :
                            "xmm4","xmm5", "xmm6", "xmm7");
      
      __asm__ __volatile__ ("movaps %%xmm2, %%xmm4 \n\t"
                            "movaps %%xmm3, %%xmm5 \n\t"
                            "movaps %0, %%xmm6 \n\t"
                            "movaps %1, %%xmm7"
                            :
                            :
                            "m" ((*psar).c3.c3),
                            "m" ((*psar).c4.c2)
                            :
                            "xmm4", "xmm5", "xmm6", "xmm7");
                            
      __asm__ __volatile__ ("mulps %%xmm1, %%xmm2 \n\t"
                            "mulps %%xmm1, %%xmm3 \n\t"
                            "mulps %%xmm0, %%xmm4 \n\t"
                            "mulps %%xmm0, %%xmm5 \n\t"
                            "shufps $0xb1, %%xmm2, %%xmm2 \n\t"
                            "shufps $0xb1, %%xmm3, %%xmm3 \n\t"
                            "subps %%xmm4, %%xmm2 \n\t"
                            "subps %%xmm5, %%xmm3 \n\t"
                            "addps %2, %%xmm2 \n\t"
                            "addps %3, %%xmm3 \n\t"
                            "movaps %%xmm2, %0 \n\t"
                            "movaps %%xmm3, %1"
                            :
                            "=m" ((*psx).c2.c2),
                            "=m" ((*psx).c3.c1)
                            :
                            "m" ((*psx).c2.c2),
                            "m" ((*psx).c3.c1)
                            :
                            "xmm2","xmm3", "xmm4", "xmm5");

      __asm__ __volatile__ ("movaps %0, %%xmm2 \n\t"
                            "movaps %1, %%xmm3 \n\t"
                            "movaps %%xmm6, %%xmm4 \n\t"
                            "movaps %%xmm7, %%xmm5"
                            :
                            :
                            "m" ((*psr).c3.c3),
                            "m" ((*psr).c4.c2)
                            :
                            "xmm2", "xmm3", "xmm6", "xmm7");

      __asm__ __volatile__ ("mulps %%xmm1, %%xmm6 \n\t"
                            "mulps %%xmm1, %%xmm7 \n\t"
                            "mulps %%xmm0, %%xmm4 \n\t"
                            "mulps %%xmm0, %%xmm5 \n\t"
                            "shufps $0xb1, %%xmm6, %%xmm6 \n\t"
                            "shufps $0xb1, %%xmm7, %%xmm7 \n\t"
                            "subps %%xmm4, %%xmm6 \n\t"
                            "subps %%xmm5, %%xmm7 \n\t"
                            "addps %%xmm2, %%xmm6 \n\t"
                            "addps %%xmm3, %%xmm7 \n\t"
                            "movaps %%xmm6, %0 \n\t"
                            "movaps %%xmm7, %1"
                            :
                            "=m" ((*psr).c3.c3),
                            "=m" ((*psr).c4.c2)
                            :
                            :
                            "xmm4","xmm5", "xmm6", "xmm7");
      
      __asm__ __volatile__ ("movaps %%xmm2, %%xmm4 \n\t"
                            "movaps %%xmm3, %%xmm5 \n\t"
                            "mulps %%xmm1, %%xmm2 \n\t"
                            "mulps %%xmm1, %%xmm3 \n\t"
                            "mulps %%xmm0, %%xmm4 \n\t"
                            "mulps %%xmm0, %%xmm5 \n\t"
                            "shufps $0xb1, %%xmm2, %%xmm2 \n\t"
                            "shufps $0xb1, %%xmm3, %%xmm3 \n\t"
                            "subps %%xmm4, %%xmm2 \n\t"
                            "subps %%xmm5, %%xmm3 \n\t"
                            "addps %2, %%xmm2 \n\t"
                            "addps %3, %%xmm3 \n\t"
                            "movaps %%xmm2, %0 \n\t"
                            "movaps %%xmm3, %1"
                            :
                            "=m" ((*psx).c3.c3),
                            "=m" ((*psx).c4.c2)
                            :
                            "m" ((*psx).c3.c3),
                            "m" ((*psx).c4.c2)
                            :
                            "xmm2","xmm3", "xmm4", "xmm5");

      psr+=1;
      psar+=1;
      psx+=1;
   }
}


void blk_mres(block_t *b,int nmr)
{
   int n,nsp;
   float rn;
   complex z;
   spinor *psx,*psr,*psar;

   nsp=(*b).volh;
   psx=(*b).s[0];
   psr=(*b).s[1];
   psar=(*b).s[2];

   set_s2zero(nsp,psx);

   for (n=0;n<nmr;n++)
   {
      Qhat_blk(b,1,2);
      scalar_prods(nsp,psr,psar,&rn,&z);

      if (rn<(2.0f*FLT_MIN))
         return;

      rn=1.0f/rn;
      z.re*=rn;
      z.im*=rn;

      upd_xr(nsp,&z,psx,psr,psar);
   }
}

#else

void blk_mres(block_t *b,int nmr)
{
   int n,nsp;
   float rn;
   complex z;
   spinor *psx,*psr,*psar;

   nsp=(*b).volh;
   psx=(*b).s[0];
   psr=(*b).s[1];
   psar=(*b).s[2];

   set_s2zero(nsp,psx);

   for (n=0;n<nmr;n++)
   {
      Qhat_blk(b,1,2);
      mulg5(nsp,psar);
      rn=norm_square(nsp,0,psar);

      if (rn<(2.0f*FLT_MIN))
         return;

      z=spinor_prod(nsp,0,psar,psr);

      rn=1.0f/rn;
      z.re*=rn;
      z.im*=rn;
      mulc_spinor_add(nsp,psx,psr,z);

      z.re=-z.re;
      z.im=-z.im;
      mulc_spinor_add(nsp,psr,psar,z);
   }
}

#endif
