Beispiel #1
0
void LUNMedium
( const AbstractDistMatrix<F>& UPre, AbstractDistMatrix<F>& XPre, 
  bool checkIfSingular )
{
    DEBUG_CSE
    const Int m = XPre.Height();
    const Int bsize = Blocksize();
    const Grid& g = UPre.Grid();

    DistMatrixReadProxy<F,F,MC,MR> UProx( UPre );
    DistMatrixReadWriteProxy<F,F,MC,MR> XProx( XPre );
    auto& U = UProx.GetLocked();
    auto& X = XProx.Get();

    DistMatrix<F,MC,  STAR> U01_MC_STAR(g);
    DistMatrix<F,STAR,STAR> U11_STAR_STAR(g);
    DistMatrix<F,MR,  STAR> X1Trans_MR_STAR(g);

    const Int kLast = LastOffset( m, bsize );
    Int k=kLast, kOld=m;
    while( true )
    {
        const bool in2x2 = ( k>0 && U.Get(k,k-1) != F(0) );
        if( in2x2 )
            --k;
        const Int nb = kOld-k;

        const Range<Int> ind0( 0, k    ),
                         ind1( k, k+nb );

        auto U01 = U( ind0, ind1 );
        auto U11 = U( ind1, ind1 );

        auto X0 = X( ind0, ALL );
        auto X1 = X( ind1, ALL );

        U11_STAR_STAR = U11; // U11[* ,* ] <- U11[MC,MR]
        X1Trans_MR_STAR.AlignWith( X0 );
        Transpose( X1, X1Trans_MR_STAR );
        
        // X1^T[MR,* ] := X1^T[MR,* ] U11^-T[* ,* ]
        //              = (U11^-1[* ,* ] X1[* ,MR])^T
        LocalQuasiTrsm
        ( RIGHT, UPPER, TRANSPOSE,
          F(1), U11_STAR_STAR, X1Trans_MR_STAR, checkIfSingular );
        Transpose( X1Trans_MR_STAR, X1 );

        U01_MC_STAR.AlignWith( X0 );
        U01_MC_STAR = U01;  // U01[MC,* ] <- U01[MC,MR]

        // X0[MC,MR] -= U01[MC,* ] X1[* ,MR]
        LocalGemm
        ( NORMAL, TRANSPOSE, F(-1), U01_MC_STAR, X1Trans_MR_STAR, F(1), X0 );

        if( k == 0 )
            break;
        kOld = k;
        k -= Min(bsize,k);
    }
}
Beispiel #2
0
bool TriangIsNormal( const ElementalMatrix<F>& UPre, Base<F> tol )
{
    DistMatrixReadProxy<F,F,MC,MR> UProx( UPre );
    auto& U = UProx.GetLocked();

    const Base<F> diagFrob = FrobeniusNorm(GetDiagonal(U));
    const Base<F> upperFrob = FrobeniusNorm( U );
    const Base<F> offDiagFrob = Sqrt(upperFrob*upperFrob-diagFrob*diagFrob);
    return offDiagFrob <= tol*diagFrob;
}
Beispiel #3
0
void LUNMedium
( UnitOrNonUnit diag, 
  const AbstractDistMatrix<F>& UPre,
        AbstractDistMatrix<F>& XPre,
  bool checkIfSingular )
{
    EL_DEBUG_CSE
    const Int m = XPre.Height();
    const Int bsize = Blocksize();
    const Grid& g = UPre.Grid();

    DistMatrixReadProxy<F,F,MC,MR> UProx( UPre );
    DistMatrixReadWriteProxy<F,F,MC,MR> XProx( XPre );
    auto& U = UProx.GetLocked();
    auto& X = XProx.Get();

    DistMatrix<F,MC,  STAR> U01_MC_STAR(g);
    DistMatrix<F,STAR,STAR> U11_STAR_STAR(g);
    DistMatrix<F,MR,  STAR> X1Trans_MR_STAR(g);

    const Int kLast = LastOffset( m, bsize );
    for( Int k=kLast; k>=0; k-=bsize )
    {
        const Int nb = Min(bsize,m-k);

        const Range<Int> ind0( 0, k    ),
                         ind1( k, k+nb );

        auto U01 = U( ind0, ind1 );
        auto U11 = U( ind1, ind1 );

        auto X0 = X( ind0, ALL );
        auto X1 = X( ind1, ALL );

        U11_STAR_STAR = U11; // U11[* ,* ] <- U11[MC,MR]
        X1Trans_MR_STAR.AlignWith( X0 );
        Transpose( X1, X1Trans_MR_STAR );
        
        // X1^T[MR,* ] := X1^T[MR,* ] U11^-T[* ,* ]
        //              = (U11^-1[* ,* ] X1[* ,MR])^T
        LocalTrsm
        ( RIGHT, UPPER, TRANSPOSE, diag, 
          F(1), U11_STAR_STAR, X1Trans_MR_STAR, checkIfSingular );
        Transpose( X1Trans_MR_STAR, X1 );

        U01_MC_STAR.AlignWith( X0 );
        U01_MC_STAR = U01;  // U01[MC,* ] <- U01[MC,MR]

        // X0[MC,MR] -= U01[MC,* ] X1[* ,MR]
        LocalGemm
        ( NORMAL, TRANSPOSE, F(-1), U01_MC_STAR, X1Trans_MR_STAR, F(1), X0 );
    }
}
Beispiel #4
0
void LUNLarge
( UnitOrNonUnit diag,
  const AbstractDistMatrix<F>& UPre,
        AbstractDistMatrix<F>& XPre, 
  bool checkIfSingular )
{
    EL_DEBUG_CSE
    const Int m = XPre.Height();
    const Int bsize = Blocksize();
    const Grid& g = UPre.Grid();

    DistMatrixReadProxy<F,F,MC,MR> UProx( UPre );
    DistMatrixReadWriteProxy<F,F,MC,MR> XProx( XPre );
    auto& U = UProx.GetLocked();
    auto& X = XProx.Get();

    DistMatrix<F,MC,  STAR> U01_MC_STAR(g);
    DistMatrix<F,STAR,STAR> U11_STAR_STAR(g);
    DistMatrix<F,STAR,MR  > X1_STAR_MR(g);
    DistMatrix<F,STAR,VR  > X1_STAR_VR(g);

    const Int kLast = LastOffset( m, bsize );
    for( Int k=kLast; k>=0; k-=bsize )
    {
        const Int nb = Min(bsize,m-k);

        const Range<Int> ind0( 0, k    ),
                         ind1( k, k+nb );

        auto U01 = U( ind0, ind1 );
        auto U11 = U( ind1, ind1 );

        auto X0 = X( ind0, ALL );
        auto X1 = X( ind1, ALL );

        U11_STAR_STAR = U11; // U11[* ,* ] <- U11[MC,MR]
        X1_STAR_VR    = X1;  // X1[* ,VR] <- X1[MC,MR]
        
        // X1[* ,VR] := U11^-1[* ,* ] X1[* ,VR]
        LocalTrsm
        ( LEFT, UPPER, NORMAL, diag, F(1), U11_STAR_STAR, X1_STAR_VR,
          checkIfSingular );

        X1_STAR_MR.AlignWith( X0 );
        X1_STAR_MR  = X1_STAR_VR; // X1[* ,MR]  <- X1[* ,VR]
        X1          = X1_STAR_MR; // X1[MC,MR] <- X1[* ,MR]
        U01_MC_STAR.AlignWith( X0 );
        U01_MC_STAR = U01;        // U01[MC,* ] <- U01[MC,MR]

        // X0[MC,MR] -= U01[MC,* ] X1[* ,MR]
        LocalGemm( NORMAL, NORMAL, F(-1), U01_MC_STAR, X1_STAR_MR, F(1), X0 );
    }
}
Beispiel #5
0
void GolubReinsch
( AbstractDistMatrix<Field>& APre,
  AbstractDistMatrix<Field>& UPre,
  AbstractDistMatrix<Base<Field>>& s,
  AbstractDistMatrix<Field>& VPre,
  const SVDCtrl<Base<Field>>& ctrl )
{
    EL_DEBUG_CSE
    DistMatrixReadWriteProxy<Field,Field,MC,MR> AProx( APre );
    DistMatrixWriteProxy<Field,Field,MC,MR> UProx( UPre );
    DistMatrixWriteProxy<Field,Field,MC,MR> VProx( VPre );
    auto& A = AProx.Get();
    auto& U = UProx.Get();
    auto& V = VProx.Get();
    return GolubReinsch( A, U, s, V, ctrl );
}
Beispiel #6
0
void CheckRealSchur( const AbstractDistMatrix<Real>& UPre, bool standardForm )
{
    EL_DEBUG_CSE

    DistMatrixReadProxy<Real,Real,MC,MR> UProx( UPre );
    auto& U = UProx.GetLocked();

    auto uMain = GetDiagonal(U);
    auto uSub = GetDiagonal(U,-1);
    DistMatrix<Real,STAR,STAR> uMain_STAR_STAR( uMain ),
                               uSub_STAR_STAR( uSub );
    auto& uMainLoc = uMain_STAR_STAR.Matrix();
    auto& uSubLoc = uSub_STAR_STAR.Matrix();

    const Int n = U.Height();
    if( standardForm )
    {
        auto uSup = GetDiagonal(U,+1);
        DistMatrix<Real,STAR,STAR> uSup_STAR_STAR( uSup );
        auto& uSupLoc = uSup_STAR_STAR.Matrix();
        for( Int j=0; j<n-1; ++j )
        {
            const Real thisDiag = uMainLoc(j);
            const Real nextDiag = uMainLoc(j+1);
            const Real thisSub = uSubLoc(j);
            const Real thisSup = uSupLoc(j);
            if( thisSub != Real(0) && thisDiag != nextDiag ) 
                LogicError
                ("Diagonal of 2x2 block was not constant: ",thisDiag," and ",
                 nextDiag);
            if( thisSub*thisSup >= 0 )
                LogicError("b*c >= 0: b=",thisSup," and c=",thisSub);
        }
    }

    if( n < 3 )
        return;
    for( Int j=0; j<n-2; ++j )
    {
        const Real thisSub = uSubLoc(j);
        const Real nextSub = uSubLoc(j+1);
        if( thisSub != Real(0) && nextSub != Real(0) )
            LogicError
            ("Quasi-triangular assumption broken at j=",j,
             ": subdiagonals were ",thisSub," and ",nextSub);
    }
}
Beispiel #7
0
void LUNLarge
( const ElementalMatrix<F>& UPre,
        ElementalMatrix<F>& XPre, 
  bool checkIfSingular )
{
    DEBUG_CSE
    const Int m = XPre.Height();
    const Int bsize = Blocksize();
    const Grid& g = UPre.Grid();

    DistMatrixReadProxy<F,F,MC,MR> UProx( UPre );
    DistMatrixReadWriteProxy<F,F,MC,MR> XProx( XPre );
    auto& U = UProx.GetLocked();
    auto& X = XProx.Get();

    DistMatrix<F,MC,  STAR> U01_MC_STAR(g);
    DistMatrix<F,STAR,STAR> U11_STAR_STAR(g);
    DistMatrix<F,STAR,MR  > X1_STAR_MR(g);
    DistMatrix<F,STAR,VR  > X1_STAR_VR(g);

    const Int kLast = LastOffset( m, bsize );
    Int k=kLast, kOld=m;
    while( true )
    {
        const bool in2x2 = ( k>0 && U.Get(k,k-1) != F(0) );
        if( in2x2 )
            --k;
        const Int nb = kOld-k;

        const Range<Int> ind0( 0, k    ),
                         ind1( k, k+nb );

        auto U01 = U( ind0, ind1 );
        auto U11 = U( ind1, ind1 );

        auto X0 = X( ind0, ALL );
        auto X1 = X( ind1, ALL );

        U11_STAR_STAR = U11; // U11[* ,* ] <- U11[MC,MR]
        X1_STAR_VR    = X1;  // X1[* ,VR] <- X1[MC,MR]
        
        // X1[* ,VR] := U11^-1[* ,* ] X1[* ,VR]
        LocalQuasiTrsm
        ( LEFT, UPPER, NORMAL, F(1), U11_STAR_STAR, X1_STAR_VR,
          checkIfSingular );

        X1_STAR_MR.AlignWith( X0 );
        X1_STAR_MR  = X1_STAR_VR; // X1[* ,MR]  <- X1[* ,VR]
        X1          = X1_STAR_MR; // X1[MC,MR] <- X1[* ,MR]
        U01_MC_STAR.AlignWith( X0 );
        U01_MC_STAR = U01;        // U01[MC,* ] <- U01[MC,MR]

        // X0[MC,MR] -= U01[MC,* ] X1[* ,MR]
        LocalGemm( NORMAL, NORMAL, F(-1), U01_MC_STAR, X1_STAR_MR, F(1), X0 );

        if( k == 0 )
            break;
        kOld = k;
        k -= Min(bsize,k);
    }
}
Beispiel #8
0
SVDInfo ScaLAPACKHelper
( const AbstractDistMatrix<F>& APre,
        AbstractDistMatrix<F>& UPre,
        AbstractDistMatrix<Base<F>>& sPre,
        AbstractDistMatrix<F>& V,
  const SVDCtrl<Base<F>>& ctrl )
{
    DEBUG_CSE
    AssertScaLAPACKSupport();
    SVDInfo info;
#ifdef EL_HAVE_SCALAPACK
    typedef Base<F> Real;
    DistMatrix<F,MC,MR,BLOCK> A( APre );
    DistMatrixWriteProxy<Real,Real,STAR,STAR> sProx(sPre);
    DistMatrixWriteProxy<F,F,MC,MR,BLOCK> UProx(UPre);
    auto& s = sProx.Get();
    auto& U = UProx.Get();

    const int m = A.Height();
    const int n = A.Width();
    const int k = Min(m,n);

    auto approach = ctrl.bidiagSVDCtrl.approach;
    if( approach == THIN_SVD || approach == COMPACT_SVD )
    {
        Zeros( U, m, k );
        DistMatrix<F,MC,MR,BLOCK> VH( A.Grid() );
        Zeros( VH, k, n );
        s.Resize( k, 1 );

        auto descA = FillDesc( A );
        auto descU = FillDesc( U );
        auto descVH = FillDesc( VH );
        scalapack::SVD
        ( m, n,
          A.Buffer(), descA.data(),
          s.Buffer(),
          U.Buffer(), descU.data(),
          VH.Buffer(), descVH.data() ); 

        const bool compact = ( approach == COMPACT_SVD );
        if( compact )
        {
            const Real twoNorm = ( k==0 ? Real(0) : s.Get(0,0) );
            const Real thresh =
              bidiag_svd::APosterioriThreshold
              ( m, n, twoNorm, ctrl.bidiagSVDCtrl );

            Int rank = k;
            for( Int j=0; j<k; ++j )
            {
                if( s.Get(j,0) <= thresh )
                {
                    rank = j;
                    break;
                }
            }
            s.Resize( rank, 1 );
            U.Resize( m, rank );
            VH.Resize( rank, n );
        }

        Adjoint( VH, V );
    }
    else
        LogicError
        ("Only Thin and Compact singular value options currently supported");
#endif
    return info;
}