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