Esempio n. 1
0
void FlaBidiagSVD
( int k, int mU, int mV, double* d, double* e, 
  double* U, int ldu, double* V, int ldv, 
  int numAccum, int maxNumIts, int bAlg )
{
    std::vector<Complex<double>> G( (k-1)*numAccum ), H( (k-1)*numAccum ); 
    FLA_Bsvd_v_opd_var1
    ( k, mU, mV, numAccum, maxNumIts, d, 1, e, 1, 
      G.data(), 1, k-1, H.data(), 1, k-1, U, 1, ldu, V, 1, ldv, bAlg );
}
Esempio n. 2
0
inline void
SimpleSVDUpper
( DistMatrix<double>& A,
  DistMatrix<double,VR,STAR>& s,
  DistMatrix<double>& V )
{
#ifndef RELEASE
    PushCallStack("svd::SimpleSVDUpper");
#endif
    typedef double Real;
    typedef Complex<Real> C;

    const int m = A.Height();
    const int n = A.Width();
    const int k = std::min( m, n );
    const int offdiagonal = ( m>=n ? 1 : -1 );
    const char uplo = ( m>=n ? 'U' : 'L' );
    const Grid& g = A.Grid();

    // Bidiagonalize A
    Bidiag( A );

    // Grab copies of the diagonal and sub/super-diagonal of A
    DistMatrix<Real,MD,STAR> d_MD_STAR( g ), 
                             e_MD_STAR( g );
    A.GetDiagonal( d_MD_STAR );
    A.GetDiagonal( e_MD_STAR, offdiagonal );

    // In order to use serial QR kernels, we need the full bidiagonal matrix
    // on each process
    DistMatrix<Real,STAR,STAR> d_STAR_STAR( d_MD_STAR ),
                               e_STAR_STAR( e_MD_STAR );

    // Initialize U and V to the appropriate identity matrices.
    DistMatrix<Real,VC,STAR> U_VC_STAR( g );
    DistMatrix<Real,VC,STAR> V_VC_STAR( g );
    U_VC_STAR.AlignWith( A );
    V_VC_STAR.AlignWith( V );
    Identity( m, k, U_VC_STAR );
    Identity( n, k, V_VC_STAR );

    // Compute the SVD of the bidiagonal matrix and accumulate the Givens
    // rotations into our local portion of U and V
    // NOTE: This _only_ works in the case where m >= n
    const int numAccum = 32;
    const int maxNumIts = 30;
    const int bAlg = 512;
    std::vector<C> GBuffer( (k-1)*numAccum ),
                   HBuffer( (k-1)*numAccum );
    FLA_Bsvd_v_opd_var1
    ( k, U_VC_STAR.LocalHeight(), V_VC_STAR.LocalHeight(), 
      numAccum, maxNumIts,
      d_STAR_STAR.LocalBuffer(), 1,
      e_STAR_STAR.LocalBuffer(), 1,
      &GBuffer[0], 1, k-1,
      &HBuffer[0], 1, k-1,
      U_VC_STAR.LocalBuffer(), 1, U_VC_STAR.LocalLDim(),
      V_VC_STAR.LocalBuffer(), 1, V_VC_STAR.LocalLDim(),
      bAlg );

    // Make a copy of A (for the Householder vectors) and pull the necessary 
    // portions of U and V into a standard matrix dist.
    DistMatrix<Real> B( A );
    if( m >= n )
    {
        DistMatrix<Real> AT( g ),
                         AB( g );
        DistMatrix<Real,VC,STAR> UT_VC_STAR( g ), 
                                 UB_VC_STAR( g );
        PartitionDown( A, AT,
                          AB, n );
        PartitionDown( U_VC_STAR, UT_VC_STAR,
                                  UB_VC_STAR, n );
        AT = UT_VC_STAR;
        MakeZeros( AB );
        V = V_VC_STAR;
    }
    else
    {
        DistMatrix<Real> VT( g ), 
                         VB( g );
        DistMatrix<Real,VC,STAR> VT_VC_STAR( g ), 
                                 VB_VC_STAR( g );
        PartitionDown( V, VT, 
                          VB, m );
        PartitionDown
        ( V_VC_STAR, VT_VC_STAR, 
                     VB_VC_STAR, m );
        VT = VT_VC_STAR;
        MakeZeros( VB );
    }

    // Backtransform U and V
    if( m >= n )
    {
        ApplyPackedReflectors
        ( LEFT, LOWER, VERTICAL, BACKWARD, 0, B, A );
        ApplyPackedReflectors
        ( LEFT, UPPER, HORIZONTAL, BACKWARD, 1, B, V );
    }
    else
    {
        ApplyPackedReflectors
        ( LEFT, LOWER, VERTICAL, BACKWARD, -1, B, A );
        ApplyPackedReflectors
        ( LEFT, UPPER, HORIZONTAL, BACKWARD, 0, B, V );
    }

    // Copy out the appropriate subset of the singular values
    s = d_STAR_STAR;
#ifndef RELEASE
    PopCallStack();
#endif
}