inline void Hanowa( DistMatrix<T,U,V>& A, int n, T mu ) { #ifndef RELEASE CallStackEntry entry("Hanowa"); #endif if( n % 2 != 0 ) throw std::logic_error("n must be an even integer"); A.ResizeTo( n, n ); const int m = n/2; std::vector<T> d(m); DistMatrix<T,U,V> ABlock( A.Grid() ); for( int j=0; j<m; ++j ) d[j] = mu; View( ABlock, A, 0, 0, m, m ); Diagonal( ABlock, d ); View( ABlock, A, m, m, m, m ); Diagonal( ABlock, d ); for( int j=0; j<m; ++j ) d[j] = -(j+1); View( ABlock, A, 0, m, m, m ); Diagonal( ABlock, d ); for( int j=0; j<m; ++j ) d[j] = j+1; View( ABlock, A, m, 0, m, m ); Diagonal( ABlock, d ); }
void MakeExtendedKahan ( ElementalMatrix<F>& A, Base<F> phi, Base<F> mu ) { EL_DEBUG_CSE typedef Base<F> Real; if( A.Height() != A.Width() ) LogicError("Extended Kahan matrices must be square"); const Int n = A.Height(); if( n % 3 != 0 ) LogicError("Dimension must be an integer multiple of 3"); const Int l = n / 3; if( !l || (l & (l-1)) ) LogicError("n/3 is not a power of two"); Int k=0; while( Int(1u<<k) < l ) ++k; if( phi <= Real(0) || phi >= Real(1) ) LogicError("phi must be in (0,1)"); if( mu <= Real(0) || mu >= Real(1) ) LogicError("mu must be in (0,1)"); // Start by setting A to the identity, and then modify the necessary // l x l blocks of its 3 x 3 partitioning. MakeIdentity( A ); unique_ptr<ElementalMatrix<F>> ABlock( A.Construct(A.Grid(),A.Root()) ); View( *ABlock, A, IR(2*l,3*l), IR(2*l,3*l) ); *ABlock *= mu; View( *ABlock, A, IR(0,l), IR(l,2*l) ); Walsh( *ABlock, k ); *ABlock *= -phi; View( *ABlock, A, IR(l,2*l), IR(2*l,3*l) ); Walsh( *ABlock, k ); *ABlock *= phi; // Now scale A by S const Real zeta = Sqrt(Real(1)-phi*phi); auto& ALoc = A.Matrix(); for( Int iLoc=0; iLoc<A.LocalHeight(); ++iLoc ) { const Int i = A.GlobalRow(iLoc); const Real gamma = Pow(zeta,Real(i)); for( Int jLoc=0; jLoc<A.LocalWidth(); ++jLoc ) ALoc(iLoc,jLoc) *= gamma; } }