/* * Multiply and replace C with product of C and Q or P where Q and P are real orthogonal matrices * defined as the product of k elementary reflectors. * * Q = H(1) H(2) . . . H(k) and P = G(1) G(2). . . G(k) * * as returned by ReduceBidiag(). * * Arguments: * C On entry, the M-by-N matrix C or if flag bit RIGHT is set then N-by-M matrix * On exit C is overwritten by Q*C or Q.T*C. If bit RIGHT is set then C is * overwritten by C*Q or C*Q.T * * A Bidiagonal reduction as returned by ReduceBidiag() where the lower trapezoidal * part, on and below first subdiagonal, holds the product Q. The upper * trapezoidal part holds the product P. * * tau The scalar factors of the elementary reflectors. If flag MULTQ is set then holds * scalar factors for Q. If flag MULTP is set then holds scalar factors for P. * Expected to be column vector is size min(M(A), N(A)). * * bits Indicators, valid bits LEFT, RIGHT, TRANS, MULTQ, MULTP * * flags result * ------------------------------------------ * MULTQ,LEFT C = Q*C n(A) == m(C) * MULTQ,RIGHT C = C*Q n(C) == m(A) * MULTQ,TRANS,LEFT C = Q.T*C n(A) == m(C) * MULTQ,TRANS,RIGHT C = C*Q.T n(C) == m(A) * MULTP,LEFT C = P*C n(A) == m(C) * MULTP,RIGHT C = C*P n(C) == m(A) * MULTP,TRANS,LEFT C = P.T*C n(A) == m(C) * MULTP,TRANS,RIGHT C = C*P.T n(C) == m(A) * */ func BDMult(C, A, tau, W *cmat.FloatMatrix, flags int, confs ...*gomas.Config) *gomas.Error { var Qh, Ch, Ph, tauh cmat.FloatMatrix var err *gomas.Error = nil // default to multiply from left if side not defined if flags&(gomas.LEFT|gomas.RIGHT) == 0 { flags = flags | gomas.LEFT } // if MULTP then flip TRANSPOSE-bit if flags&gomas.MULTP != 0 { // LQ.P = G(k)G(k-1)...G(1) and // Bidiag.P = G(1)G(2)...G(k) // therefore flip the TRANSPOSE bit. if flags&gomas.TRANS != 0 { flags &= ^gomas.TRANS } else { flags |= gomas.TRANS } } if m(A) > n(A) || (m(A) == n(A) && flags&gomas.LOWER == 0) { switch flags & (gomas.MULTQ | gomas.MULTP) { case gomas.MULTQ: tauh.SubMatrix(tau, 0, 0, n(A), 1) err = QRMult(C, A, &tauh, W, flags, confs...) case gomas.MULTP: Ph.SubMatrix(A, 0, 1, n(A)-1, n(A)-1) tauh.SubMatrix(tau, 0, 0, n(A)-1, 1) if flags&gomas.RIGHT != 0 { Ch.SubMatrix(C, 0, 1, m(C), n(C)-1) } else { Ch.SubMatrix(C, 1, 0, m(C)-1, n(C)) } err = LQMult(&Ch, &Ph, &tauh, W, flags, confs...) } } else { switch flags & (gomas.MULTQ | gomas.MULTP) { case gomas.MULTQ: Qh.SubMatrix(A, 1, 0, m(A)-1, m(A)-1) tauh.SubMatrix(tau, 0, 0, m(A)-1, 1) if flags&gomas.RIGHT != 0 { Ch.SubMatrix(C, 0, 1, m(C), n(C)-1) } else { Ch.SubMatrix(C, 1, 0, m(C)-1, n(C)) } err = QRMult(&Ch, &Qh, &tauh, W, flags, confs...) case gomas.MULTP: tauh.SubMatrix(tau, 0, 0, m(A), 1) err = LQMult(C, A, &tauh, W, flags, confs...) } } if err != nil { err.Update("BDMult") } return err }
/* * Generates the real orthogonal matrix Q which is defined as the product of K elementary * reflectors of order N embedded in matrix A as returned by TRDReduce(). * * A On entry tridiagonal reduction as returned by TRDReduce(). * On exit the orthogonal matrix Q. * * tau Scalar coefficients of elementary reflectors. * * W Workspace * * K Number of reflectors , 0 < K < N * * flags LOWER or UPPER * * confs Optional blocking configuration * * If flags has UPPER set then * Q = H(K)...H(1)H(0) where 0 < K < N-1 * * If flags has LOWR set then * Q = H(0)H(1)...H(K) where 0 < K < N-1 */ func TRDBuild(A, tau, W *cmat.FloatMatrix, K, flags int, confs ...*gomas.Config) *gomas.Error { var err *gomas.Error = nil var Qh, tauh cmat.FloatMatrix var s, d cmat.FloatMatrix if K > m(A)-1 { K = m(A) - 1 } switch flags & (gomas.LOWER | gomas.UPPER) { case gomas.LOWER: // Shift Q matrix embedded in A right and fill first column // unit column vector for j := m(A) - 1; j > 0; j-- { s.SubMatrix(A, j, j-1, m(A)-j, 1) d.SubMatrix(A, j, j, m(A)-j, 1) blasd.Copy(&d, &s) A.Set(0, j, 0.0) } // zero first column and set first entry to one d.Column(A, 0) blasd.Scale(&d, 0.0) d.Set(0, 0, 1.0) Qh.SubMatrix(A, 1, 1, m(A)-1, m(A)-1) tauh.SubMatrix(tau, 0, 0, m(A)-1, 1) err = QRBuild(&Qh, &tauh, W, K, confs...) case gomas.UPPER: // Shift Q matrix embedded in A left and fill last column // unit column vector for j := 1; j < m(A); j++ { s.SubMatrix(A, 0, j, j, 1) d.SubMatrix(A, 0, j-1, j, 1) blasd.Copy(&d, &s) A.Set(-1, j-1, 0.0) } // zero last column and set last entry to one d.Column(A, m(A)-1) blasd.Scale(&d, 0.0) d.Set(-1, 0, 1.0) Qh.SubMatrix(A, 0, 0, m(A)-1, m(A)-1) tauh.SubMatrix(tau, 0, 0, m(A)-1, 1) err = QLBuild(&Qh, &tauh, W, K, confs...) } if err != nil { err.Update("TRDBuild") } return err }
/* * Generate one of the orthogonal matrices Q or P.T determined by BDReduce() when * reducing a real matrix A to bidiagonal form. Q and P.T are defined as products * elementary reflectors H(i) or G(i) respectively. * * Orthogonal matrix Q is generated if flag WANTQ is set. And matrix P respectively * if flag WANTP is set. */ func BDBuild(A, tau, W *cmat.FloatMatrix, K, flags int, confs ...*gomas.Config) *gomas.Error { var Qh, Ph, tauh, d, s cmat.FloatMatrix var err *gomas.Error = nil if m(A) == 0 || n(A) == 0 { return nil } if m(A) > n(A) || (m(A) == n(A) && flags&gomas.LOWER == 0) { switch flags & (gomas.WANTQ | gomas.WANTP) { case gomas.WANTQ: tauh.SubMatrix(tau, 0, 0, n(A), 1) err = QRBuild(A, &tauh, W, K, confs...) case gomas.WANTP: // Shift P matrix embedded in A down and fill first column and row // to unit vector for j := n(A) - 1; j > 0; j-- { s.SubMatrix(A, j-1, j, 1, n(A)-j) d.SubMatrix(A, j, j, 1, n(A)-j) blasd.Copy(&d, &s) A.Set(j, 0, 0.0) } // zero first row and set first entry to one d.Row(A, 0) blasd.Scale(&d, 0.0) d.Set(0, 0, 1.0) Ph.SubMatrix(A, 1, 1, n(A)-1, n(A)-1) tauh.SubMatrix(tau, 0, 0, n(A)-1, 1) if K > n(A)-1 { K = n(A) - 1 } err = LQBuild(&Ph, &tauh, W, K, confs...) } } else { switch flags & (gomas.WANTQ | gomas.WANTP) { case gomas.WANTQ: // Shift Q matrix embedded in A right and fill first column and row // to unit vector for j := m(A) - 1; j > 0; j-- { s.SubMatrix(A, j, j-1, m(A)-j, 1) d.SubMatrix(A, j, j, m(A)-j, 1) blasd.Copy(&d, &s) A.Set(0, j, 0.0) } // zero first column and set first entry to one d.Column(A, 0) blasd.Scale(&d, 0.0) d.Set(0, 0, 1.0) Qh.SubMatrix(A, 1, 1, m(A)-1, m(A)-1) tauh.SubMatrix(tau, 0, 0, m(A)-1, 1) if K > m(A)-1 { K = m(A) - 1 } err = QRBuild(&Qh, &tauh, W, K, confs...) case gomas.WANTP: tauh.SubMatrix(tau, 0, 0, m(A), 1) err = LQBuild(A, &tauh, W, K, confs...) } } if err != nil { err.Update("BDBuild") } return err }