void LUNMedium ( const AbstractDistMatrix<F>& UPre, AbstractDistMatrix<F>& XPre, bool checkIfSingular ) { DEBUG_CSE const Int m = XPre.Height(); const Int bsize = Blocksize(); const Grid& g = UPre.Grid(); DistMatrixReadProxy<F,F,MC,MR> UProx( UPre ); DistMatrixReadWriteProxy<F,F,MC,MR> XProx( XPre ); auto& U = UProx.GetLocked(); auto& X = XProx.Get(); DistMatrix<F,MC, STAR> U01_MC_STAR(g); DistMatrix<F,STAR,STAR> U11_STAR_STAR(g); DistMatrix<F,MR, STAR> X1Trans_MR_STAR(g); const Int kLast = LastOffset( m, bsize ); Int k=kLast, kOld=m; while( true ) { const bool in2x2 = ( k>0 && U.Get(k,k-1) != F(0) ); if( in2x2 ) --k; const Int nb = kOld-k; const Range<Int> ind0( 0, k ), ind1( k, k+nb ); auto U01 = U( ind0, ind1 ); auto U11 = U( ind1, ind1 ); auto X0 = X( ind0, ALL ); auto X1 = X( ind1, ALL ); U11_STAR_STAR = U11; // U11[* ,* ] <- U11[MC,MR] X1Trans_MR_STAR.AlignWith( X0 ); Transpose( X1, X1Trans_MR_STAR ); // X1^T[MR,* ] := X1^T[MR,* ] U11^-T[* ,* ] // = (U11^-1[* ,* ] X1[* ,MR])^T LocalQuasiTrsm ( RIGHT, UPPER, TRANSPOSE, F(1), U11_STAR_STAR, X1Trans_MR_STAR, checkIfSingular ); Transpose( X1Trans_MR_STAR, X1 ); U01_MC_STAR.AlignWith( X0 ); U01_MC_STAR = U01; // U01[MC,* ] <- U01[MC,MR] // X0[MC,MR] -= U01[MC,* ] X1[* ,MR] LocalGemm ( NORMAL, TRANSPOSE, F(-1), U01_MC_STAR, X1Trans_MR_STAR, F(1), X0 ); if( k == 0 ) break; kOld = k; k -= Min(bsize,k); } }
bool TriangIsNormal( const ElementalMatrix<F>& UPre, Base<F> tol ) { DistMatrixReadProxy<F,F,MC,MR> UProx( UPre ); auto& U = UProx.GetLocked(); const Base<F> diagFrob = FrobeniusNorm(GetDiagonal(U)); const Base<F> upperFrob = FrobeniusNorm( U ); const Base<F> offDiagFrob = Sqrt(upperFrob*upperFrob-diagFrob*diagFrob); return offDiagFrob <= tol*diagFrob; }
void LUNMedium ( UnitOrNonUnit diag, const AbstractDistMatrix<F>& UPre, AbstractDistMatrix<F>& XPre, bool checkIfSingular ) { EL_DEBUG_CSE const Int m = XPre.Height(); const Int bsize = Blocksize(); const Grid& g = UPre.Grid(); DistMatrixReadProxy<F,F,MC,MR> UProx( UPre ); DistMatrixReadWriteProxy<F,F,MC,MR> XProx( XPre ); auto& U = UProx.GetLocked(); auto& X = XProx.Get(); DistMatrix<F,MC, STAR> U01_MC_STAR(g); DistMatrix<F,STAR,STAR> U11_STAR_STAR(g); DistMatrix<F,MR, STAR> X1Trans_MR_STAR(g); const Int kLast = LastOffset( m, bsize ); for( Int k=kLast; k>=0; k-=bsize ) { const Int nb = Min(bsize,m-k); const Range<Int> ind0( 0, k ), ind1( k, k+nb ); auto U01 = U( ind0, ind1 ); auto U11 = U( ind1, ind1 ); auto X0 = X( ind0, ALL ); auto X1 = X( ind1, ALL ); U11_STAR_STAR = U11; // U11[* ,* ] <- U11[MC,MR] X1Trans_MR_STAR.AlignWith( X0 ); Transpose( X1, X1Trans_MR_STAR ); // X1^T[MR,* ] := X1^T[MR,* ] U11^-T[* ,* ] // = (U11^-1[* ,* ] X1[* ,MR])^T LocalTrsm ( RIGHT, UPPER, TRANSPOSE, diag, F(1), U11_STAR_STAR, X1Trans_MR_STAR, checkIfSingular ); Transpose( X1Trans_MR_STAR, X1 ); U01_MC_STAR.AlignWith( X0 ); U01_MC_STAR = U01; // U01[MC,* ] <- U01[MC,MR] // X0[MC,MR] -= U01[MC,* ] X1[* ,MR] LocalGemm ( NORMAL, TRANSPOSE, F(-1), U01_MC_STAR, X1Trans_MR_STAR, F(1), X0 ); } }
void LUNLarge ( UnitOrNonUnit diag, const AbstractDistMatrix<F>& UPre, AbstractDistMatrix<F>& XPre, bool checkIfSingular ) { EL_DEBUG_CSE const Int m = XPre.Height(); const Int bsize = Blocksize(); const Grid& g = UPre.Grid(); DistMatrixReadProxy<F,F,MC,MR> UProx( UPre ); DistMatrixReadWriteProxy<F,F,MC,MR> XProx( XPre ); auto& U = UProx.GetLocked(); auto& X = XProx.Get(); DistMatrix<F,MC, STAR> U01_MC_STAR(g); DistMatrix<F,STAR,STAR> U11_STAR_STAR(g); DistMatrix<F,STAR,MR > X1_STAR_MR(g); DistMatrix<F,STAR,VR > X1_STAR_VR(g); const Int kLast = LastOffset( m, bsize ); for( Int k=kLast; k>=0; k-=bsize ) { const Int nb = Min(bsize,m-k); const Range<Int> ind0( 0, k ), ind1( k, k+nb ); auto U01 = U( ind0, ind1 ); auto U11 = U( ind1, ind1 ); auto X0 = X( ind0, ALL ); auto X1 = X( ind1, ALL ); U11_STAR_STAR = U11; // U11[* ,* ] <- U11[MC,MR] X1_STAR_VR = X1; // X1[* ,VR] <- X1[MC,MR] // X1[* ,VR] := U11^-1[* ,* ] X1[* ,VR] LocalTrsm ( LEFT, UPPER, NORMAL, diag, F(1), U11_STAR_STAR, X1_STAR_VR, checkIfSingular ); X1_STAR_MR.AlignWith( X0 ); X1_STAR_MR = X1_STAR_VR; // X1[* ,MR] <- X1[* ,VR] X1 = X1_STAR_MR; // X1[MC,MR] <- X1[* ,MR] U01_MC_STAR.AlignWith( X0 ); U01_MC_STAR = U01; // U01[MC,* ] <- U01[MC,MR] // X0[MC,MR] -= U01[MC,* ] X1[* ,MR] LocalGemm( NORMAL, NORMAL, F(-1), U01_MC_STAR, X1_STAR_MR, F(1), X0 ); } }
void GolubReinsch ( AbstractDistMatrix<Field>& APre, AbstractDistMatrix<Field>& UPre, AbstractDistMatrix<Base<Field>>& s, AbstractDistMatrix<Field>& VPre, const SVDCtrl<Base<Field>>& ctrl ) { EL_DEBUG_CSE DistMatrixReadWriteProxy<Field,Field,MC,MR> AProx( APre ); DistMatrixWriteProxy<Field,Field,MC,MR> UProx( UPre ); DistMatrixWriteProxy<Field,Field,MC,MR> VProx( VPre ); auto& A = AProx.Get(); auto& U = UProx.Get(); auto& V = VProx.Get(); return GolubReinsch( A, U, s, V, ctrl ); }
void CheckRealSchur( const AbstractDistMatrix<Real>& UPre, bool standardForm ) { EL_DEBUG_CSE DistMatrixReadProxy<Real,Real,MC,MR> UProx( UPre ); auto& U = UProx.GetLocked(); auto uMain = GetDiagonal(U); auto uSub = GetDiagonal(U,-1); DistMatrix<Real,STAR,STAR> uMain_STAR_STAR( uMain ), uSub_STAR_STAR( uSub ); auto& uMainLoc = uMain_STAR_STAR.Matrix(); auto& uSubLoc = uSub_STAR_STAR.Matrix(); const Int n = U.Height(); if( standardForm ) { auto uSup = GetDiagonal(U,+1); DistMatrix<Real,STAR,STAR> uSup_STAR_STAR( uSup ); auto& uSupLoc = uSup_STAR_STAR.Matrix(); for( Int j=0; j<n-1; ++j ) { const Real thisDiag = uMainLoc(j); const Real nextDiag = uMainLoc(j+1); const Real thisSub = uSubLoc(j); const Real thisSup = uSupLoc(j); if( thisSub != Real(0) && thisDiag != nextDiag ) LogicError ("Diagonal of 2x2 block was not constant: ",thisDiag," and ", nextDiag); if( thisSub*thisSup >= 0 ) LogicError("b*c >= 0: b=",thisSup," and c=",thisSub); } } if( n < 3 ) return; for( Int j=0; j<n-2; ++j ) { const Real thisSub = uSubLoc(j); const Real nextSub = uSubLoc(j+1); if( thisSub != Real(0) && nextSub != Real(0) ) LogicError ("Quasi-triangular assumption broken at j=",j, ": subdiagonals were ",thisSub," and ",nextSub); } }
void LUNLarge ( const ElementalMatrix<F>& UPre, ElementalMatrix<F>& XPre, bool checkIfSingular ) { DEBUG_CSE const Int m = XPre.Height(); const Int bsize = Blocksize(); const Grid& g = UPre.Grid(); DistMatrixReadProxy<F,F,MC,MR> UProx( UPre ); DistMatrixReadWriteProxy<F,F,MC,MR> XProx( XPre ); auto& U = UProx.GetLocked(); auto& X = XProx.Get(); DistMatrix<F,MC, STAR> U01_MC_STAR(g); DistMatrix<F,STAR,STAR> U11_STAR_STAR(g); DistMatrix<F,STAR,MR > X1_STAR_MR(g); DistMatrix<F,STAR,VR > X1_STAR_VR(g); const Int kLast = LastOffset( m, bsize ); Int k=kLast, kOld=m; while( true ) { const bool in2x2 = ( k>0 && U.Get(k,k-1) != F(0) ); if( in2x2 ) --k; const Int nb = kOld-k; const Range<Int> ind0( 0, k ), ind1( k, k+nb ); auto U01 = U( ind0, ind1 ); auto U11 = U( ind1, ind1 ); auto X0 = X( ind0, ALL ); auto X1 = X( ind1, ALL ); U11_STAR_STAR = U11; // U11[* ,* ] <- U11[MC,MR] X1_STAR_VR = X1; // X1[* ,VR] <- X1[MC,MR] // X1[* ,VR] := U11^-1[* ,* ] X1[* ,VR] LocalQuasiTrsm ( LEFT, UPPER, NORMAL, F(1), U11_STAR_STAR, X1_STAR_VR, checkIfSingular ); X1_STAR_MR.AlignWith( X0 ); X1_STAR_MR = X1_STAR_VR; // X1[* ,MR] <- X1[* ,VR] X1 = X1_STAR_MR; // X1[MC,MR] <- X1[* ,MR] U01_MC_STAR.AlignWith( X0 ); U01_MC_STAR = U01; // U01[MC,* ] <- U01[MC,MR] // X0[MC,MR] -= U01[MC,* ] X1[* ,MR] LocalGemm( NORMAL, NORMAL, F(-1), U01_MC_STAR, X1_STAR_MR, F(1), X0 ); if( k == 0 ) break; kOld = k; k -= Min(bsize,k); } }
SVDInfo ScaLAPACKHelper ( const AbstractDistMatrix<F>& APre, AbstractDistMatrix<F>& UPre, AbstractDistMatrix<Base<F>>& sPre, AbstractDistMatrix<F>& V, const SVDCtrl<Base<F>>& ctrl ) { DEBUG_CSE AssertScaLAPACKSupport(); SVDInfo info; #ifdef EL_HAVE_SCALAPACK typedef Base<F> Real; DistMatrix<F,MC,MR,BLOCK> A( APre ); DistMatrixWriteProxy<Real,Real,STAR,STAR> sProx(sPre); DistMatrixWriteProxy<F,F,MC,MR,BLOCK> UProx(UPre); auto& s = sProx.Get(); auto& U = UProx.Get(); const int m = A.Height(); const int n = A.Width(); const int k = Min(m,n); auto approach = ctrl.bidiagSVDCtrl.approach; if( approach == THIN_SVD || approach == COMPACT_SVD ) { Zeros( U, m, k ); DistMatrix<F,MC,MR,BLOCK> VH( A.Grid() ); Zeros( VH, k, n ); s.Resize( k, 1 ); auto descA = FillDesc( A ); auto descU = FillDesc( U ); auto descVH = FillDesc( VH ); scalapack::SVD ( m, n, A.Buffer(), descA.data(), s.Buffer(), U.Buffer(), descU.data(), VH.Buffer(), descVH.data() ); const bool compact = ( approach == COMPACT_SVD ); if( compact ) { const Real twoNorm = ( k==0 ? Real(0) : s.Get(0,0) ); const Real thresh = bidiag_svd::APosterioriThreshold ( m, n, twoNorm, ctrl.bidiagSVDCtrl ); Int rank = k; for( Int j=0; j<k; ++j ) { if( s.Get(j,0) <= thresh ) { rank = j; break; } } s.Resize( rank, 1 ); U.Resize( m, rank ); VH.Resize( rank, n ); } Adjoint( VH, V ); } else LogicError ("Only Thin and Compact singular value options currently supported"); #endif return info; }