예제 #1
0
    static void SymLDL_Decompose(SymBandMatrixView<T> A)
    {
        TMVAssert(A.uplo() == Lower);
        TMVAssert(A.ct() == NonConj);
        TMVAssert(A.issym());
        TMVAssert(A.nlo() == 1);
        const ptrdiff_t N = A.size();
#ifdef XDEBUG
        Matrix<T> A0(A);
        //cout<<"SymLDLDecompose:\n";
        //cout<<"A = "<<TMV_Text(A)<<"  "<<A<<endl;
#endif

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

        if (A.isdm()) {
            T Ax0 = *Lj;
            if (*Dj == T(0))  {
#ifdef NOTHROW
                std::cerr<<"Non Posdef HermBandMatrix found\n"; 
                exit(1); 
#else
                throw NonPosDefSymBandLDL<T>(A);
#endif
            }
            *Lj /= *Dj;
            ++Dj;
            *Dj -= *Lj * Ax0;
            ++Lj;
        } else {
            ptrdiff_t step = A.diagstep();
            for(ptrdiff_t j=0;j<N-1;++j) {
                T Ax0 = *Lj;
                if (*Dj == T(0))  {
#ifdef NOTHROW
                    std::cerr<<"Non Posdef HermBandMatrix found\n"; 
                    exit(1); 
#else
                    throw NonPosDefSymBandLDL<T>(A);
#endif
                }
                *Lj /= *Dj;
                Dj += step;
                *Dj -= *Lj * Ax0;
                Lj += step;
            }
        }
        if (*Dj == T(0))  {
#ifdef NOTHROW
            std::cerr<<"Non Posdef HermBandMatrix found\n"; 
            exit(1); 
#else
            throw NonPosDefSymBandLDL<T>(A);
#endif
        }

#ifdef XDEBUG
        //cout<<"Done SymLDLDecom\n";
        BandMatrix<T> L = A.lowerBand();
        L.diag().SetAllTo(T(1));
        DiagMatrix<T> D = DiagMatrixViewOf(A.diag());
        BandMatrix<T> A2 = L * D * L.transpose();
        TMV_RealType(T) normldl = TMV_SQR(Norm(L))*Norm(D);
        //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<<"SymLDLDecomp: A = "<<TMV_Text(A)<<"  "<<A0<<endl;
            cerr<<"Done: A = "<<A<<endl;
            cerr<<"L = "<<L<<endl;
            cerr<<"D = "<<D<<endl;
            cerr<<"LT = "<<L.transpose()<<endl;
            cerr<<"L*D*LT = "<<A2<<endl;
            cerr<<"Norm(diff) = "<<Norm(A2-A0);
            cerr<<"  Norm(L)^2*Norm(D) = "<<normldl<<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
    }