237 lines
		
	
	
		
			8.1 KiB
		
	
	
	
		
			C++
		
	
	
			
		
		
	
	
			237 lines
		
	
	
		
			8.1 KiB
		
	
	
	
		
			C++
		
	
	
| // =============================================================================
 | |
| // === spqr_larftb =============================================================
 | |
| // =============================================================================
 | |
| 
 | |
| // Apply a set of Householder reflections to a matrix.  Given the vectors
 | |
| // V and coefficients Tau, construct the matrix T and then apply the updates.
 | |
| // In MATLAB (1-based indexing), this function computes the following:
 | |
| 
 | |
| /*
 | |
|     function C = larftb (C, V, Tau, method)
 | |
|     [v k] = size (V) ;
 | |
|     [m n] = size (C) ;
 | |
|     % construct T for the compact WY representation
 | |
|     V = tril (V,-1) + eye (v,k) ;
 | |
|     T = zeros (k,k) ;
 | |
|     T (1,1) = Tau (1) ;
 | |
|     for j = 2:k
 | |
|         tau = Tau (j) ;
 | |
|         z = -tau * V (:, 1:j-1)' * V (:,j) ;
 | |
|         T (1:j-1,j) = T (1:j-1,1:j-1) * z ;
 | |
|         T (j,j) = tau ;
 | |
|     end
 | |
|     % apply the updates
 | |
|     if (method == 0)
 | |
|         C = C - V * T' * V' * C ;       % method 0: Left, Transpose
 | |
|     elseif (method == 1)
 | |
|         C = C - V * T * V' * C ;        % method 1: Left, No Transpose
 | |
|     elseif (method == 2)
 | |
|         C = C - C * V * T' * V' ;       % method 2: Right, Transpose
 | |
|     elseif (method == 3)
 | |
|         C = C - C * V * T * V' ;        % method 3: Right, No Transpose
 | |
|     end
 | |
| */
 | |
| 
 | |
| #include "spqr_subset.hpp"
 | |
| 
 | |
| inline void spqr_private_larft (char direct, char storev, Int n, Int k,
 | |
|     double *V, Int ldv, double *Tau, double *T, Int ldt, cholmod_common *cc)
 | |
| {
 | |
|     BLAS_INT N = n, K = k, LDV = ldv, LDT = ldt ;
 | |
|     if (CHECK_BLAS_INT &&
 | |
|         !(EQ (N,n) && EQ (K,k) && EQ (LDV,ldv) && EQ (LDT,ldt)))
 | |
|     {
 | |
|         cc->blas_ok = FALSE ;
 | |
|     }
 | |
|     if (!CHECK_BLAS_INT || cc->blas_ok)
 | |
|     {
 | |
|         LAPACK_DLARFT (&direct, &storev, &N, &K, V, &LDV, Tau, T, &LDT) ;
 | |
|     }
 | |
| }
 | |
| 
 | |
| inline void spqr_private_larft (char direct, char storev, Int n, Int k,
 | |
|     Complex *V, Int ldv, Complex *Tau, Complex *T, Int ldt, cholmod_common *cc)
 | |
| {
 | |
|     BLAS_INT N = n, K = k, LDV = ldv, LDT = ldt ;
 | |
|     if (CHECK_BLAS_INT &&
 | |
|         !(EQ (N,n) && EQ (K,k) && EQ (LDV,ldv) && EQ (LDT,ldt)))
 | |
|     {
 | |
|         cc->blas_ok = FALSE ;
 | |
|     }
 | |
|     if (!CHECK_BLAS_INT || cc->blas_ok)
 | |
|     {
 | |
|         LAPACK_ZLARFT (&direct, &storev, &N, &K, V, &LDV, Tau, T, &LDT) ;
 | |
|     }
 | |
| }
 | |
| 
 | |
| 
 | |
| inline void spqr_private_larfb (char side, char trans, char direct, char storev,
 | |
|     Int m, Int n, Int k, double *V, Int ldv, double *T, Int ldt, double *C,
 | |
|     Int ldc, double *Work, Int ldwork, cholmod_common *cc)
 | |
