gonum.org/v1/gonum@v0.14.0/lapack/gonum/dgerqf.go (about) 1 // Copyright ©2017 The Gonum Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package gonum 6 7 import ( 8 "gonum.org/v1/gonum/blas" 9 "gonum.org/v1/gonum/lapack" 10 ) 11 12 // Dgerqf computes an RQ factorization of the m×n matrix A, 13 // 14 // A = R * Q. 15 // 16 // On exit, if m <= n, the upper triangle of the subarray 17 // A[0:m, n-m:n] contains the m×m upper triangular matrix R. 18 // If m >= n, the elements on and above the (m-n)-th subdiagonal 19 // contain the m×n upper trapezoidal matrix R. 20 // The remaining elements, with tau, represent the 21 // orthogonal matrix Q as a product of min(m,n) elementary 22 // reflectors. 23 // 24 // The matrix Q is represented as a product of elementary reflectors 25 // 26 // Q = H_0 H_1 . . . H_{min(m,n)-1}. 27 // 28 // Each H(i) has the form 29 // 30 // H_i = I - tau_i * v * vᵀ 31 // 32 // where v is a vector with v[0:n-k+i-1] stored in A[m-k+i, 0:n-k+i-1], 33 // v[n-k+i:n] = 0 and v[n-k+i] = 1. 34 // 35 // tau must have length min(m,n), work must have length max(1, lwork), 36 // and lwork must be -1 or at least max(1, m), otherwise Dgerqf will panic. 37 // On exit, work[0] will contain the optimal length for work. 38 // 39 // Dgerqf is an internal routine. It is exported for testing purposes. 40 func (impl Implementation) Dgerqf(m, n int, a []float64, lda int, tau, work []float64, lwork int) { 41 switch { 42 case m < 0: 43 panic(mLT0) 44 case n < 0: 45 panic(nLT0) 46 case lda < max(1, n): 47 panic(badLdA) 48 case lwork < max(1, m) && lwork != -1: 49 panic(badLWork) 50 case len(work) < max(1, lwork): 51 panic(shortWork) 52 } 53 54 // Quick return if possible. 55 k := min(m, n) 56 if k == 0 { 57 work[0] = 1 58 return 59 } 60 61 nb := impl.Ilaenv(1, "DGERQF", " ", m, n, -1, -1) 62 if lwork == -1 { 63 work[0] = float64(m * nb) 64 return 65 } 66 67 if len(a) < (m-1)*lda+n { 68 panic(shortA) 69 } 70 if len(tau) != k { 71 panic(badLenTau) 72 } 73 74 nbmin := 2 75 nx := 1 76 iws := m 77 var ldwork int 78 if 1 < nb && nb < k { 79 // Determine when to cross over from blocked to unblocked code. 80 nx = max(0, impl.Ilaenv(3, "DGERQF", " ", m, n, -1, -1)) 81 if nx < k { 82 // Determine whether workspace is large enough for blocked code. 83 iws = m * nb 84 if lwork < iws { 85 // Not enough workspace to use optimal nb. Reduce 86 // nb and determine the minimum value of nb. 87 nb = lwork / m 88 nbmin = max(2, impl.Ilaenv(2, "DGERQF", " ", m, n, -1, -1)) 89 } 90 ldwork = nb 91 } 92 } 93 94 var mu, nu int 95 if nbmin <= nb && nb < k && nx < k { 96 // Use blocked code initially. 97 // The last kk rows are handled by the block method. 98 ki := ((k - nx - 1) / nb) * nb 99 kk := min(k, ki+nb) 100 101 var i int 102 for i = k - kk + ki; i >= k-kk; i -= nb { 103 ib := min(k-i, nb) 104 105 // Compute the RQ factorization of the current block 106 // A[m-k+i:m-k+i+ib-1, 0:n-k+i+ib-1]. 107 impl.Dgerq2(ib, n-k+i+ib, a[(m-k+i)*lda:], lda, tau[i:], work) 108 if m-k+i > 0 { 109 // Form the triangular factor of the block reflector 110 // H = H_{i+ib-1} . . . H_{i+1} H_i. 111 impl.Dlarft(lapack.Backward, lapack.RowWise, 112 n-k+i+ib, ib, a[(m-k+i)*lda:], lda, tau[i:], 113 work, ldwork) 114 115 // Apply H to A[0:m-k+i-1, 0:n-k+i+ib-1] from the right. 116 impl.Dlarfb(blas.Right, blas.NoTrans, lapack.Backward, lapack.RowWise, 117 m-k+i, n-k+i+ib, ib, a[(m-k+i)*lda:], lda, 118 work, ldwork, 119 a, lda, 120 work[ib*ldwork:], ldwork) 121 } 122 } 123 mu = m - k + i + nb 124 nu = n - k + i + nb 125 } else { 126 mu = m 127 nu = n 128 } 129 130 // Use unblocked code to factor the last or only block. 131 if mu > 0 && nu > 0 { 132 impl.Dgerq2(mu, nu, a, lda, tau, work) 133 } 134 work[0] = float64(iws) 135 }