void UUnb( Matrix<F>& A, Matrix<F>& householderScalars ) { DEBUG_CSE const Int n = A.Height(); const Int householderScalarsHeight = Max(n-1,0); householderScalars.Resize( householderScalarsHeight, 1 ); // Temporary products Matrix<F> x1, x12Adj; for( Int k=0; k<n-1; ++k ) { const Range<Int> ind1( k, k+1 ), ind2( k+1, n ); auto a21 = A( ind2, ind1 ); auto A22 = A( ind2, ind2 ); auto A2 = A( IR(0,n), ind2 ); auto alpha21T = A( IR(k+1,k+2), ind1 ); auto a21B = A( IR(k+2,n), ind1 ); // Find tau and v such that // / I - tau | 1 | | 1, v^H | \ | alpha21T | = | beta | // \ | v | / | a21B | | 0 | const F tau = LeftReflector( alpha21T, a21B ); householderScalars(k) = tau; // Temporarily set a21 := | 1 | // | v | const F beta = alpha21T(0); alpha21T(0) = F(1); // A2 := A2 Hous(a21,tau)^H // = A2 (I - conj(tau) a21 a21^H) // = A2 - conj(tau) (A2 a21) a21^H // ----------------------------------- // x1 := A2 a21 Zeros( x1, n, 1 ); Gemv( NORMAL, F(1), A2, a21, F(0), x1 ); // A2 := A2 - conj(tau) x1 a21^H Ger( -Conj(tau), x1, a21, A2 ); // A22 := Hous(a21,tau) A22 // = (I - tau a21 a21^H) A22 // = A22 - tau a21 (A22^H a21)^H // ---------------------------------- // x12^H := (a21^H A22)^H = A22^H a21 Zeros( x12Adj, A22.Width(), 1 ); Gemv( ADJOINT, F(1), A22, a21, F(0), x12Adj ); // A22 := A22 - tau a21 x12 Ger( -tau, a21, x12Adj, A22 ); // Put beta back alpha21T(0) = beta; } }
inline void MakeNormalUniformSpectrum ( Matrix<Complex<R> >& A, Complex<R> center, R radius ) { #ifndef RELEASE PushCallStack("MakeNormalUniformSpectrum"); #endif typedef Complex<R> C; if( A.Height() != A.Width() ) throw std::logic_error("Cannot make a non-square matrix normal"); // Sample the diagonal matrix D from the ball B_radius(center) // and then rotate it with a random Householder similarity transformation: // // (I-2uu^H) D (I-2uu^H)^H = D - 2(u (conj(D) u)^H + (D u) u^H) + // (4 u^H D u) u u^H // // Form d and D const int n = A.Height(); std::vector<C> d( n ); for( int j=0; j<n; ++j ) d[j] = center + radius*SampleUnitBall<C>(); Diagonal( d, A ); // Form u Matrix<C> u( n, 1 ); MakeUniform( u ); const R origNorm = Nrm2( u ); Scale( 1/origNorm, u ); // Form v := D u Matrix<C> v( n, 1 ); for( int i=0; i<n; ++i ) v.Set( i, 0, d[i]*u.Get(i,0) ); // Form w := conj(D) u Matrix<C> w( n, 1 ); for( int i=0; i<n; ++i ) w.Set( i, 0, Conj(d[i])*u.Get(i,0) ); // Update A := A - 2(u w^H + v u^H) Ger( C(-2), u, w, A ); Ger( C(-2), v, u, A ); // Form \gamma := 4 u^H (D u) = 4 (u,Du) const C gamma = 4*Dot(u,v); // Update A := A + gamma u u^H Ger( gamma, u, u, A ); #ifndef RELEASE PopCallStack(); #endif }
inline void Gerc ( T alpha, const DistMatrix<T>& x, const DistMatrix<T>& y, DistMatrix<T>& A ) { Ger( alpha, x, y, A ); }
inline void LocalGer ( T alpha, const DistMatrix<T,xColDist,xRowDist>& x, const DistMatrix<T,yColDist,yRowDist>& y, DistMatrix<T,AColDist,ARowDist>& A ) { DEBUG_ONLY(CallStackEntry cse("LocalGer")) // TODO: Add error checking here Ger( alpha, x.LockedMatrix(), y.LockedMatrix(), A.Matrix() ); }
void PanelHouseholder ( Matrix<F>& A, Matrix<F>& householderScalars, Matrix<Base<F>>& signature ) { DEBUG_CSE typedef Base<F> Real; const Int m = A.Height(); const Int n = A.Width(); const Int minDim = Min(m,n); householderScalars.Resize( minDim, 1 ); signature.Resize( minDim, 1 ); Matrix<F> z21; for( Int k=0; k<minDim; ++k ) { const Range<Int> ind1( k ), ind2( k+1, END ), indR( k, n ); F& alpha11 = A(k,k); auto a12 = A( ind1, ind2 ); auto a1R = A( ind1, indR ); auto A2R = A( ind2, indR ); // Find tau and v such that // |alpha11 a12| /I - tau |1 | |1 conj(v)|\ = |beta 0| // \ |v^T| / const F tau = RightReflector( alpha11, a12 ); householderScalars(k) = tau; // Temporarily set a1R = | 1 v | const F alpha = alpha11; alpha11 = 1; // A2R := A2R Hous(a1R^T,tau) // = A2R (I - tau a1R^T conj(a1R)) // = A2R - tau (A2R a1R^T) conj(a1R) Zeros( z21, A2R.Height(), 1 ); Gemv( NORMAL, F(1), A2R, a1R, F(0), z21 ); Ger( -tau, z21, a1R, A2R ); // Reset alpha11's value alpha11 = alpha; } // Form d and rescale L auto L = A( ALL, IR(0,minDim) ); GetRealPartOfDiagonal(L,signature); auto sgn = []( const Real& delta ) { return delta >= Real(0) ? Real(1) : Real(-1); }; EntrywiseMap( signature, function<Real(Real)>(sgn) ); DiagonalScaleTrapezoid( RIGHT, LOWER, NORMAL, signature, L ); }
inline void LocalGer ( T alpha, const DistMatrix<T,xColDist,xRowDist>& x, const DistMatrix<T,yColDist,yRowDist>& y, DistMatrix<T,AColDist,ARowDist>& A ) { #ifndef RELEASE CallStackEntry entry("LocalGer"); // TODO: Add error checking here #endif Ger( alpha, x.LockedMatrix(), y.LockedMatrix(), A.Matrix() ); }
inline void PanelQR( Matrix<Real>& A ) { #ifndef RELEASE PushCallStack("internal::PanelQR"); #endif Matrix<Real> ATL, ATR, A00, a01, A02, aLeftCol, ARightPan, ABL, ABR, a10, alpha11, a12, A20, a21, A22; Matrix<Real> z; PushBlocksizeStack( 1 ); PartitionDownLeftDiagonal ( A, ATL, ATR, ABL, ABR, 0 ); while( ATL.Height() < A.Height() && ATL.Width() < A.Width() ) { RepartitionDownDiagonal ( ATL, /**/ ATR, A00, /**/ a01, A02, /*************/ /**********************/ /**/ a10, /**/ alpha11, a12, ABL, /**/ ABR, A20, /**/ a21, A22 ); aLeftCol.View2x1( alpha11, a21 ); ARightPan.View2x1( a12, A22 ); Zeros( ARightPan.Width(), 1, z ); //--------------------------------------------------------------------// const Real tau = Reflector( alpha11, a21 ); const Real alpha = alpha11.Get(0,0); alpha11.Set(0,0,1); Gemv( TRANSPOSE, Real(1), ARightPan, aLeftCol, Real(0), z ); Ger( -tau, aLeftCol, z, ARightPan ); alpha11.Set(0,0,alpha); //--------------------------------------------------------------------// SlidePartitionDownDiagonal ( ATL, /**/ ATR, A00, a01, /**/ A02, /**/ a10, alpha11, /**/ a12, /*************/ /**********************/ ABL, /**/ ABR, A20, a21, /**/ A22 ); } PopBlocksizeStack(); #ifndef RELEASE PopCallStack(); #endif }
// Describes how to run the CLBlast routine static StatusCode RunRoutine(const Arguments<T> &args, Buffers<T> &buffers, Queue &queue) { auto queue_plain = queue(); auto event = cl_event{}; auto status = Ger(args.layout, args.m, args.n, args.alpha, buffers.x_vec(), args.x_offset, args.x_inc, buffers.y_vec(), args.y_offset, args.y_inc, buffers.a_mat(), args.a_offset, args.a_ld, &queue_plain, &event); if (status == StatusCode::kSuccess) { clWaitForEvents(1, &event); clReleaseEvent(event); } return status; }
inline void PanelLQ( Matrix<Real>& A ) { #ifndef RELEASE PushCallStack("internal::PanelLQ"); #endif Matrix<Real> ATL, ATR, A00, a01, A02, aTopRow, ABottomPan, ABL, ABR, a10, alpha11, a12, A20, a21, A22; Matrix<Real> z; PushBlocksizeStack( 1 ); PartitionDownLeftDiagonal ( A, ATL, ATR, ABL, ABR, 0 ); while( ATL.Height() < A.Height() && ATL.Width() < A.Width() ) { RepartitionDownDiagonal ( ATL, /**/ ATR, A00, /**/ a01, A02, /*************/ /**********************/ /**/ a10, /**/ alpha11, a12, ABL, /**/ ABR, A20, /**/ a21, A22 ); aTopRow.View1x2( alpha11, a12 ); ABottomPan.View1x2( a21, A22 ); Zeros( ABottomPan.Height(), 1, z ); //--------------------------------------------------------------------// const Real tau = Reflector( alpha11, a12 ); const Real alpha = alpha11.Get(0,0); alpha11.Set(0,0,1); Gemv( NORMAL, Real(1), ABottomPan, aTopRow, Real(0), z ); Ger( -tau, z, aTopRow, ABottomPan ); alpha11.Set(0,0,alpha); //--------------------------------------------------------------------// SlidePartitionDownDiagonal ( ATL, /**/ ATR, A00, a01, /**/ A02, /**/ a10, alpha11, /**/ a12, /*************/ /**********************/ ABL, /**/ ABR, A20, a21, /**/ A22 ); } PopBlocksizeStack(); #ifndef RELEASE PopCallStack(); #endif }
inline void PanelHouseholder( Matrix<F>& A, Matrix<F>& t ) { #ifndef RELEASE CallStackEntry entry("lq::PanelHouseholder"); if( t.Height() != Min(A.Height(),A.Width()) || t.Width() != 1 ) LogicError ("t must be a vector of height equal to the minimum dimension of A"); #endif Matrix<F> ATL, ATR, A00, a01, A02, aTopRow, ABottomPan, ABL, ABR, a10, alpha11, a12, A20, a21, A22; Matrix<F> tT, t0, tB, tau1, t2; Matrix<F> z, aTopRowConj; PartitionDownDiagonal ( A, ATL, ATR, ABL, ABR, 0 ); PartitionDown ( t, tT, tB, 0 ); while( ATL.Height() < A.Height() && ATL.Width() < A.Width() ) { RepartitionDownDiagonal ( ATL, /**/ ATR, A00, /**/ a01, A02, /*************/ /**********************/ /**/ a10, /**/ alpha11, a12, ABL, /**/ ABR, A20, /**/ a21, A22, 1 ); RepartitionDown ( tT, t0, /**/ /****/ tau1, tB, t2, 1 ); View1x2( aTopRow, alpha11, a12 ); View1x2( ABottomPan, a21, A22 ); //--------------------------------------------------------------------// // Compute the Householder reflector const F tau = Reflector( alpha11, a12 ); tau1.Set( 0, 0, tau ); // Apply the Householder reflector const F alpha = alpha11.Get(0,0); alpha11.Set(0,0,1); Conjugate( aTopRow, aTopRowConj ); Zeros( z, ABottomPan.Height(), 1 ); Gemv( NORMAL, F(1), ABottomPan, aTopRowConj, F(0), z ); Ger( -Conj(tau), z, aTopRowConj, ABottomPan ); alpha11.Set(0,0,alpha); //--------------------------------------------------------------------// SlidePartitionDown ( tT, t0, tau1, /**/ /****/ tB, t2 ); SlidePartitionDownDiagonal ( ATL, /**/ ATR, A00, a01, /**/ A02, /**/ a10, alpha11, /**/ a12, /*************/ /**********************/ ABL, /**/ ABR, A20, a21, /**/ A22 ); } }
inline void PanelHouseholder( DistMatrix<F>& A, DistMatrix<F,MD,STAR>& t ) { #ifndef RELEASE CallStackEntry entry("lq::PanelHouseholder"); if( A.Grid() != t.Grid() ) LogicError("{A,t} must be distributed over the same grid"); if( t.Height() != Min(A.Height(),A.Width()) || t.Width() != 1 ) LogicError ("t must be a vector of height equal to the minimum dimension of A"); if( !t.AlignedWithDiagonal( A, 0 ) ) LogicError("t must be aligned with A's main diagonal"); #endif const Grid& g = A.Grid(); // Matrix views DistMatrix<F> ATL(g), ATR(g), A00(g), a01(g), A02(g), aTopRow(g), ABottomPan(g), ABL(g), ABR(g), a10(g), alpha11(g), a12(g), A20(g), a21(g), A22(g); DistMatrix<F,MD,STAR> tT(g), t0(g), tB(g), tau1(g), t2(g); // Temporary distributions DistMatrix<F> aTopRowConj(g); DistMatrix<F,STAR,MR > aTopRowConj_STAR_MR(g); DistMatrix<F,MC, STAR> z_MC_STAR(g); PartitionDownDiagonal ( A, ATL, ATR, ABL, ABR, 0 ); PartitionDown ( t, tT, tB, 0 ); while( ATL.Height() < A.Height() && ATL.Width() < A.Width() ) { RepartitionDownDiagonal ( ATL, /**/ ATR, A00, /**/ a01, A02, /*************/ /**********************/ /**/ a10, /**/ alpha11, a12, ABL, /**/ ABR, A20, /**/ a21, A22, 1 ); RepartitionDown ( tT, t0, /**/ /****/ tau1, tB, t2, 1 ); View1x2( aTopRow, alpha11, a12 ); View1x2( ABottomPan, a21, A22 ); aTopRowConj_STAR_MR.AlignWith( ABottomPan ); z_MC_STAR.AlignWith( ABottomPan ); //--------------------------------------------------------------------// // Compute the Householder reflector const F tau = Reflector( alpha11, a12 ); tau1.Set( 0, 0, tau ); // Apply the Householder reflector const bool myDiagonalEntry = ( g.Row() == alpha11.ColAlignment() && g.Col() == alpha11.RowAlignment() ); F alpha = 0; if( myDiagonalEntry ) { alpha = alpha11.GetLocal(0,0); alpha11.SetLocal(0,0,1); } Conjugate( aTopRow, aTopRowConj ); aTopRowConj_STAR_MR = aTopRowConj; Zeros( z_MC_STAR, ABottomPan.Height(), 1 ); LocalGemv ( NORMAL, F(1), ABottomPan, aTopRowConj_STAR_MR, F(0), z_MC_STAR ); z_MC_STAR.SumOverRow(); Ger ( -Conj(tau), z_MC_STAR.LockedMatrix(), aTopRowConj_STAR_MR.LockedMatrix(), ABottomPan.Matrix() ); if( myDiagonalEntry ) alpha11.SetLocal(0,0,alpha); //--------------------------------------------------------------------// SlidePartitionDown ( tT, t0, tau1, /**/ /****/ tB, t2 ); SlidePartitionDownDiagonal ( ATL, /**/ ATR, A00, a01, /**/ A02, /**/ a10, alpha11, /**/ a12, /*************/ /**********************/ ABL, /**/ ABR, A20, a21, /**/ A22 ); } }
inline void Ger ( T alpha, const DistMatrix<T>& x, const DistMatrix<T>& y, DistMatrix<T>& A ) { #ifndef RELEASE CallStackEntry entry("Ger"); if( A.Grid() != x.Grid() || x.Grid() != y.Grid() ) LogicError ("{A,x,y} must be distributed over the same grid"); if( ( x.Width() != 1 && x.Height() != 1 ) || ( y.Width() != 1 && y.Height() != 1 ) ) LogicError("x and y are assumed to be vectors"); const Int xLength = ( x.Width()==1 ? x.Height() : x.Width() ); const Int yLength = ( y.Width()==1 ? y.Height() : y.Width() ); if( A.Height() != xLength || A.Width() != yLength ) { std::ostringstream msg; msg << "Nonconformal Ger: \n" << " A ~ " << A.Height() << " x " << A.Width() << "\n" << " x ~ " << x.Height() << " x " << x.Width() << "\n" << " y ~ " << y.Height() << " x " << y.Width() << "\n"; LogicError( msg.str() ); } #endif const Grid& g = A.Grid(); if( x.Width() == 1 && y.Width() == 1 ) { // Temporary distributions DistMatrix<T,MC,STAR> x_MC_STAR(g); DistMatrix<T,MR,STAR> y_MR_STAR(g); // Begin the algoritm x_MC_STAR.AlignWith( A ); y_MR_STAR.AlignWith( A ); //--------------------------------------------------------------------// x_MC_STAR = x; y_MR_STAR = y; Ger ( alpha, x_MC_STAR.LockedMatrix(), y_MR_STAR.LockedMatrix(), A.Matrix() ); //--------------------------------------------------------------------// } else if( x.Width() == 1 ) { // Temporary distributions DistMatrix<T,MC, STAR> x_MC_STAR(g); DistMatrix<T,STAR,MR > y_STAR_MR(g); // Begin the algorithm x_MC_STAR.AlignWith( A ); y_STAR_MR.AlignWith( A ); //--------------------------------------------------------------------// x_MC_STAR = x; y_STAR_MR = y; Ger ( alpha, x_MC_STAR.LockedMatrix(), y_STAR_MR.LockedMatrix(), A.Matrix() ); //--------------------------------------------------------------------// } else if( y.Width() == 1 ) { // Temporary distributions DistMatrix<T,STAR,MC > x_STAR_MC(g); DistMatrix<T,MR, STAR> y_MR_STAR(g); // Begin the algorithm x_STAR_MC.AlignWith( A ); y_MR_STAR.AlignWith( A ); //--------------------------------------------------------------------// x_STAR_MC = x; y_MR_STAR = y; Ger ( alpha, x_STAR_MC.LockedMatrix(), y_MR_STAR.LockedMatrix(), A.Matrix() ); //--------------------------------------------------------------------// } else { // Temporary distributions DistMatrix<T,STAR,MC> x_STAR_MC(g); DistMatrix<T,STAR,MR> y_STAR_MR(g); // Begin the algorithm x_STAR_MC.AlignWith( A ); y_STAR_MR.AlignWith( A ); //--------------------------------------------------------------------// x_STAR_MC = x; y_STAR_MR = y; Ger ( alpha, x_STAR_MC.LockedMatrix(), y_STAR_MR.LockedMatrix(), A.Matrix() ); //--------------------------------------------------------------------// } }
inline void MakeNormalUniformSpectrum ( DistMatrix<Complex<R>,U,V>& A, Complex<R> center=0, R radius=1 ) { #ifndef RELEASE CallStackEntry entry("MakeNormalUniformSpectrum"); #endif typedef Complex<R> C; if( A.Height() != A.Width() ) LogicError("Cannot make a non-square matrix normal"); const Grid& grid = A.Grid(); const bool standardDist = ( U == MC && V == MR ); // Sample the diagonal matrix D from the ball B_radius(center) // and then rotate it with a random Householder similarity transformation: // // (I-2uu^H) D (I-2uu^H)^H = D - 2(u (Conj(D) u)^H + (D u) u^H) + // (4 u^H D u) u u^H // // Form d and D const Int n = A.Height(); std::vector<C> d( n ); if( grid.Rank() == 0 ) for( Int j=0; j<n; ++j ) d[j] = SampleBall<C>( center, radius ); mpi::Broadcast( &d[0], n, 0, grid.Comm() ); DistMatrix<C> ABackup( grid ); if( standardDist ) Diagonal( A, d ); else { ABackup.AlignWith( A ); Diagonal( ABackup, d ); } // Form u DistMatrix<C> u( grid ); if( standardDist ) u.AlignWith( A ); else u.AlignWith( ABackup ); Uniform( u, n, 1 ); const R origNorm = Nrm2( u ); Scale( 1/origNorm, u ); // Form v := D u DistMatrix<C> v( grid ); if( standardDist ) v.AlignWith( A ); else v.AlignWith( ABackup ); v.ResizeTo( n, 1 ); if( v.LocalWidth() == 1 ) { const Int colShift = v.ColShift(); const Int colStride = v.ColStride(); const Int localHeight = v.LocalHeight(); for( Int iLoc=0; iLoc<localHeight; ++iLoc ) { const Int i = colShift + iLoc*colStride; v.SetLocal( iLoc, 0, d[i]*u.GetLocal(iLoc,0) ); } } // Form w := Conj(D) u DistMatrix<C> w( grid ); if( standardDist ) w.AlignWith( A ); else w.AlignWith( ABackup ); w.ResizeTo( n, 1 ); if( w.LocalWidth() == 1 ) { const Int colShift = w.ColShift(); const Int colStride = w.ColStride(); const Int localHeight = w.LocalHeight(); for( Int iLoc=0; iLoc<localHeight; ++iLoc ) { const Int i = colShift + iLoc*colStride; w.SetLocal( iLoc, 0, Conj(d[i])*u.GetLocal(iLoc,0) ); } } // Update A := A - 2(u w^H + v u^H) if( standardDist ) { Ger( C(-2), u, w, A ); Ger( C(-2), v, u, A ); } else { Ger( C(-2), u, w, ABackup ); Ger( C(-2), v, u, ABackup ); } // Form \gamma := 4 u^H (D u) = 4 (u,Du) const C gamma = 4*Dot(u,v); // Update A := A + gamma u u^H if( standardDist ) Ger( gamma, u, u, A ); else Ger( gamma, u, u, ABackup ); // Copy the result into the correct distribution if( !standardDist ) A = ABackup; }
inline void PanelLQ( DistMatrix<Real>& A ) { #ifndef RELEASE PushCallStack("internal::PanelLQ"); #endif const Grid& g = A.Grid(); // Matrix views DistMatrix<Real> ATL(g), ATR(g), A00(g), a01(g), A02(g), aTopRow(g), ABottomPan(g), ABL(g), ABR(g), a10(g), alpha11(g), a12(g), A20(g), a21(g), A22(g); // Temporary distributions DistMatrix<Real,STAR,MR> aTopRow_STAR_MR(g); DistMatrix<Real,MC,STAR> z_MC_STAR(g); PushBlocksizeStack( 1 ); PartitionDownLeftDiagonal ( A, ATL, ATR, ABL, ABR, 0 ); while( ATL.Height() < A.Height() && ATL.Width() < A.Width() ) { RepartitionDownDiagonal ( ATL, /**/ ATR, A00, /**/ a01, A02, /*************/ /**********************/ /**/ a10, /**/ alpha11, a12, ABL, /**/ ABR, A20, /**/ a21, A22 ); aTopRow.View1x2( alpha11, a12 ); ABottomPan.View1x2( a21, A22 ); aTopRow_STAR_MR.AlignWith( ABottomPan ); z_MC_STAR.AlignWith( ABottomPan ); Zeros( ABottomPan.Height(), 1, z_MC_STAR ); //--------------------------------------------------------------------// const Real tau = Reflector( alpha11, a12 ); const bool myDiagonalEntry = ( g.Row() == alpha11.ColAlignment() && g.Col() == alpha11.RowAlignment() ); Real alpha = 0; if( myDiagonalEntry ) { alpha = alpha11.GetLocal(0,0); alpha11.SetLocal(0,0,1); } aTopRow_STAR_MR = aTopRow; Gemv ( NORMAL, Real(1), ABottomPan.LockedLocalMatrix(), aTopRow_STAR_MR.LockedLocalMatrix(), Real(0), z_MC_STAR.LocalMatrix() ); z_MC_STAR.SumOverRow(); Ger ( -tau, z_MC_STAR.LockedLocalMatrix(), aTopRow_STAR_MR.LockedLocalMatrix(), ABottomPan.LocalMatrix() ); if( myDiagonalEntry ) alpha11.SetLocal(0,0,alpha); //--------------------------------------------------------------------// aTopRow_STAR_MR.FreeAlignments(); z_MC_STAR.FreeAlignments(); SlidePartitionDownDiagonal ( ATL, /**/ ATR, A00, a01, /**/ A02, /**/ a10, alpha11, /**/ a12, /*************/ /**********************/ ABL, /**/ ABR, A20, a21, /**/ A22 ); } PopBlocksizeStack(); #ifndef RELEASE PopCallStack(); #endif }
inline void PanelLQ ( DistMatrix<Complex<Real> >& A, DistMatrix<Complex<Real>,MD,STAR>& t ) { #ifndef RELEASE PushCallStack("internal::PanelLQ"); if( A.Grid() != t.Grid() ) throw std::logic_error("{A,t} must be distributed over the same grid"); if( t.Height() != std::min(A.Height(),A.Width()) || t.Width() != 1 ) throw std::logic_error ("t must be a vector of height equal to the minimum dimension of A"); if( !t.AlignedWithDiagonal( A, 0 ) ) throw std::logic_error("t must be aligned with A's main diagonal"); #endif typedef Complex<Real> C; const Grid& g = A.Grid(); // Matrix views DistMatrix<C> ATL(g), ATR(g), A00(g), a01(g), A02(g), aTopRow(g), ABottomPan(g), ABL(g), ABR(g), a10(g), alpha11(g), a12(g), A20(g), a21(g), A22(g); DistMatrix<C,MD,STAR> tT(g), t0(g), tB(g), tau1(g), t2(g); // Temporary distributions DistMatrix<C> aTopRowConj(g); DistMatrix<C,STAR,MR > aTopRowConj_STAR_MR(g); DistMatrix<C,MC, STAR> z_MC_STAR(g); PushBlocksizeStack( 1 ); PartitionDownLeftDiagonal ( A, ATL, ATR, ABL, ABR, 0 ); PartitionDown ( t, tT, tB, 0 ); while( ATL.Height() < A.Height() && ATL.Width() < A.Width() ) { RepartitionDownDiagonal ( ATL, /**/ ATR, A00, /**/ a01, A02, /*************/ /**********************/ /**/ a10, /**/ alpha11, a12, ABL, /**/ ABR, A20, /**/ a21, A22 ); RepartitionDown ( tT, t0, /**/ /****/ tau1, tB, t2 ); aTopRow.View1x2( alpha11, a12 ); ABottomPan.View1x2( a21, A22 ); aTopRowConj_STAR_MR.AlignWith( ABottomPan ); z_MC_STAR.AlignWith( ABottomPan ); Zeros( ABottomPan.Height(), 1, z_MC_STAR ); //--------------------------------------------------------------------// const C tau = Reflector( alpha11, a12 ); tau1.Set( 0, 0, tau ); const bool myDiagonalEntry = ( g.Row() == alpha11.ColAlignment() && g.Col() == alpha11.RowAlignment() ); C alpha = 0; if( myDiagonalEntry ) { alpha = alpha11.GetLocal(0,0); alpha11.SetLocal(0,0,1); } Conjugate( aTopRow, aTopRowConj ); aTopRowConj_STAR_MR = aTopRowConj; Gemv ( NORMAL, C(1), ABottomPan.LockedLocalMatrix(), aTopRowConj_STAR_MR.LockedLocalMatrix(), C(0), z_MC_STAR.LocalMatrix() ); z_MC_STAR.SumOverRow(); Ger ( -Conj(tau), z_MC_STAR.LockedLocalMatrix(), aTopRowConj_STAR_MR.LockedLocalMatrix(), ABottomPan.LocalMatrix() ); if( myDiagonalEntry ) alpha11.SetLocal(0,0,alpha); //--------------------------------------------------------------------// aTopRowConj_STAR_MR.FreeAlignments(); z_MC_STAR.FreeAlignments(); SlidePartitionDown ( tT, t0, tau1, /**/ /****/ tB, t2 ); SlidePartitionDownDiagonal ( ATL, /**/ ATR, A00, a01, /**/ A02, /**/ a10, alpha11, /**/ a12, /*************/ /**********************/ ABL, /**/ ABR, A20, a21, /**/ A22 ); } PopBlocksizeStack(); #ifndef RELEASE PopCallStack(); #endif }
inline void PanelLQ ( Matrix<Complex<Real> >& A, Matrix<Complex<Real> >& t ) { #ifndef RELEASE PushCallStack("internal::PanelLQ"); if( t.Height() != std::min(A.Height(),A.Width()) || t.Width() != 1 ) throw std::logic_error ("t must be a vector of height equal to the minimum dimension of A"); #endif typedef Complex<Real> C; Matrix<C> ATL, ATR, A00, a01, A02, aTopRow, ABottomPan, ABL, ABR, a10, alpha11, a12, A20, a21, A22; Matrix<C> tT, t0, tB, tau1, t2; Matrix<C> z, aTopRowConj; PushBlocksizeStack( 1 ); PartitionDownLeftDiagonal ( A, ATL, ATR, ABL, ABR, 0 ); PartitionDown ( t, tT, tB, 0 ); while( ATL.Height() < A.Height() && ATL.Width() < A.Width() ) { RepartitionDownDiagonal ( ATL, /**/ ATR, A00, /**/ a01, A02, /*************/ /**********************/ /**/ a10, /**/ alpha11, a12, ABL, /**/ ABR, A20, /**/ a21, A22 ); RepartitionDown ( tT, t0, /**/ /****/ tau1, tB, t2 ); aTopRow.View1x2( alpha11, a12 ); ABottomPan.View1x2( a21, A22 ); Zeros( ABottomPan.Height(), 1, z ); //--------------------------------------------------------------------// const C tau = Reflector( alpha11, a12 ); tau1.Set( 0, 0, tau ); const C alpha = alpha11.Get(0,0); alpha11.Set(0,0,1); Conjugate( aTopRow, aTopRowConj ); Gemv( NORMAL, C(1), ABottomPan, aTopRowConj, C(0), z ); Ger( -Conj(tau), z, aTopRowConj, ABottomPan ); alpha11.Set(0,0,alpha); //--------------------------------------------------------------------// SlidePartitionDown ( tT, t0, tau1, /**/ /****/ tB, t2 ); SlidePartitionDownDiagonal ( ATL, /**/ ATR, A00, a01, /**/ A02, /**/ a10, alpha11, /**/ a12, /*************/ /**********************/ ABL, /**/ ABR, A20, a21, /**/ A22 ); } PopBlocksizeStack(); #ifndef RELEASE PopCallStack(); #endif }