コード例 #1
0
    static void DoNonLapCH_Decompose(SymBandMatrixView<T> A)
    {
        // Cholesky decompostion for a banded Hermitian matrix follows the 
        // same structure as a regular Cholesky decomposition, but we 
        // take advantage of the fact that the column or row lengths are 
        // shorter.
        //
        TMVAssert(A.uplo() == Lower);
        TMVAssert(A.ct() == NonConj);
        TMVAssert(isReal(T()) || A.isherm());
        TMVAssert(A.iscm() || A.isrm());
        TMVAssert(cm == A.iscm());
        const ptrdiff_t N = A.size();
#ifdef XDEBUG
        Matrix<T> A0(A);
        //cout<<"CHDecompose:\n";
        //cout<<"A = "<<TMV_Text(A)<<"  "<<A<<endl;
#endif

        VectorView<TMV_RealType(T)> Adiag = A.diag().realPart();
        const ptrdiff_t nlo = A.nlo();

        if (nlo == 0) {
            TMV_RealType(T)* Ajj= Adiag.ptr();
            const ptrdiff_t ds = Adiag.step();
            for(ptrdiff_t j=0;j<N;++j,Ajj+=ds) {
#ifdef TMVFLDEBUG
                TMVAssert(Ajj >= A.realPart()._first);
                TMVAssert(Ajj < A.realPart()._last);
#endif
                if (*Ajj <= TMV_RealType(T)(0))  {
#ifdef NOTHROW
                    std::cerr<<"Non Posdef HermBandMatrix found\n"; 
                    exit(1); 
#else
                    throw NonPosDefHermBandMatrix<T>(A);
#endif
                }
                *Ajj = TMV_SQRT(*Ajj);
            }
        } else if (cm) {
            TMV_RealType(T)* Ajj= Adiag.ptr();
            const ptrdiff_t ds = Adiag.step();
            ptrdiff_t endcol = nlo+1;
            for(ptrdiff_t j=0;j<N-1;++j,Ajj+=ds) {
#ifdef TMVFLDEBUG
                TMVAssert(Ajj >= A.realPart()._first);
                TMVAssert(Ajj < A.realPart()._last);
#endif
                if (*Ajj <= TMV_RealType(T)(0))  {
#ifdef NOTHROW
                    std::cerr<<"Non Posdef HermBandMatrix found\n"; 
                    exit(1); 
#else
                    throw NonPosDefHermBandMatrix<T>(A);
#endif
                }
                *Ajj = TMV_SQRT(*Ajj);
                A.col(j,j+1,endcol) /= *Ajj;
                A.subSymMatrix(j+1,endcol) -= 
                    A.col(j,j+1,endcol) ^ A.col(j,j+1,endcol).conjugate();
                if (endcol < N) ++endcol;
            }
#ifdef TMVFLDEBUG
            TMVAssert(Ajj >= A.realPart()._first);
            TMVAssert(Ajj < A.realPart()._last);
#endif
            if (*Ajj <= TMV_RealType(T)(0))  {
#ifdef NOTHROW
                std::cerr<<"Non Posdef HermBandMatrix found\n"; 
                exit(1); 
#else
                throw NonPosDefHermBandMatrix<T>(A);
#endif
            }
            *Ajj = TMV_SQRT(*Ajj);
        } else {
            TMV_RealType(T)* Aii = Adiag.ptr();
            const ptrdiff_t ds = Adiag.step();
            ptrdiff_t startrow = 0;
#ifdef TMVFLDEBUG
            TMVAssert(Aii >= A.realPart()._first);
            TMVAssert(Aii < A.realPart()._last);
#endif
            if (*Aii <= TMV_RealType(T)(0)) {
#ifdef NOTHROW
                std::cerr<<"Non Posdef HermBandMatrix found\n"; 
                exit(1); 
#else
                throw NonPosDefHermBandMatrix<T>(A);
#endif
            }
            *Aii = TMV_SQRT(*Aii);
            for(ptrdiff_t i=1;i<N;++i) {
                if (i > nlo) ++startrow;
                Aii+=ds;
                A.row(i,startrow,i) %= 
                    A.subSymBandMatrix(startrow,i).lowerBand().adjoint();
#ifdef TMVFLDEBUG
                TMVAssert(Aii >= A.realPart()._first);
                TMVAssert(Aii < A.realPart()._last);
#endif
                *Aii -= NormSq(A.row(i,startrow,i));
                if (*Aii <= TMV_RealType(T)(0))  {
#ifdef NOTHROW
                    std::cerr<<"Non Posdef HermBandMatrix found\n"; 
                    exit(1); 
#else
                    throw NonPosDefHermBandMatrix<T>(A);
#endif
                }
                *Aii = TMV_SQRT(*Aii);
            }
        }

#ifdef XDEBUG
        //cout<<"Done CHDecompose\n";
        BandMatrix<T> L = A.lowerBand();
        BandMatrix<T> A2 = L * L.adjoint();
        TMV_RealType(T) normll = TMV_SQR(Norm(L));
        if (!(Norm(A2-A0) < 0.001*normll)) {
            cerr<<"CH_Decompose: A = "<<TMV_Text(A)<<"  "<<A0<<endl;
            cerr<<"Done: A = "<<A<<endl;
            cerr<<"L = "<<L<<endl;
            cerr<<"Lt = "<<L.adjoint()<<endl;
            cerr<<"L*Lt = "<<A2<<endl;
            cerr<<"Norm(diff) = "<<Norm(A2-A0);
            cerr<<"  Norm(L)^2 = "<<normll<<endl;
            abort();
        }
#endif
    }
