void GetMappedDiagonal ( const DistMatrix<T,U,V>& A, AbstractDistMatrix<S>& dPre, function<S(const T&)> func, Int offset ) { EL_DEBUG_CSE EL_DEBUG_ONLY(AssertSameGrids( A, dPre )) ElementalProxyCtrl ctrl; ctrl.colConstrain = true; ctrl.colAlign = A.DiagonalAlign(offset); ctrl.rootConstrain = true; ctrl.root = A.DiagonalRoot(offset); DistMatrixWriteProxy<S,S,DiagCol<U,V>(),DiagRow<U,V>()> dProx( dPre, ctrl ); auto& d = dProx.Get(); d.Resize( A.DiagonalLength(offset), 1 ); if( d.Participating() ) { const Int diagShift = d.ColShift(); const Int iStart = diagShift + Max(-offset,0); const Int jStart = diagShift + Max( offset,0); const Int colStride = A.ColStride(); const Int rowStride = A.RowStride(); const Int iLocStart = (iStart-A.ColShift()) / colStride; const Int jLocStart = (jStart-A.RowShift()) / rowStride; const Int iLocStride = d.ColStride() / colStride; const Int jLocStride = d.ColStride() / rowStride; const Int localDiagLength = d.LocalHeight(); S* dBuf = d.Buffer(); const T* ABuf = A.LockedBuffer(); const Int ldim = A.LDim(); EL_PARALLEL_FOR for( Int k=0; k<localDiagLength; ++k ) { const Int iLoc = iLocStart + k*iLocStride; const Int jLoc = jLocStart + k*jLocStride; dBuf[k] = func(ABuf[iLoc+jLoc*ldim]); } } }
void TestCorrectness ( UpperOrLower uplo, const DistMatrix<F>& A, const DistMatrix<F,STAR,STAR>& t, DistMatrix<F>& AOrig, bool print, bool display ) { typedef Base<F> Real; const Grid& g = A.Grid(); const Int m = AOrig.Height(); const Real infNormAOrig = HermitianInfinityNorm( uplo, AOrig ); const Real frobNormAOrig = HermitianFrobeniusNorm( uplo, AOrig ); if( g.Rank() == 0 ) cout << "Testing error..." << endl; // Grab the diagonal and subdiagonal of the symmetric tridiagonal matrix Int subdiagonal = ( uplo==LOWER ? -1 : +1 ); auto d = GetRealPartOfDiagonal(A); auto e = GetRealPartOfDiagonal(A,subdiagonal); // Grab a full copy of e so that we may fill the opposite subdiagonal DistMatrix<Real,STAR,STAR> e_STAR_STAR( e ); DistMatrix<Real,MD,STAR> eOpposite(g); eOpposite.SetRoot( A.DiagonalRoot(-subdiagonal) ); eOpposite.AlignCols( A.DiagonalAlign(-subdiagonal) ); eOpposite = e_STAR_STAR; // Zero B and then fill its tridiagonal DistMatrix<F> B(g); B.AlignWith( A ); Zeros( B, m, m ); SetRealPartOfDiagonal( B, d ); SetRealPartOfDiagonal( B, e, subdiagonal ); SetRealPartOfDiagonal( B, eOpposite, -subdiagonal ); if( print ) Print( B, "Tridiagonal" ); if( display ) Display( B, "Tridiagonal" ); // Reverse the accumulated Householder transforms, ignoring symmetry herm_tridiag::ApplyQ( LEFT, uplo, NORMAL, A, t, B ); herm_tridiag::ApplyQ( RIGHT, uplo, ADJOINT, A, t, B ); if( print ) Print( B, "Rotated tridiagonal" ); if( display ) Display( B, "Rotated tridiagonal" ); // Compare the appropriate triangle of AOrig and B MakeTrapezoidal( uplo, AOrig ); MakeTrapezoidal( uplo, B ); B -= AOrig; if( print ) Print( B, "Error in rotated tridiagonal" ); if( display ) Display( B, "Error in rotated tridiagonal" ); const Real infNormError = HermitianInfinityNorm( uplo, B ); const Real frobNormError = HermitianFrobeniusNorm( uplo, B ); // Compute || I - Q Q^H || MakeIdentity( B ); herm_tridiag::ApplyQ( RIGHT, uplo, ADJOINT, A, t, B ); DistMatrix<F> QHAdj( g ); Adjoint( B, QHAdj ); MakeIdentity( B ); herm_tridiag::ApplyQ( LEFT, uplo, NORMAL, A, t, B ); QHAdj -= B; herm_tridiag::ApplyQ( RIGHT, uplo, ADJOINT, A, t, B ); ShiftDiagonal( B, F(-1) ); const Real infNormQError = InfinityNorm( B ); const Real frobNormQError = FrobeniusNorm( B ); if( g.Rank() == 0 ) { cout << " ||A||_oo = " << infNormAOrig << "\n" << " ||A||_F = " << frobNormAOrig << "\n" << " || I - Q^H Q ||_oo = " << infNormQError << "\n" << " || I - Q^H Q ||_F = " << frobNormQError << "\n" << " ||A - Q T Q^H||_oo = " << infNormError << "\n" << " ||A - Q T Q^H||_F = " << frobNormError << endl; } }