void SortAndFilter ( Matrix<Base<F>>& w, Matrix<F>& Q, const HermitianTridiagEigCtrl<Base<F>>& ctrl ) { const Int n = w.Height(); if( ctrl.subset.indexSubset ) { auto sortPairs = TaggedSort( w, ctrl.sort ); for( Int j=0; j<n; ++j ) w(j) = sortPairs[j].value; ApplyTaggedSortToEachRow( sortPairs, Q ); auto wCopy = w; auto QCopy = Q; w = wCopy(IR(ctrl.subset.lowerIndex,ctrl.subset.upperIndex+1),ALL); Q = QCopy(ALL,IR(ctrl.subset.lowerIndex,ctrl.subset.upperIndex+1)); } else if( ctrl.subset.rangeSubset ) { Int numValid = 0; for( Int j=0; j<n; ++j ) if( w(j) > ctrl.subset.lowerBound && w(j) <= ctrl.subset.upperBound ) ++numValid; // TODO(poulson): Avoid unnecessary extra matrix for Q Matrix<Base<F>> wFilter(numValid,1); Matrix<F> QFilter(n,numValid); numValid = 0; for( Int j=0; j<n; ++j ) { if( w(j) > ctrl.subset.lowerBound && w(j) <= ctrl.subset.upperBound ) { wFilter(numValid) = w(j); auto qFilterCol = QFilter(ALL,IR(numValid)); qFilterCol = Q(ALL,IR(j)); ++numValid; } } w = wFilter; Q = QFilter; auto sortPairs = TaggedSort( w, ctrl.sort ); for( Int j=0; j<numValid; ++j ) w(j) = sortPairs[j].value; ApplyTaggedSortToEachRow( sortPairs, Q ); } else { auto sortPairs = TaggedSort( w, ctrl.sort ); for( Int j=0; j<n; ++j ) w(j) = sortPairs[j].value; ApplyTaggedSortToEachRow( sortPairs, Q ); } }
namespace El { // This routine is slightly more general than necessary (complex support) so // that it may also be used for sorting Hermitian eigenpairs namespace herm_eig { template<typename F> void Sort( Matrix<Base<F>>& w, Matrix<F>& Z, SortType sort ) { DEBUG_ONLY(CSE cse("herm_eig::Sort")) if( sort == UNSORTED ) return; // Initialize the pairs of indices and eigenvalues typedef Base<F> Real; vector<ValueInt<Real>> pairs = TaggedSort( w, sort ); // Reorder the eigenvectors and eigenvalues using the new ordering const Int n = Z.Height(); const Int k = Z.Width(); Matrix<F> ZPerm( n, k ); for( Int j=0; j<k; ++j ) { const Int source = pairs[j].index; MemCopy( ZPerm.Buffer(0,j), Z.LockedBuffer(0,source), n ); w.Set(j,0,pairs[j].value); } Z = ZPerm; } template<typename Real,typename F>
void SortAndFilter ( AbstractDistMatrix<Base<F>>& wPre, AbstractDistMatrix<F>& QPre, const HermitianTridiagEigCtrl<Base<F>>& ctrl ) { DEBUG_CSE typedef Base<F> Real; DistMatrixReadWriteProxy<Real,Real,STAR,STAR> wProx( wPre ); DistMatrixReadWriteProxy<F,F,VC,STAR> QProx( QPre ); auto& w = wProx.Get(); auto& Q = QProx.Get(); const Int n = w.Height(); const Grid& g = w.Grid(); if( ctrl.subset.indexSubset ) { auto sortPairs = TaggedSort( w, ctrl.sort ); for( Int j=0; j<n; ++j ) w.SetLocal( j, 0, sortPairs[j].value ); ApplyTaggedSortToEachRow( sortPairs, Q ); DistMatrix<Real,STAR,STAR> wCopy( w ); DistMatrix<F,VC,STAR> QCopy( Q ); w = wCopy(IR(ctrl.subset.lowerIndex,ctrl.subset.upperIndex+1),ALL); Q = QCopy(ALL,IR(ctrl.subset.lowerIndex,ctrl.subset.upperIndex+1)); } else if( ctrl.subset.rangeSubset ) { Int numValid = 0; for( Int j=0; j<n; ++j ) if( w.GetLocal(j,0) > ctrl.subset.lowerBound && w.GetLocal(j,0) <= ctrl.subset.upperBound ) ++numValid; DistMatrix<Real,STAR,STAR> wFilter(numValid,1,g); DistMatrix<F,VC,STAR> QFilter(n,numValid,g); numValid = 0; for( Int j=0; j<n; ++j ) { if( w.GetLocal(j,0) > ctrl.subset.lowerBound && w.GetLocal(j,0) <= ctrl.subset.upperBound ) { wFilter.SetLocal( numValid, 0, w.GetLocal(j,0) ); auto qFilterCol = QFilter(ALL,IR(numValid)); qFilterCol = Q(ALL,IR(j)); ++numValid; } } w = wFilter; Q = QFilter; auto sortPairs = TaggedSort( w, ctrl.sort ); for( Int j=0; j<numValid; ++j ) w.SetLocal( j, 0, sortPairs[j].value ); ApplyTaggedSortToEachRow( sortPairs, Q ); } else { auto sortPairs = TaggedSort( w, ctrl.sort ); for( Int j=0; j<n; ++j ) w.SetLocal( j, 0, sortPairs[j].value ); ApplyTaggedSortToEachRow( sortPairs, Q ); } }