| {
 | |
|     BLAS_INT M = m, N = n, K = k, LDV = ldv, LDT = ldt, LDC = ldc,
 | |
|         LDWORK = ldwork ;
 | |
|     if (CHECK_BLAS_INT &&
 | |
|         !(EQ (M,m) && EQ (N,n) && EQ (K,k) && EQ (LDV,ldv) &&
 | |
|           EQ (LDT,ldt) && EQ (LDV,ldv) && EQ (LDWORK,ldwork)))
 | |
|     {
 | |
|         cc->blas_ok = FALSE ;
 | |
|     }
 | |
|     if (!CHECK_BLAS_INT || cc->blas_ok)
 | |
|     {
 | |
|         LAPACK_DLARFB (&side, &trans, &direct, &storev, &M, &N, &K, V, &LDV,
 | |
|             T, &LDT, C, &LDC, Work, &LDWORK) ;
 | |
|     }
 | |
| }
 | |
| 
 | |
| 
 | |
| inline void spqr_private_larfb (char side, char trans, char direct, char storev,
 | |
|     Int m, Int n, Int k, Complex *V, Int ldv, Complex *T, Int ldt, Complex *C,
 | |
|     Int ldc, Complex *Work, Int ldwork, cholmod_common *cc)
 | |
| {
 | |
|     char tr = (trans == 'T') ? 'C' : 'N' ;      // change T to C
 | |
|     BLAS_INT M = m, N = n, K = k, LDV = ldv, LDT = ldt, LDC = ldc,
 | |
|         LDWORK = ldwork ;
 | |
|     if (CHECK_BLAS_INT &&
 | |
|         !(EQ (M,m) && EQ (N,n) && EQ (K,k) && EQ (LDV,ldv) &&
 | |
|           EQ (LDT,ldt) && EQ (LDV,ldv) && EQ (LDWORK,ldwork)))
 | |
|     {
 | |
|         cc->blas_ok = FALSE ;
 | |
|     }
 | |
|     if (!CHECK_BLAS_INT || cc->blas_ok)
 | |
|     {
 | |
|         LAPACK_ZLARFB (&side, &tr, &direct, &storev, &M, &N, &K, V, &LDV,
 | |
|             T, &LDT, C, &LDC, Work, &LDWORK) ;
 | |
|     }
 | |
| }
 | |
| 
 | |
| 
 | |
| // =============================================================================
 | |
| 
 | |
| template <typename Entry> void spqr_larftb
 | |
| (
 | |
|     // inputs, not modified (V is modified and then restored on output)
 | |
|     int method,     // 0,1,2,3
 | |
|     Int m,          // C is m-by-n
 | |
|     Int n,
 | |
|     Int k,          // V is v-by-k
 | |
|                     // for methods 0 and 1, v = m,
 | |
|                     // for methods 2 and 3, v = n
 | |
|     Int ldc,        // leading dimension of C
 | |
|     Int ldv,        // leading dimension of V
 | |
|     Entry *V,       // V is v-by-k, unit lower triangular (diag not stored)
 | |
|     Entry *Tau,     // size k, the k Householder coefficients
 | |
| 
 | |
|     // input/output
 | |
|     Entry *C,       // C is m-by-n, with leading dimension ldc
 | |
| 
 | |
|     // workspace, not defined on input or output
 | |
|     Entry *W,       // for methods 0,1: size k*k + n*k
 | |
|                     // for methods 2,3: size k*k + m*k
 | |
|     cholmod_common *cc
 | |
| )
 | |
