gonum.org/v1/gonum@v0.14.0/lapack/gonum/dorgtr.go (about) 1 // Copyright ©2016 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/blas" 8 9 // Dorgtr generates a real orthogonal matrix Q which is defined as the product 10 // of n-1 elementary reflectors of order n as returned by Dsytrd. 11 // 12 // The construction of Q depends on the value of uplo: 13 // 14 // Q = H_{n-1} * ... * H_1 * H_0 if uplo == blas.Upper 15 // Q = H_0 * H_1 * ... * H_{n-1} if uplo == blas.Lower 16 // 17 // where H_i is constructed from the elementary reflectors as computed by Dsytrd. 18 // See the documentation for Dsytrd for more information. 19 // 20 // tau must have length at least n-1, and Dorgtr will panic otherwise. 21 // 22 // work is temporary storage, and lwork specifies the usable memory length. At 23 // minimum, lwork >= max(1,n-1), and Dorgtr will panic otherwise. The amount of blocking 24 // is limited by the usable length. 25 // If lwork == -1, instead of computing Dorgtr the optimal work length is stored 26 // into work[0]. 27 // 28 // Dorgtr is an internal routine. It is exported for testing purposes. 29 func (impl Implementation) Dorgtr(uplo blas.Uplo, n int, a []float64, lda int, tau, work []float64, lwork int) { 30 switch { 31 case uplo != blas.Upper && uplo != blas.Lower: 32 panic(badUplo) 33 case n < 0: 34 panic(nLT0) 35 case lda < max(1, n): 36 panic(badLdA) 37 case lwork < max(1, n-1) && lwork != -1: 38 panic(badLWork) 39 case len(work) < max(1, lwork): 40 panic(shortWork) 41 } 42 43 if n == 0 { 44 work[0] = 1 45 return 46 } 47 48 var nb int 49 if uplo == blas.Upper { 50 nb = impl.Ilaenv(1, "DORGQL", " ", n-1, n-1, n-1, -1) 51 } else { 52 nb = impl.Ilaenv(1, "DORGQR", " ", n-1, n-1, n-1, -1) 53 } 54 lworkopt := max(1, n-1) * nb 55 if lwork == -1 { 56 work[0] = float64(lworkopt) 57 return 58 } 59 60 switch { 61 case len(a) < (n-1)*lda+n: 62 panic(shortA) 63 case len(tau) < n-1: 64 panic(shortTau) 65 } 66 67 if uplo == blas.Upper { 68 // Q was determined by a call to Dsytrd with uplo == blas.Upper. 69 // Shift the vectors which define the elementary reflectors one column 70 // to the left, and set the last row and column of Q to those of the unit 71 // matrix. 72 for j := 0; j < n-1; j++ { 73 for i := 0; i < j; i++ { 74 a[i*lda+j] = a[i*lda+j+1] 75 } 76 a[(n-1)*lda+j] = 0 77 } 78 for i := 0; i < n-1; i++ { 79 a[i*lda+n-1] = 0 80 } 81 a[(n-1)*lda+n-1] = 1 82 83 // Generate Q[0:n-1, 0:n-1]. 84 impl.Dorgql(n-1, n-1, n-1, a, lda, tau, work, lwork) 85 } else { 86 // Q was determined by a call to Dsytrd with uplo == blas.Upper. 87 // Shift the vectors which define the elementary reflectors one column 88 // to the right, and set the first row and column of Q to those of the unit 89 // matrix. 90 for j := n - 1; j > 0; j-- { 91 a[j] = 0 92 for i := j + 1; i < n; i++ { 93 a[i*lda+j] = a[i*lda+j-1] 94 } 95 } 96 a[0] = 1 97 for i := 1; i < n; i++ { 98 a[i*lda] = 0 99 } 100 if n > 1 { 101 // Generate Q[1:n, 1:n]. 102 impl.Dorgqr(n-1, n-1, n-1, a[lda+1:], lda, tau, work, lwork) 103 } 104 } 105 work[0] = float64(lworkopt) 106 }