inline void HermitianSVD ( UpperOrLower uplo, DistMatrix<F>& A, DistMatrix<BASE(F),VR,STAR>& s, DistMatrix<F>& U, DistMatrix<F>& V ) { #ifndef RELEASE CallStackEntry entry("HermitianSVD"); #endif #ifdef HAVE_PMRRR typedef BASE(F) R; // Grab an eigenvalue decomposition of A HermitianEig( uplo, A, s, V ); // Redistribute the singular values into an [MR,* ] distribution const Grid& grid = A.Grid(); DistMatrix<R,MR,STAR> s_MR_STAR( grid ); s_MR_STAR.AlignWith( V.DistData() ); s_MR_STAR = s; // Set the singular values to the absolute value of the eigenvalues const Int numLocalVals = s.LocalHeight(); for( Int iLoc=0; iLoc<numLocalVals; ++iLoc ) { const R sigma = s.GetLocal(iLoc,0); s.SetLocal(iLoc,0,Abs(sigma)); } // Copy V into U (flipping the sign as necessary) U.AlignWith( V ); U.ResizeTo( V.Height(), V.Width() ); const Int localHeight = V.LocalHeight(); const Int localWidth = V.LocalWidth(); for( Int jLoc=0; jLoc<localWidth; ++jLoc ) { const R sigma = s_MR_STAR.GetLocal( jLoc, 0 ); F* UCol = U.Buffer( 0, jLoc ); const F* VCol = V.LockedBuffer( 0, jLoc ); if( sigma >= 0 ) for( Int iLoc=0; iLoc<localHeight; ++iLoc ) UCol[iLoc] = VCol[iLoc]; else for( Int iLoc=0; iLoc<localHeight; ++iLoc ) UCol[iLoc] = -VCol[iLoc]; } #else U = A; MakeHermitian( uplo, U ); SVD( U, s, V ); #endif // ifdef HAVE_PMRRR }
inline void HermitianSVD ( UpperOrLower uplo, DistMatrix<F>& A, DistMatrix<typename Base<F>::type,VR,STAR>& s, DistMatrix<F>& U, DistMatrix<F>& V ) { #ifndef RELEASE PushCallStack("HermitianSVD"); #endif typedef typename Base<F>::type R; // Grab an eigenvalue decomposition of A HermitianEig( uplo, A, s, V ); // Redistribute the singular values into an [MR,* ] distribution const Grid& grid = A.Grid(); DistMatrix<R,MR,STAR> s_MR_STAR( grid ); s_MR_STAR.AlignWith( V ); s_MR_STAR = s; // Set the singular values to the absolute value of the eigenvalues const int numLocalVals = s.LocalHeight(); for( int iLocal=0; iLocal<numLocalVals; ++iLocal ) { const R sigma = s.GetLocal(iLocal,0); s.SetLocal(iLocal,0,Abs(sigma)); } // Copy V into U (flipping the sign as necessary) U.AlignWith( V ); U.ResizeTo( V.Height(), V.Width() ); const int localHeight = V.LocalHeight(); const int localWidth = V.LocalWidth(); for( int jLocal=0; jLocal<localWidth; ++jLocal ) { const R sigma = s_MR_STAR.GetLocal( jLocal, 0 ); F* UCol = U.LocalBuffer( 0, jLocal ); const F* VCol = V.LockedLocalBuffer( 0, jLocal ); if( sigma >= 0 ) for( int iLocal=0; iLocal<localHeight; ++iLocal ) UCol[iLocal] = VCol[iLocal]; else for( int iLocal=0; iLocal<localHeight; ++iLocal ) UCol[iLocal] = -VCol[iLocal]; } #ifndef RELEASE PopCallStack(); #endif }