| {
 | |
|     Entry *T, *Work ;
 | |
| 
 | |
|     // -------------------------------------------------------------------------
 | |
|     // check inputs and split up workspace
 | |
|     // -------------------------------------------------------------------------
 | |
| 
 | |
|     if (m <= 0 || n <= 0 || k <= 0)
 | |
|     {
 | |
|         return ; // nothing to do
 | |
|     }
 | |
| 
 | |
|     T = W ;             // triangular k-by-k matrix for block reflector
 | |
|     Work = W + k*k ;    // workspace of size n*k or m*k for larfb
 | |
| 
 | |
|     // -------------------------------------------------------------------------
 | |
|     // construct and apply the k-by-k upper triangular matrix T
 | |
|     // -------------------------------------------------------------------------
 | |
| 
 | |
|     // larft and larfb are always used "Forward" and "Columnwise"
 | |
| 
 | |
|     if (method == SPQR_QTX)
 | |
|     {
 | |
|         ASSERT (m >= k) ;
 | |
|         spqr_private_larft ('F', 'C', m, k, V, ldv, Tau, T, k, cc) ;
 | |
|         // Left, Transpose, Forward, Columwise:
 | |
|         spqr_private_larfb ('L', 'T', 'F', 'C', m, n, k, V, ldv, T, k, C, ldc,
 | |
|             Work, n, cc) ;
 | |
|     }
 | |
|     else if (method == SPQR_QX)
 | |
|     {
 | |
|         ASSERT (m >= k) ;
 | |
|         spqr_private_larft ('F', 'C', m, k, V, ldv, Tau, T, k, cc) ;
 | |
|         // Left, No Transpose, Forward, Columwise:
 | |
|         spqr_private_larfb ('L', 'N', 'F', 'C', m, n, k, V, ldv, T, k, C, ldc,
 | |
|             Work, n, cc) ;
 | |
|     }
 | |
|     else if (method == SPQR_XQT)
 | |
|     {
 | |
|         ASSERT (n >= k) ;
 | |
|         spqr_private_larft ('F', 'C', n, k, V, ldv, Tau, T, k, cc) ;
 | |
|         // Right, Transpose, Forward, Columwise:
 | |
|         spqr_private_larfb ('R', 'T', 'F', 'C', m, n, k, V, ldv, T, k, C, ldc,
 | |
|             Work, m, cc) ;
 | |
|     }
 | |
|     else if (method == SPQR_XQ)
 | |
|     {
 | |
|         ASSERT (n >= k) ;
 | |
|         spqr_private_larft ('F', 'C', n, k, V, ldv, Tau, T, k, cc) ;
 | |
|         // Right, No Transpose, Forward, Columwise:
 | |
|         spqr_private_larfb ('R', 'N', 'F', 'C', m, n, k, V, ldv, T, k, C, ldc,
 | |
|             Work, m, cc) ;
 | |
|     }
 | |
| }
 | |
| 
 | |
| // =============================================================================
 | |
| 
 | |
| template void spqr_larftb <double>
 | |
| (
 | |
|     // inputs, not modified (V is modified and then restored on output)
 | |
|     int method,     // 0,1,2,3
 | |
|     Int m,          // C is m-by-n
 | |
|     Int n,
 | |
|     Int k,          // V is v-by-k
 | |
|                     // for methods 0 and 1, v = m,
 | |
|                     // for methods 2 and 3, v = n
 | |
|     Int ldc,        // leading dimension of C
 | |
|     Int ldv,        // leading dimension of V
 | |
|     double *V,      // V is v-by-k, unit lower triangular (diag not stored)
 | |
|     double *Tau,    // size k, the k Householder coefficients
 | |
| 
 | |
|     // input/output
 | |
|     double *C,      // C is m-by-n, with leading dimension ldc
 | |
| 
 | |
|     // workspace, not defined on input or output
 | |
|     double *W,      // for methods 0,1: size k*k + n*k
 | |
|                     // for methods 2,3: size k*k + m*k
 | |
|     cholmod_common *cc
 | |
| ) ;
 | |
| 
 | |
| // =============================================================================
 | |
| 
 | |
| template void spqr_larftb <Complex>
 | |
| (
 | |
|     // inputs, not modified (V is modified and then restored on output)
 | |
|     int method,     // 0,1,2,3
 | |
|     Int m,          // C is m-by-n
 | |
|     Int n,
 | |
|     Int k,          // V is v-by-k
 | |
|                     // for methods 0 and 1, v = m,
 | |
|                     // for methods 2 and 3, v = n
 | |
|     Int ldc,        // leading dimension of C
 | |
|     Int ldv,        // leading dimension of V
 | |
|     Complex *V,     // V is v-by-k, unit lower triangular (diag not stored)
 | |
|     Complex *Tau,   // size k, the k Householder coefficients
 | |
| 
 | |
|     // input/output
 | |
|     Complex *C,     // C is m-by-n, with leading dimension ldc
 | |
| 
 | |
|     // workspace, not defined on input or output
 | |
|     Complex *W,     // for methods 0,1: size k*k + n*k
 | |
|                     // for methods 2,3: size k*k + m*k
 | |
|     cholmod_common *cc
 | |
| ) ;
 |