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 }
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 }