gonum.org/v1/gonum@v0.14.0/lapack/gonum/dorgbr.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 "gonum.org/v1/gonum/lapack" 8 9 // Dorgbr generates one of the matrices Q or Pᵀ computed by Dgebrd 10 // computed from the decomposition Dgebrd. See Dgebd2 for the description of 11 // Q and Pᵀ. 12 // 13 // If vect == lapack.GenerateQ, then a is assumed to have been an m×k matrix and 14 // Q is of order m. If m >= k, then Dorgbr returns the first n columns of Q 15 // where m >= n >= k. If m < k, then Dorgbr returns Q as an m×m matrix. 16 // 17 // If vect == lapack.GeneratePT, then A is assumed to have been a k×n matrix, and 18 // Pᵀ is of order n. If k < n, then Dorgbr returns the first m rows of Pᵀ, 19 // where n >= m >= k. If k >= n, then Dorgbr returns Pᵀ as an n×n matrix. 20 // 21 // Dorgbr is an internal routine. It is exported for testing purposes. 22 func (impl Implementation) Dorgbr(vect lapack.GenOrtho, m, n, k int, a []float64, lda int, tau, work []float64, lwork int) { 23 wantq := vect == lapack.GenerateQ 24 mn := min(m, n) 25 switch { 26 case vect != lapack.GenerateQ && vect != lapack.GeneratePT: 27 panic(badGenOrtho) 28 case m < 0: 29 panic(mLT0) 30 case n < 0: 31 panic(nLT0) 32 case k < 0: 33 panic(kLT0) 34 case wantq && n > m: 35 panic(nGTM) 36 case wantq && n < min(m, k): 37 panic("lapack: n < min(m,k)") 38 case !wantq && m > n: 39 panic(mGTN) 40 case !wantq && m < min(n, k): 41 panic("lapack: m < min(n,k)") 42 case lda < max(1, n) && lwork != -1: 43 // Normally, we follow the reference and require the leading 44 // dimension to be always valid, even in case of workspace 45 // queries. However, if a caller provided a placeholder value 46 // for lda (and a) when doing a workspace query that didn't 47 // fulfill the condition here, it would cause a panic. This is 48 // exactly what Dgesvd does. 49 panic(badLdA) 50 case lwork < max(1, mn) && lwork != -1: 51 panic(badLWork) 52 case len(work) < max(1, lwork): 53 panic(shortWork) 54 } 55 56 // Quick return if possible. 57 work[0] = 1 58 if m == 0 || n == 0 { 59 return 60 } 61 62 if wantq { 63 if m >= k { 64 impl.Dorgqr(m, n, k, a, lda, tau, work, -1) 65 } else if m > 1 { 66 impl.Dorgqr(m-1, m-1, m-1, a[lda+1:], lda, tau, work, -1) 67 } 68 } else { 69 if k < n { 70 impl.Dorglq(m, n, k, a, lda, tau, work, -1) 71 } else if n > 1 { 72 impl.Dorglq(n-1, n-1, n-1, a[lda+1:], lda, tau, work, -1) 73 } 74 } 75 lworkopt := int(work[0]) 76 lworkopt = max(lworkopt, mn) 77 if lwork == -1 { 78 work[0] = float64(lworkopt) 79 return 80 } 81 82 switch { 83 case len(a) < (m-1)*lda+n: 84 panic(shortA) 85 case wantq && len(tau) < min(m, k): 86 panic(shortTau) 87 case !wantq && len(tau) < min(n, k): 88 panic(shortTau) 89 } 90 91 if wantq { 92 // Form Q, determined by a call to Dgebrd to reduce an m×k matrix. 93 if m >= k { 94 impl.Dorgqr(m, n, k, a, lda, tau, work, lwork) 95 } else { 96 // Shift the vectors which define the elementary reflectors one 97 // column to the right, and set the first row and column of Q to 98 // those of the unit matrix. 99 for j := m - 1; j >= 1; j-- { 100 a[j] = 0 101 for i := j + 1; i < m; i++ { 102 a[i*lda+j] = a[i*lda+j-1] 103 } 104 } 105 a[0] = 1 106 for i := 1; i < m; i++ { 107 a[i*lda] = 0 108 } 109 if m > 1 { 110 // Form Q[1:m-1, 1:m-1] 111 impl.Dorgqr(m-1, m-1, m-1, a[lda+1:], lda, tau, work, lwork) 112 } 113 } 114 } else { 115 // Form Pᵀ, determined by a call to Dgebrd to reduce a k×n matrix. 116 if k < n { 117 impl.Dorglq(m, n, k, a, lda, tau, work, lwork) 118 } else { 119 // Shift the vectors which define the elementary reflectors one 120 // row downward, and set the first row and column of Pᵀ to 121 // those of the unit matrix. 122 a[0] = 1 123 for i := 1; i < n; i++ { 124 a[i*lda] = 0 125 } 126 for j := 1; j < n; j++ { 127 for i := j - 1; i >= 1; i-- { 128 a[i*lda+j] = a[(i-1)*lda+j] 129 } 130 a[j] = 0 131 } 132 if n > 1 { 133 impl.Dorglq(n-1, n-1, n-1, a[lda+1:], lda, tau, work, lwork) 134 } 135 } 136 } 137 work[0] = float64(lworkopt) 138 }