Пример #1
0
/*
Diagonalization of an mxm matrix A by a rotation R.
*/
int Diago(double *A, double *R, int m, double threshold)
{
	int encore = 1;
	int rots = 0;
	int p, q;
	double theta, c, s;

	Identity(R, m);

	/* Sweeps until no pair gets updated  */
	while (encore>0)  {
		encore = 0;
		for (p = 0; p<m; p++)
			for (q = p + 1; q<m; q++) {
				theta = Givens(A, m, p, q);
				if (fabs(theta) > threshold) {
					c = cos(theta);
					s = sin(theta);
					LeftRotSimple(A, m, m, p, q, c, s);
					RightRotSimple(A, m, m, p, q, c, s);
					LeftRotSimple(R, m, m, p, q, c, s);
					encore = 1;
					rots++;
				}
			}
	}
	return rots;
}
Пример #2
0
void NeighborColSwap
(       Matrix<F>& Q,
        Matrix<F>& R,
  Int j )
{
    DEBUG_CSE
    typedef Base<F> Real;
    const Int m = Q.Height();

    ColSwap( R, j, j+1 );
    if( j < m-1 )
    {
        Real c; F s;
        Givens( R(j,j), R(j+1,j), c, s );

        auto RBR = R( IR(j,END), IR(j,END) );
        // RBR((0,1),:) := |  c,       s | RBR((0,1),:)
        //                 | -conj(s), c |
        RotateRows( c, s, RBR, 0, 1 );
        // Since |  c,       s |^H = | c,       -s |, the transformation
        //       | -conj(s), c |     | conj(s),  c |
        //
        // s |-> -s inverts a Givens rotation matrix.
        //
        // We therefore update
        //
        //   Q(:,(j,j+1)) := Q(:,(j,j+1)) | c,       -s |.
        //                                | conj(s),  c |
        RotateCols( c, -s, Q, j, j+1 );
    }
}
//#####################################################################
// Function Implicit_QR_Step
//#####################################################################
template<class T,int bandwidth> void BANDED_SYMMETRIC_MATRIX<T,bandwidth>::
Implicit_QR_Step(const int start,const T shift)
{
    // see Golub and Van Loan, 8.3.2, p. 420
    T x=A(start)[1]-shift,z=A(start)[2];
    for(int k=start;;k++){ // chase offdiagonal element z into oblivion
        T c,s;Givens(x,z,c,s);
        if(k>start){T& b=A(k-1)[2];b=c*b-s*z;}
        T &ap=A(k)[1],&bp=A(k)[2],&aq=A(k+1)[1],&bq=A(k+1)[2]; // p,q = k,k+1
        T cc=c*c,cs=c*s,ss=s*s,ccap=cc*ap,csbp=cs*bp,ssaq=ss*aq,csap=cs*ap,ccbp=cc*bp,ssbp=ss*bp,csaq=cs*aq,ssap=ss*ap,ccaq=cc*aq;
        ap=ccap-2*csbp+ssaq;bp=csap+ccbp-ssbp-csaq;aq=ssap+2*csbp+ccaq; // TODO: save 7 flops somehow
        if(!bq) return; // stop if matrix decouples
        x=bp;z=-s*bq;bq=c*bq;}
}
Пример #4
0
void NeighborColSwap
(       Matrix<F>& Q,
        Matrix<F>& R,
  Int j )
{
    DEBUG_CSE
    typedef Base<F> Real;
    const Int m = Q.Height();

    ColSwap( R, j, j+1 );
    if( j < m-1 )
    {
        Real c; F s;
        Givens( R.Get(j,j), R.Get(j+1,j), c, s );

        auto RBR = R( IR(j,END), IR(j,END) );
        RotateRows( c, s, RBR, 0, 1 );

        auto col1 = Q( ALL, IR(j)   );
        auto col2 = Q( ALL, IR(j+1) );
        RotateCols( c, Conj(s), Q, j, j+1 );
    }
}
Пример #5
0
void LUTUnb
( bool conjugate,
  const Matrix<F>& U,
        Matrix<F>& X,
  bool checkIfSingular )
{
    EL_DEBUG_CSE
    typedef Base<F> Real;
    const Int m = X.Height();
    const Int n = X.Width();
    if( conjugate )
        Conjugate( X );

    const F* UBuf = U.LockedBuffer();
          F* XBuf = X.Buffer();
    const Int ldu = U.LDim();
    const Int ldx = X.LDim();

    Int k=0;
    while( k < m )
    {
        const bool in2x2 = ( k+1<m && UBuf[(k+1)+k*ldu] != F(0) );
        if( in2x2 )
        {
            // Solve the 2x2 linear systems via a 2x2 QR decomposition produced
            // by the Givens rotation
            //    | c        s | | U(k,  k) | = | gamma11 | 
            //    | -conj(s) c | | U(k+1,k) |   | 0       |
            //
            // and by also forming the right two entries of the 2x2 resulting
            // upper-triangular matrix, say gamma12 and gamma22
            //
            // Extract the 2x2 diagonal block, D
            const F delta11 = UBuf[ k   + k   *ldu];
            const F delta12 = UBuf[ k   +(k+1)*ldu];
            const F delta21 = UBuf[(k+1)+ k   *ldu];
            const F delta22 = UBuf[(k+1)+(k+1)*ldu];
            // Decompose D = Q R
            Real c; F s;
            const F gamma11 = Givens( delta11, delta21, c, s );
            const F gamma12 =        c*delta12 + s*delta22;
            const F gamma22 = -Conj(s)*delta12 + c*delta22;
            if( checkIfSingular )
            {
                // TODO: Check if sufficiently small instead
                if( gamma11 == F(0) || gamma22 == F(0) )
                    LogicError("Singular diagonal block detected");
            }
            for( Int j=0; j<n; ++j )
            {
                F* xBuf = &XBuf[j*ldx];

                // Solve against R^T
                xBuf[k  ] /= gamma11;
                xBuf[k+1] -= gamma12*xBuf[k];
                xBuf[k+1] /= gamma22;

                // Solve against Q^T
                const F chi1 = xBuf[k  ];
                const F chi2 = xBuf[k+1];
                xBuf[k  ] = c*chi1 - Conj(s)*chi2;
                xBuf[k+1] = s*chi1 +       c*chi2;

                // Update x2 := x2 - U12^T x1
                blas::Axpy
                ( m-(k+2), -xBuf[k  ],
                  &UBuf[ k   +(k+2)*ldu], ldu, &xBuf[k+2], 1 );
                blas::Axpy
                ( m-(k+2), -xBuf[k+1],
                  &UBuf[(k+1)+(k+2)*ldu], ldu, &xBuf[k+2], 1 );
            }
            k += 2;
        }
        else
        {
            if( checkIfSingular )
            {
                // TODO: Check if sufficiently small instead
                if( UBuf[k+k*ldu] == F(0) )
                    LogicError("Singular diagonal entry detected");
            }
            for( Int j=0; j<n; ++j )
            {
                F* xBuf = &XBuf[j*ldx];
                xBuf[k] /= UBuf[k+k*ldu];
                blas::Axpy
                ( m-(k+1), -xBuf[k], &UBuf[k+(k+1)*ldu], ldu, &xBuf[k+1], 1 );
            }
            k += 1;
        }
    }
    if( conjugate )
        Conjugate( X );
}
Пример #6
0
void LLTUnb
( bool conjugate, const Matrix<F>& L, Matrix<F>& X, bool checkIfSingular )
{
    EL_DEBUG_CSE
    typedef Base<F> Real;
    const Int m = X.Height();
    const Int n = X.Width();

    const F* LBuf = L.LockedBuffer();
          F* XBuf = X.Buffer();
    const Int ldl = L.LDim();
    const Int ldx = X.LDim();

    if( conjugate )
        Conjugate( X );

    Int k=m-1;
    while( k >= 0 )
    {
        const bool in2x2 = ( k>0 && LBuf[(k-1)+k*ldl] != F(0) );
        if( in2x2 )
        {
            --k;
            // Solve the 2x2 linear systems via a 2x2 LQ decomposition produced
            // by the Givens rotation
            //    | L(k,k) L(k,k+1) | | c -conj(s) | = | gamma11 0 |
            //                        | s    c     |
            // and by also forming the bottom two entries of the 2x2 resulting
            // lower-triangular matrix, say gamma21 and gamma22
            //
            // Extract the 2x2 diagonal block, D
            const F delta11 = LBuf[   k +   k *ldl];
            const F delta12 = LBuf[   k +(k+1)*ldl];
            const F delta21 = LBuf[(k+1)+   k *ldl];
            const F delta22 = LBuf[(k+1)+(k+1)*ldl];
            // Decompose D = L Q
            Real c; F s;
            const F gamma11 = Givens( delta11, delta12, c, s );
            const F gamma21 =        c*delta21 + s*delta22;
            const F gamma22 = -Conj(s)*delta21 + c*delta22;
            if( checkIfSingular )
            {
                // TODO: Instead check if values are too small in magnitude
                if( gamma11 == F(0) || gamma22 == F(0) )
                    LogicError("Singular diagonal block detected");
            }
            for( Int j=0; j<n; ++j )
            {
                F* xBuf = &XBuf[j*ldx];
                // Solve against Q^T
                const F chi1 = xBuf[k  ];
                const F chi2 = xBuf[k+1];
                xBuf[k  ] =        c*chi1 + s*chi2;
                xBuf[k+1] = -Conj(s)*chi1 + c*chi2;

                // Solve against R^T
                xBuf[k+1] /= gamma22;
                xBuf[k  ] -= gamma21*xBuf[k+1];
                xBuf[k  ] /= gamma11;

                // Update x0 := x0 - L10^T x1
                blas::Axpy( k, -xBuf[k  ], &LBuf[k  ], ldl, xBuf, 1 );
                blas::Axpy( k, -xBuf[k+1], &LBuf[k+1], ldl, xBuf, 1 );
            }
        }
        else
        {
            if( checkIfSingular )
                if( LBuf[k+k*ldl] == F(0) )
                    LogicError("Singular diagonal entry detected");
            for( Int j=0; j<n; ++j )
            {
                F* xBuf = &XBuf[j*ldx];
                // Solve the 1x1 linear system
                xBuf[k] /= LBuf[k+k*ldl];

                // Update x0 := x0 - l10^T chi_1
                blas::Axpy( k, -xBuf[k], &LBuf[k], ldl, xBuf, 1 );
            }
        }
        --k;
    }
    if( conjugate )
        Conjugate( X );
}
Пример #7
0
Matrix DivideAndSolve(Matrix A,int p)
{
  double a,b,d,e,s,c,mu,i;
  int h,j,k,l,m,o,rowstartt,colstartt,rowendt,colendt;
  Vector v,u,x,y,z;
  Matrix B,C,D,E,Q,U,H;

  U = newIdMatrix();
  H = newMatrix();
  v = newVector();

  i = p+1;

  rowstartt = i; 
  colstartt = 0;

  while (rowstartt<n)
    {
      rowendt = (rowstartt+i-1<n-1)?rowstartt+i-1:n-1; 
      colstartt = rowstartt-i;
      colendt = colstartt+i-1;
      
      /* Now T_i has dimension (p-h)x(p-h) */

      /* First zero all but row 1 in T_i */

      for (m=colstartt;m<=colendt;m++)
	{
	  if (norm(A,m,rowstartt,rowendt)!=0.0)
	    {
	      /* Find Householder(A(h:p,m)) */
	      House(A,v,m,rowstartt,rowendt);
	      for (o=0;o<rowstartt;o++)
		v[o]=0.0;
	      for (o=rowendt+1;o<n;o++)
		v[o]=0.0;
	      ApplyHouse(A,v,rowstartt,rowendt);
	    }
	  printf("m=%i, rowstart=%i, rowend=%i\n",m,rowstartt,rowendt);
	  printVector(v);
	  printMatrix(A);
	}

      /* Now zero all but the last entry in row 1 */

      WeirdHouse(A,v,rowstartt,colstartt,colendt);

      /* Apply the HouseHolder */

      ApplyHouse(A,v,colstartt,colendt);

      /* Now T_i has one single non-zero entry */

      /* Iterate with explicit shift to zero the last
	 non-zero entry */

      while (A[rowstartt][colendt]>
	     (A[rowstartt-1][colendt]-A[rowstartt][colendt+1])*epsilon)
	{
	  printMatrix(A);
	  /* Wilkonson Shift?? */
	  d  =(A[rowstartt-1][colendt]-A[rowstartt][colendt+1])/2.0;
	  b = A[rowstartt][colendt];
	  mu = A[rowstartt][colendt+1]+d-sign(d)*sqrt(d*d+b*b);

	  /* Determine the givens */
	  Givens(A[rowstartt-1][colendt]-mu,
		 A[rowstartt][colendt],&s,&c);
	  
	  /* Apply the givens */
	  ApplyGivens(A,s,c,rowstartt-1,rowstartt,0,n-1);
	  printf("%e\n",A[colstartt][colendt]);
	}

      rowstartt+=i;
      colstartt+=i;
    }				    
}
Пример #8
0
void LUTUnb
( bool conjugate, 
  const Matrix<Real>& U, 
  const Matrix<Complex<Real>>& shifts, 
        Matrix<Real>& XReal,
        Matrix<Real>& XImag )
{
    DEBUG_CSE
    typedef Complex<Real> C;
    const Int m = XReal.Height();
    const Int n = XReal.Width();
  
    if( conjugate )
        XImag *= -1;

    const Real* UBuf = U.LockedBuffer();
          Real* XRealBuf = XReal.Buffer();
          Real* XImagBuf = XImag.Buffer();
    const Int ldU = U.LDim();
    const Int ldXReal = XReal.LDim();
    const Int ldXImag = XImag.LDim();

    Int k=0;
    while( k < m )
    {
        const bool in2x2 = ( k+1<m && UBuf[(k+1)+k*ldU] != Real(0) );
        if( in2x2 )
        {
            // Solve the 2x2 linear systems via 2x2 QR decompositions produced
            // by the Givens rotation
            //    | c        s | | U(k,  k)-shift | = | gamma11 | 
            //    | -conj(s) c | | U(k+1,k)       |   | 0       |
            //
            // and by also forming the right two entries of the 2x2 resulting
            // upper-triangular matrix, say gamma12 and gamma22
            //
            // Extract the constant part of the 2x2 diagonal block, D
            const Real delta12 = UBuf[ k   +(k+1)*ldU];
            const Real delta21 = UBuf[(k+1)+ k   *ldU];
            for( Int j=0; j<n; ++j )
            {
                const C delta11 = UBuf[ k   + k   *ldU] - shifts.Get(j,0);
                const C delta22 = UBuf[(k+1)+(k+1)*ldU] - shifts.Get(j,0);
                // Decompose D = Q R
                Real c; C s;
                const C gamma11 = Givens( delta11, C(delta21), c, s );
                const C gamma12 =        c*delta12 + s*delta22;
                const C gamma22 = -Conj(s)*delta12 + c*delta22;

                Real* xRealBuf = &XRealBuf[j*ldXReal];
                Real* xImagBuf = &XImagBuf[j*ldXImag]; 

                // Solve against R^T
                C chi1(xRealBuf[k  ],xImagBuf[k  ]);
                C chi2(xRealBuf[k+1],xImagBuf[k+1]);
                chi1 /= gamma11;
                chi2 -= gamma12*chi1;
                chi2 /= gamma22;

                // Solve against Q^T
                const C eta1 = c*chi1 - Conj(s)*chi2;
                const C eta2 = s*chi1 +       c*chi2;
                xRealBuf[k  ] = eta1.real();
                xImagBuf[k  ] = eta1.imag();
                xRealBuf[k+1] = eta2.real();
                xImagBuf[k+1] = eta2.imag();

                // Update x2 := x2 - U12^T x1
                blas::Axpy
                ( m-(k+2), -xRealBuf[k  ],
                  &UBuf[ k   +(k+2)*ldU], ldU, &xRealBuf[k+2], 1 );
                blas::Axpy
                ( m-(k+2), -xImagBuf[k  ],
                  &UBuf[ k   +(k+2)*ldU], ldU, &xImagBuf[k+2], 1 );
                blas::Axpy
                ( m-(k+2), -xRealBuf[k+1],
                  &UBuf[(k+1)+(k+2)*ldU], ldU, &xRealBuf[k+2], 1 );
                blas::Axpy
                ( m-(k+2), -xImagBuf[k+1],
                  &UBuf[(k+1)+(k+2)*ldU], ldU, &xImagBuf[k+2], 1 );
            }
            k += 2;
        }
        else
        {
            for( Int j=0; j<n; ++j )
            {
                Real* xRealBuf = &XRealBuf[j*ldXReal];
                Real* xImagBuf = &XImagBuf[j*ldXImag];
                C eta1( xRealBuf[k], xImagBuf[k] );
                eta1 /= UBuf[k+k*ldU] - shifts.Get(j,0);
                xRealBuf[k] = eta1.real();
                xImagBuf[k] = eta1.imag();
                blas::Axpy
                ( m-(k+1), -xRealBuf[k], 
                  &UBuf[k+(k+1)*ldU], ldU, &xRealBuf[k+1], 1 );
                blas::Axpy
                ( m-(k+1), -xImagBuf[k], 
                  &UBuf[k+(k+1)*ldU], ldU, &xImagBuf[k+1], 1 );
            }
            k += 1;
        }
    }
    if( conjugate )
        XImag *= -1;
}
Пример #9
0
void LUTUnb
( bool conjugate, const Matrix<F>& U, const Matrix<F>& shifts, Matrix<F>& X )
{
    DEBUG_CSE
    typedef Base<F> Real;
    const Int m = X.Height();
    const Int n = X.Width();

    if( conjugate )
        Conjugate( X );

    const F* UBuf = U.LockedBuffer();
          F* XBuf = X.Buffer();
    const Int ldU = U.LDim();
    const Int ldX = X.LDim();

    Int k=0;
    while( k < m )
    {
        const bool in2x2 = ( k+1<m && UBuf[(k+1)+k*ldU] != F(0) );
        if( in2x2 )
        {
            // Solve the 2x2 linear systems via 2x2 QR decompositions produced
            // by the Givens rotation
            //    | c        s | | U(k,  k)-shift | = | gamma11 | 
            //    | -conj(s) c | | U(k+1,k)       |   | 0       |
            //
            // and by also forming the right two entries of the 2x2 resulting
            // upper-triangular matrix, say gamma12 and gamma22
            //
            // Extract the constant part of the 2x2 diagonal block, D
            const F delta12 = UBuf[ k   +(k+1)*ldU];
            const F delta21 = UBuf[(k+1)+ k   *ldU];
            for( Int j=0; j<n; ++j )
            {
                const F delta11 = UBuf[ k   + k   *ldU] - shifts.Get(j,0);
                const F delta22 = UBuf[(k+1)+(k+1)*ldU] - shifts.Get(j,0);
                // Decompose D = Q R
                Real c; F s;
                const F gamma11 = Givens( delta11, delta21, c, s );
                const F gamma12 =        c*delta12 + s*delta22;
                const F gamma22 = -Conj(s)*delta12 + c*delta22;

                F* xBuf = &XBuf[j*ldX];

                // Solve against R^T
                F chi1 = xBuf[k  ];
                F chi2 = xBuf[k+1];
                chi1 /= gamma11;
                chi2 -= gamma12*chi1;
                chi2 /= gamma22;

                // Solve against Q^T
                xBuf[k  ] = c*chi1 - Conj(s)*chi2;
                xBuf[k+1] = s*chi1 +       c*chi2;

                // Update x2 := x2 - U12^T x1
                blas::Axpy
                ( m-(k+2), -xBuf[k  ],
                  &UBuf[ k   +(k+2)*ldU], ldU, &xBuf[k+2], 1 );
                blas::Axpy
                ( m-(k+2), -xBuf[k+1],
                  &UBuf[(k+1)+(k+2)*ldU], ldU, &xBuf[k+2], 1 );
            }
            k += 2;
        }
        else
        {
            for( Int j=0; j<n; ++j )
            {
                F* xBuf = &XBuf[j*ldX];
                xBuf[k] /= UBuf[k+k*ldU] - shifts.Get(j,0);
                blas::Axpy
                ( m-(k+1), -xBuf[k], &UBuf[k+(k+1)*ldU], ldU, &xBuf[k+1], 1 );
            }
            k += 1;
        }
    }
    if( conjugate )
        Conjugate( X );
}
Пример #10
0
void LUNUnb( const Matrix<F>& U, Matrix<F>& X, bool checkIfSingular )
{
    DEBUG_CSE
    const Int m = X.Height();
    const Int n = X.Width();
    typedef Base<F> Real;
    
    const F* UBuf = U.LockedBuffer();
          F* XBuf = X.Buffer();
    const Int ldu = U.LDim();
    const Int ldx = X.LDim();
    
    Int k=m-1;
    while( k >= 0 )
    {
        const bool in2x2 = ( k>0 && UBuf[k+(k-1)*ldu] != F(0) );
        if( in2x2 )
        {
            --k;
            // Solve the 2x2 linear systems via a 2x2 QR decomposition produced
            // by the Givens rotation
            //    | c        s | | U(k,  k) | = | gamma11 | 
            //    | -conj(s) c | | U(k+1,k) |   | 0       |
            //
            // and by also forming the right two entries of the 2x2 resulting
            // upper-triangular matrix, say gamma12 and gamma22
            //
            // Extract the 2x2 diagonal block, D
            const F delta11 = UBuf[ k   + k   *ldu];
            const F delta12 = UBuf[ k   +(k+1)*ldu];
            const F delta21 = UBuf[(k+1)+ k   *ldu];
            const F delta22 = UBuf[(k+1)+(k+1)*ldu];
            // Decompose D = Q R
            Real c; F s;
            const F gamma11 = Givens( delta11, delta21, c, s );
            const F gamma12 =        c*delta12 + s*delta22;
            const F gamma22 = -Conj(s)*delta12 + c*delta22;
            if( checkIfSingular )
            {
                // TODO: Instead check if values are too small in magnitude
                if( gamma11 == F(0) || gamma22 == F(0) )
                    LogicError("Singular diagonal block detected");
            }
            for( Int j=0; j<n; ++j )
            {
                F* xBuf = &XBuf[j*ldx];
                // Solve against Q
                const F chi1 = xBuf[k  ];
                const F chi2 = xBuf[k+1];
                xBuf[k  ] =        c*chi1 + s*chi2;
                xBuf[k+1] = -Conj(s)*chi1 + c*chi2;

                // Solve against R
                xBuf[k+1] /= gamma22;
                xBuf[k  ] -= gamma12*xBuf[k+1];
                xBuf[k  ] /= gamma11;

                // Update x0 := x0 - U01 x1
                blas::Axpy( k, -xBuf[k  ], &UBuf[ k   *ldu], 1, xBuf, 1 );
                blas::Axpy( k, -xBuf[k+1], &UBuf[(k+1)*ldu], 1, xBuf, 1 );
            }
        }
        else
        {
            if( checkIfSingular )
                if( UBuf[k+k*ldu] == F(0) )
                    LogicError("Singular diagonal entry detected");
            for( Int j=0; j<n; ++j )
            {
                F* xBuf = &XBuf[j*ldx];
                // Solve the 1x1 linear system
                xBuf[k] /= UBuf[k+k*ldu];

                // Update x0 := x0 - u01 chi_1
                blas::Axpy( k, -xBuf[k], &UBuf[k*ldu], 1, xBuf, 1 );
            }
        }
        --k;
    }
}
Пример #11
0
void LLNUnb( const Matrix<F>& L, Matrix<F>& X, bool checkIfSingular )
{
    DEBUG_CSE
    typedef Base<F> Real;
    const Int m = X.Height();
    const Int n = X.Width();

    const F* LBuf = L.LockedBuffer();
          F* XBuf = X.Buffer();
    const Int ldl = L.LDim();
    const Int ldx = X.LDim();

    Int k=0;
    while( k < m )
    {
        const bool in2x2 = ( k+1<m && LBuf[k+(k+1)*ldl] != F(0) );
        if( in2x2 ) 
        {
            // Solve the 2x2 linear systems via a 2x2 LQ decomposition produced
            // by the Givens rotation
            //    | L(k,k) L(k,k+1) | | c -conj(s) | = | gamma11 0 |
            //                        | s    c     |
            // and by also forming the bottom two entries of the 2x2 resulting
            // lower-triangular matrix, say gamma21 and gamma22
            //
            // Extract the 2x2 diagonal block, D
            const F delta11 = LBuf[ k   + k   *ldl];
            const F delta12 = LBuf[ k   +(k+1)*ldl];
            const F delta21 = LBuf[(k+1)+ k   *ldl];
            const F delta22 = LBuf[(k+1)+(k+1)*ldl];
            // Decompose D = L Q
            Real c; F s;
            const F gamma11 = Givens( delta11, delta12, c, s );
            const F gamma21 =        c*delta21 + s*delta22;
            const F gamma22 = -Conj(s)*delta21 + c*delta22;
            if( checkIfSingular )
            {
                // TODO: Check if sufficiently small instead
                if( gamma11 == F(0) || gamma22 == F(0) )
                    LogicError("Singular diagonal block detected");
            }
            for( Int j=0; j<n; ++j )
            {
                F* xBuf = &XBuf[j*ldx];

                // Solve against L
                xBuf[k  ] /= gamma11;
                xBuf[k+1] -= gamma21*xBuf[k];
                xBuf[k+1] /= gamma22;

                // Solve against Q
                const F chi1 = xBuf[k  ];
                const F chi2 = xBuf[k+1];
                xBuf[k  ] = c*chi1 - Conj(s)*chi2;
                xBuf[k+1] = s*chi1 +       c*chi2;

                // Update x2 := x2 - L21 x1
                blas::Axpy
                ( m-(k+2), -xBuf[k  ], 
                  &LBuf[(k+2)+ k   *ldl], 1, &xBuf[k+2], 1 );
                blas::Axpy
                ( m-(k+2), -xBuf[k+1], 
                  &LBuf[(k+2)+(k+1)*ldl], 1, &xBuf[k+2], 1 );
            }

            k += 2;
        }
        else
        {
            if( checkIfSingular )
            {
                // TODO: Check if sufficiently small instead
                if( LBuf[k+k*ldl] == F(0) )
                    LogicError("Singular diagonal entry detected");
            }
            for( Int j=0; j<n; ++j )
            {
                F* xBuf = &XBuf[j*ldx];
                xBuf[k] /= LBuf[k+k*ldl];
                blas::Axpy
                ( m-(k+1), -xBuf[k], &LBuf[(k+1)+k*ldl], 1, &xBuf[k+1], 1 );
            }
            k += 1;
        }
    }
}
Пример #12
0
void LLTUnb
( bool conjugate, const Matrix<F>& L, const Matrix<F>& shifts, Matrix<F>& X )
{
    DEBUG_CSE
    typedef Base<F> Real;
    const Int m = X.Height();
    const Int n = X.Width();

    const F* LBuf = L.LockedBuffer();
          F* XBuf = X.Buffer();
    const Int ldl = L.LDim();
    const Int ldx = X.LDim();

    if( conjugate )
        Conjugate( X );

    Int k=m-1;
    while( k >= 0 )
    {
        const bool in2x2 = ( k>0 && LBuf[(k-1)+k*ldl] != F(0) );
        if( in2x2 )
        {
            --k;
            // Solve the 2x2 linear systems via 2x2 LQ decompositions produced
            // by the Givens rotation
            //    | L(k,k)-shift L(k,k+1) | | c -conj(s) | = | gamma11 0 |
            //                              | s    c     |
            // and by also forming the bottom two entries of the 2x2 resulting
            // lower-triangular matrix, say gamma21 and gamma22
            //
            // Extract the constant part of the 2x2 diagonal block, D
            const F delta12 = LBuf[   k +(k+1)*ldl];
            const F delta21 = LBuf[(k+1)+   k *ldl];
            for( Int j=0; j<n; ++j )
            {
                const F delta11 = LBuf[   k +   k *ldl] - shifts.Get(j,0);
                const F delta22 = LBuf[(k+1)+(k+1)*ldl] - shifts.Get(j,0);
                // Decompose D = L Q
                Real c; F s;
                const F gamma11 = Givens( delta11, delta12, c, s );
                const F gamma21 =        c*delta21 + s*delta22;
                const F gamma22 = -Conj(s)*delta21 + c*delta22;

                F* xBuf = &XBuf[j*ldx];
                // Solve against Q^T
                const F chi1 = xBuf[k  ];
                const F chi2 = xBuf[k+1];
                xBuf[k  ] =        c*chi1 + s*chi2;
                xBuf[k+1] = -Conj(s)*chi1 + c*chi2;

                // Solve against R^T
                xBuf[k+1] /= gamma22;
                xBuf[k  ] -= gamma21*xBuf[k+1];
                xBuf[k  ] /= gamma11;

                // Update x0 := x0 - L10^T x1
                blas::Axpy( k, -xBuf[k  ], &LBuf[k  ], ldl, xBuf, 1 );
                blas::Axpy( k, -xBuf[k+1], &LBuf[k+1], ldl, xBuf, 1 );
            }
        }
        else
        {
            for( Int j=0; j<n; ++j )
            {
                F* xBuf = &XBuf[j*ldx];
                // Solve the 1x1 linear system
                xBuf[k] /= LBuf[k+k*ldl] - shifts.Get(j,0);

                // Update x0 := x0 - l10^T chi_1
                blas::Axpy( k, -xBuf[k], &LBuf[k], ldl, xBuf, 1 );
            }
        }
        --k;
    }
    if( conjugate )
        Conjugate( X );
}