void HermitianSign ( UpperOrLower uplo, AbstractDistMatrix<Field>& APre, AbstractDistMatrix<Field>& NPre, const HermitianEigCtrl<Field>& ctrl ) { EL_DEBUG_CSE DistMatrixReadWriteProxy<Field,Field,MC,MR> AProx( APre ); DistMatrixWriteProxy<Field,Field,MC,MR> NProx( NPre ); auto& A = AProx.Get(); auto& N = NProx.Get(); // Get the EVD of A typedef Base<Field> Real; const Grid& g = A.Grid(); DistMatrix<Real,VR,STAR> w(g); DistMatrix<Field> Q(g); auto ctrlMod( ctrl ); ctrlMod.tridiagEigCtrl.sort = UNSORTED; HermitianEig( uplo, A, w, Q, ctrlMod ); const Int n = A.Height(); const Int numLocalEigs = w.LocalHeight(); DistMatrix<Real,VR,STAR> wSgn(g), wAbs(g); wSgn.AlignWith( w ); wAbs.AlignWith( w ); wSgn.Resize( n, 1 ); wAbs.Resize( n, 1 ); for( Int iLoc=0; iLoc<numLocalEigs; ++iLoc ) { const Real omega = w.GetLocal(iLoc,0); if( omega >= 0 ) { wSgn.SetLocal(iLoc,0,Real(1)); wAbs.SetLocal(iLoc,0,omega); } else { wSgn.SetLocal(iLoc,0,Real(-1)); wAbs.SetLocal(iLoc,0,-omega); } } // Form the Hermitian matrix with the modified eigenvalues HermitianFromEVD( uplo, A, wSgn, Q ); HermitianFromEVD( uplo, N, wAbs, Q ); }
void HermitianPseudoinverse ( UpperOrLower uplo, Matrix<F>& A, Base<F> tolerance ) { DEBUG_CSE typedef Base<F> Real; // Get the EVD of A // TODO: Use a relative eigenvalue lower bound Matrix<Real> w; Matrix<F> Z; HermitianEig( uplo, A, w, Z ); if( tolerance == Real(0) ) { // Set the tolerance equal to n ||A||_2 eps const Int n = Z.Height(); const Real eps = limits::Epsilon<Real>(); const Real twoNorm = MaxNorm( w ); tolerance = n*twoNorm*eps; } // Invert above the tolerance auto omegaMap = [=]( Real omega ) { return ( omega < tolerance ? Real(0) : 1/omega ); }; EntrywiseMap( w, function<Real(Real)>(omegaMap) ); // Form the pseudoinverse HermitianFromEVD( uplo, A, w, Z ); }
void HermitianSign ( UpperOrLower uplo, Matrix<Field>& A, const HermitianEigCtrl<Field>& ctrl ) { EL_DEBUG_CSE typedef Base<Field> Real; // Get the EVD of A Matrix<Real> w; Matrix<Field> Q; auto ctrlMod( ctrl ); ctrlMod.tridiagEigCtrl.sort = UNSORTED; HermitianEig( uplo, A, w, Q, ctrlMod ); const Int n = A.Height(); for( Int i=0; i<n; ++i ) { const Real omega = w(i); if( omega >= 0 ) w(i) = Real(1); else w(i) = Real(-1); } // Reform the Hermitian matrix with the modified eigenvalues HermitianFromEVD( uplo, A, w, Q ); }
void HermitianPseudoinverse ( UpperOrLower uplo, ElementalMatrix<F>& APre, Base<F> tolerance ) { DEBUG_CSE typedef Base<F> Real; DistMatrixReadWriteProxy<F,F,MC,MR> AProx( APre ); auto& A = AProx.Get(); const Grid& g = A.Grid(); // Get the EVD of A // TODO: Use a relative eigenvalue lower-bound DistMatrix<Real,VR,STAR> w(g); DistMatrix<F> Z(g); HermitianEig( uplo, A, w, Z ); if( tolerance == Real(0) ) { // Set the tolerance equal to n ||A||_2 eps const Int n = Z.Height(); const Real eps = limits::Epsilon<Real>(); const Real twoNorm = MaxNorm( w ); tolerance = n*twoNorm*eps; } // Invert above the tolerance auto omegaMap = [=]( Real omega ) { return ( omega < tolerance ? Real(0) : 1/omega ); }; EntrywiseMap( w, function<Real(Real)>(omegaMap) ); // Form the pseudoinverse HermitianFromEVD( uplo, A, w, Z ); }
void HermitianSign ( UpperOrLower uplo, ElementalMatrix<F>& APre, const HermitianEigCtrl<F>& ctrl ) { DEBUG_CSE DistMatrixReadWriteProxy<F,F,MC,MR> AProx( APre ); auto& A = AProx.Get(); // Get the EVD of A typedef Base<F> Real; const Grid& g = A.Grid(); DistMatrix<Real,VR,STAR> w(g); DistMatrix<F> Q(g); auto ctrlMod( ctrl ); ctrlMod.tridiagEigCtrl.sort = UNSORTED; HermitianEig( uplo, A, w, Q, ctrlMod ); const Int numLocalEigs = w.LocalHeight(); for( Int iLoc=0; iLoc<numLocalEigs; ++iLoc ) { const Real omega = w.GetLocal(iLoc,0); if( omega >= 0 ) w.SetLocal(iLoc,0,Real(1)); else w.SetLocal(iLoc,0,Real(-1)); } // Reform the Hermitian matrix with the modified eigenvalues HermitianFromEVD( uplo, A, w, Q ); }
inline Matrix<F> HermitianFromEVD ( UpperOrLower uplo, const Matrix<BASE(F)>& w, const Matrix<F>& Z ) { Matrix<F> A; HermitianFromEVD( uplo, A, w, Z ); return A; }
void HermitianSign ( UpperOrLower uplo, Matrix<Field>& A, Matrix<Field>& N, const HermitianEigCtrl<Field>& ctrl ) { EL_DEBUG_CSE typedef Base<Field> Real; // Get the EVD of A Matrix<Real> w; Matrix<Field> Q; auto ctrlMod( ctrl ); ctrlMod.tridiagEigCtrl.sort = UNSORTED; HermitianEig( uplo, A, w, Q, ctrlMod ); const Int n = A.Height(); Matrix<Real> wSgn( n, 1 ), wAbs( n, 1 ); for( Int i=0; i<n; ++i ) { const Real omega = w(i); if( omega >= 0 ) { wSgn(i) = Real(1); wAbs(i) = omega; } else { wSgn(i) = Real(-1); wAbs(i) = -omega; } } // Form the Hermitian matrices with modified eigenvalues HermitianFromEVD( uplo, A, wSgn, Q ); HermitianFromEVD( uplo, N, wAbs, Q ); }
void SVD( Matrix<F>& A, Matrix<F>& P ) { DEBUG_CSE typedef Base<F> Real; // Get the SVD of A Matrix<Real> s; Matrix<F> U, V; SVDCtrl<Real> ctrl; ctrl.overwrite = true; El::SVD( A, U, s, V, ctrl ); // Form Q := U V^H in A Gemm( NORMAL, ADJOINT, F(1), U, V, A ); // Form P := V Sigma V^H in P HermitianFromEVD( LOWER, P, s, V ); }
void SVD( ElementalMatrix<F>& APre, ElementalMatrix<F>& PPre ) { DEBUG_CSE typedef Base<F> Real; DistMatrixReadWriteProxy<F,F,MC,MR> AProx( APre ); DistMatrixWriteProxy<F,F,MC,MR> PProx( PPre ); auto& A = AProx.Get(); auto& P = PProx.Get(); const Grid& g = A.Grid(); // Get the SVD of A DistMatrix<Real,VR,STAR> s(g); DistMatrix<F> U(g), V(g); SVDCtrl<Real> ctrl; ctrl.overwrite = true; El::SVD( A, U, s, V, ctrl ); // Form Q := U V^H in A Gemm( NORMAL, ADJOINT, F(1), U, V, A ); // Form P := V Sigma V^H in P HermitianFromEVD( LOWER, P, s, V ); }