コード例 #2
0
    static void NonLapLDL_Decompose(SymBandMatrixView<T> A)
    {
        // For tridiagonal Hermitian band matrices, the sqrt can 
        // become a significant fraction of the calculation.
        // This is unnecessary if we instead decompose A into L D Lt
        // where L is unit diagonal.
        //
        // In this case, the equations become:
        //
        // A = L0 D L0t
        //
        // ( A00 Ax0t ) = (  1  0 ) ( D0  0 ) ( 1 Lx0t )
        // ( Ax0 Axx  ) = ( Lx0 1 ) (  0 Dx ) ( 0   1  )
        //              = (  1  0 ) ( D0  D0 Lx0t )
        //              = ( Lx0 1 ) ( 0   Dx      )
        //
        // The equations from this are:
        //
        // A00 = D0
        // Ax0 = Lx0 D0
        // Axx = Lx0 D0 Lx0t + Axx'
        //
        // where Axx' = Dx is the sub-matrix for the next step.
        //
        TMVAssert(A.uplo() == Lower);
        TMVAssert(A.ct() == NonConj);
        TMVAssert(A.isherm());
        TMVAssert(A.nlo() == 1);
        const ptrdiff_t N = A.size();
#ifdef XDEBUG
        Matrix<T> A0(A);
        //cout<<"LDLDecompose:\n";
        //cout<<"A = "<<TMV_Text(A)<<"  "<<A<<endl;
#endif

        TMV_RealType(T)* Dj = A.realPart().ptr();
        T* Lj = A.diag(-1).ptr();

        if (A.isdm()) {
            for(ptrdiff_t j=0;j<N-1;++j) {
                T Ax0 = *Lj;
                if (*Dj == TMV_RealType(T)(0))  {
#ifdef NOTHROW
                    std::cerr<<"Non Posdef HermBandMatrix found\n"; 
                    exit(1); 
#else
                    throw NonPosDefHermBandLDL<T>(A);
#endif
                }
                *Lj /= *Dj;
                if (isReal(T())) ++Dj; else Dj+=2;
                *Dj -= TMV_REAL(TMV_CONJ(*Lj) * Ax0);
                ++Lj;
            }
        } else {
            const ptrdiff_t Dstep = A.diag().realPart().step();
            const ptrdiff_t Lstep = A.diag().step();
            for(ptrdiff_t j=0;j<N-1;++j) {
                T Ax0 = *Lj;
                if (*Dj == TMV_RealType(T)(0))  {
#ifdef NOTHROW
                    std::cerr<<"Non Posdef HermBandMatrix found\n"; 
                    exit(1); 
#else
                    throw NonPosDefHermBandLDL<T>(A);
#endif
                }
                *Lj /= *Dj;
                Dj += Dstep;
                *Dj -= TMV_REAL(TMV_CONJ(*Lj) * Ax0);
                Lj += Lstep;
            }
        }
        if (*Dj == TMV_RealType(T)(0))  {
#ifdef NOTHROW
            std::cerr<<"Non Posdef HermBandMatrix found\n"; 
            exit(1); 
#else
            throw NonPosDefHermBandLDL<T>(A);
#endif
        }

#ifdef XDEBUG
        //cout<<"Done LDLDecompose\n";
        BandMatrix<T> L = A.lowerBand();
        L.diag().SetAllTo(T(1));
        DiagMatrix<T> D = DiagMatrixViewOf(A.diag());
        BandMatrix<T> A2 = L * D * L.adjoint();
        TMV_RealType(T) normldl = TMV_SQR(Norm(L))*Norm(D);
        //cout<<"Done: A = "<<A<<endl;
        //cout<<"L = "<<L<<endl;
        //cout<<"D = "<<D<<endl;
        //cout<<"A2 = "<<A2<<endl;
        //cout<<"cf A0 = "<<A0<<endl;
        if (!(Norm(A2-A0) < 0.001*normldl)) {
            cerr<<"LDL_Decompose: A = "<<TMV_Text(A)<<"  "<<A0<<endl;
            cerr<<"Done: A = "<<A<<endl;
            cerr<<"L = "<<L<<endl;
            cerr<<"D = "<<D<<endl;
            cerr<<"Lt = "<<L.adjoint()<<endl;
            cerr<<"L*D*Lt = "<<A2<<endl;
            cerr<<"Norm(diff) = "<<Norm(A2-A0);
            cerr<<"  Norm(L)^2*Norm(D) = "<<normldl<<endl;
            abort();
        }
#endif
    }