gonum.org/v1/gonum@v0.14.0/lapack/gonum/dorglq.go (about) 1 // Copyright ©2015 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 // Dorglq generates an m×n matrix Q with orthonormal columns defined by the 13 // product of elementary reflectors as computed by Dgelqf. 14 // 15 // Q = H_0 * H_1 * ... * H_{k-1} 16 // 17 // Dorglq is the blocked version of Dorgl2 that makes greater use of level-3 BLAS 18 // routines. 19 // 20 // len(tau) >= k, 0 <= k <= m, and 0 <= m <= n. 21 // 22 // work is temporary storage, and lwork specifies the usable memory length. At minimum, 23 // lwork >= m, and the amount of blocking is limited by the usable length. 24 // If lwork == -1, instead of computing Dorglq the optimal work length is stored 25 // into work[0]. 26 // 27 // Dorglq will panic if the conditions on input values are not met. 28 // 29 // Dorglq is an internal routine. It is exported for testing purposes. 30 func (impl Implementation) Dorglq(m, n, k int, a []float64, lda int, tau, work []float64, lwork int) { 31 switch { 32 case m < 0: 33 panic(mLT0) 34 case n < m: 35 panic(nLTM) 36 case k < 0: 37 panic(kLT0) 38 case k > m: 39 panic(kGTM) 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 if m == 0 { 49 work[0] = 1 50 return 51 } 52 53 nb := impl.Ilaenv(1, "DORGLQ", " ", m, n, k, -1) 54 if lwork == -1 { 55 work[0] = float64(m * nb) 56 return 57 } 58 59 switch { 60 case len(a) < (m-1)*lda+n: 61 panic(shortA) 62 case len(tau) < k: 63 panic(shortTau) 64 } 65 66 nbmin := 2 // Minimum block size 67 var nx int // Crossover size from blocked to unblocked code 68 iws := m // Length of work needed 69 var ldwork int 70 if 1 < nb && nb < k { 71 nx = max(0, impl.Ilaenv(3, "DORGLQ", " ", m, n, k, -1)) 72 if nx < k { 73 ldwork = nb 74 iws = m * ldwork 75 if lwork < iws { 76 nb = lwork / m 77 ldwork = nb 78 nbmin = max(2, impl.Ilaenv(2, "DORGLQ", " ", m, n, k, -1)) 79 } 80 } 81 } 82 83 var ki, kk int 84 if nbmin <= nb && nb < k && nx < k { 85 // The first kk rows are handled by the blocked method. 86 ki = ((k - nx - 1) / nb) * nb 87 kk = min(k, ki+nb) 88 for i := kk; i < m; i++ { 89 for j := 0; j < kk; j++ { 90 a[i*lda+j] = 0 91 } 92 } 93 } 94 if kk < m { 95 // Perform the operation on columns kk to the end. 96 impl.Dorgl2(m-kk, n-kk, k-kk, a[kk*lda+kk:], lda, tau[kk:], work) 97 } 98 if kk > 0 { 99 // Perform the operation on column-blocks 100 for i := ki; i >= 0; i -= nb { 101 ib := min(nb, k-i) 102 if i+ib < m { 103 impl.Dlarft(lapack.Forward, lapack.RowWise, 104 n-i, ib, 105 a[i*lda+i:], lda, 106 tau[i:], 107 work, ldwork) 108 109 impl.Dlarfb(blas.Right, blas.Trans, lapack.Forward, lapack.RowWise, 110 m-i-ib, n-i, ib, 111 a[i*lda+i:], lda, 112 work, ldwork, 113 a[(i+ib)*lda+i:], lda, 114 work[ib*ldwork:], ldwork) 115 } 116 impl.Dorgl2(ib, n-i, ib, a[i*lda+i:], lda, tau[i:], work) 117 for l := i; l < i+ib; l++ { 118 for j := 0; j < i; j++ { 119 a[l*lda+j] = 0 120 } 121 } 122 } 123 } 124 work[0] = float64(iws) 125 }