HessenbergSchurInfo RedundantlyHandleWindow ( DistMatrix<Field,MC,MR,BLOCK>& H, DistMatrix<Complex<Base<Field>>,STAR,STAR>& w, DistMatrix<Field,MC,MR,BLOCK>& Z, const HessenbergSchurCtrl& ctrl ) { EL_DEBUG_CSE const Int n = H.Height(); const Int winBeg = ( ctrl.winBeg==END ? n : ctrl.winBeg ); const Int winEnd = ( ctrl.winEnd==END ? n : ctrl.winEnd ); // TODO(poulson): Fill this information structure HessenbergSchurInfo info; const auto winInd = IR(winBeg,winEnd); auto HWin = H(winInd,winInd); auto wWin = w(winInd,ALL); // Compute the Schur decomposition HWin = ZWin TWin ZWin', // where HWin is overwritten by TWin, and wWin by diag(TWin). Matrix<Field> ZWin; ConsistentlyComputeDecomposition( HWin, wWin, ZWin ); if( ctrl.fullTriangle ) { if( n > winEnd ) { // Overwrite H(winInd,winEnd:n) *= ZWin' // (applied from the left) auto HRight = H( winInd, IR(winEnd,n) ); TransformRows( ZWin, HRight ); } // Overwrite H(0:winBeg,winInd) *= ZWin auto HTop = H( IR(0,winBeg), winInd ); TransformColumns( ZWin, HTop ); } if( ctrl.wantSchurVecs ) { // Overwrite Z(:,winInd) *= ZWin auto ZBlock = Z( ALL, winInd ); TransformColumns( ZWin, ZBlock ); } return info; }
void TransformRows ( const Matrix<F>& V, DistMatrix<F,MC,MR,BLOCK>& A ) { DEBUG_CSE const Int height = A.Height(); const Grid& grid = A.Grid(); const Int blockHeight = A.BlockHeight(); const Int firstBlockHeight = blockHeight - A.ColCut(); if( height <= firstBlockHeight || grid.Height() == 1 ) { if( grid.Row() == A.RowOwner(0) ) { // This process row can locally update its portion of A TransformRows( V, A.Matrix() ); } } else if( height <= firstBlockHeight + blockHeight ) { const int firstRow = A.RowOwner( 0 ); const int secondRow = A.RowOwner( firstBlockHeight ); if( grid.Row() == firstRow ) { // // Replace A with // // | VLeft, VRight |' | ATop |, // | ABottom | // // where ATop is owned by this process row and ABottom by the next. // auto VLeft = V( ALL, IR(0,firstBlockHeight) ); // Partition space for the combined matrix Matrix<F> ACombine( height, A.LocalWidth() ); auto ATop = ACombine( IR(0,firstBlockHeight), ALL ); auto ABottom = ACombine( IR(firstBlockHeight,END), ALL ); // Copy our portion into the combined matrix ATop = A.LockedMatrix(); // Exchange the data El::SendRecv( ATop, ABottom, A.ColComm(), secondRow, secondRow ); // Form our portion of the result Gemm( ADJOINT, NORMAL, F(1), VLeft, ACombine, A.Matrix() ); } else if( grid.Row() == secondRow ) { // // Replace A with // // | VLeft, VRight |' | ATop |, // | ABottom | // // where ATop is owned by the previous process row and ABottom by // this one. // auto VRight = V( ALL, IR(firstBlockHeight,END) ); // Partition space for the combined matrix Matrix<F> ACombine( height, A.LocalWidth() ); auto ATop = ACombine( IR(0,firstBlockHeight), ALL ); auto ABottom = ACombine( IR(firstBlockHeight,END), ALL ); // Copy our portion into the combined matrix ABottom = A.LockedMatrix(); // Exchange the data El::SendRecv( ABottom, ATop, A.ColComm(), firstRow, firstRow ); // Form our portion of the result Gemm( ADJOINT, NORMAL, F(1), VRight, ACombine, A.Matrix() ); } } else { // Fall back to the entire process column interacting. // TODO(poulson): Only form the subset of the result that we need. DistMatrix<F,STAR,MR,BLOCK> A_STAR_MR( A ); Matrix<F> ALocCopy( A_STAR_MR.Matrix() ); Gemm( ADJOINT, NORMAL, F(1), V, ALocCopy, A_STAR_MR.Matrix() ); A = A_STAR_MR; } }