github.com/jingcheng-WU/gonum@v0.9.1-0.20210323123734-f1a2a11a8f7b/lapack/gonum/dlahr2.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 ( 8 "github.com/jingcheng-WU/gonum/blas" 9 "github.com/jingcheng-WU/gonum/blas/blas64" 10 ) 11 12 // Dlahr2 reduces the first nb columns of a real general n×(n-k+1) matrix A so 13 // that elements below the k-th subdiagonal are zero. The reduction is performed 14 // by an orthogonal similarity transformation Qᵀ * A * Q. Dlahr2 returns the 15 // matrices V and T which determine Q as a block reflector I - V*T*Vᵀ, and 16 // also the matrix Y = A * V * T. 17 // 18 // The matrix Q is represented as a product of nb elementary reflectors 19 // Q = H_0 * H_1 * ... * H_{nb-1}. 20 // Each H_i has the form 21 // H_i = I - tau[i] * v * vᵀ, 22 // where v is a real vector with v[0:i+k-1] = 0 and v[i+k-1] = 1. v[i+k:n] is 23 // stored on exit in A[i+k+1:n,i]. 24 // 25 // The elements of the vectors v together form the (n-k+1)×nb matrix 26 // V which is needed, with T and Y, to apply the transformation to the 27 // unreduced part of the matrix, using an update of the form 28 // A = (I - V*T*Vᵀ) * (A - Y*Vᵀ). 29 // 30 // On entry, a contains the n×(n-k+1) general matrix A. On return, the elements 31 // on and above the k-th subdiagonal in the first nb columns are overwritten 32 // with the corresponding elements of the reduced matrix; the elements below the 33 // k-th subdiagonal, with the slice tau, represent the matrix Q as a product of 34 // elementary reflectors. The other columns of A are unchanged. 35 // 36 // The contents of A on exit are illustrated by the following example 37 // with n = 7, k = 3 and nb = 2: 38 // [ a a a a a ] 39 // [ a a a a a ] 40 // [ a a a a a ] 41 // [ h h a a a ] 42 // [ v0 h a a a ] 43 // [ v0 v1 a a a ] 44 // [ v0 v1 a a a ] 45 // where a denotes an element of the original matrix A, h denotes a 46 // modified element of the upper Hessenberg matrix H, and vi denotes an 47 // element of the vector defining H_i. 48 // 49 // k is the offset for the reduction. Elements below the k-th subdiagonal in the 50 // first nb columns are reduced to zero. 51 // 52 // nb is the number of columns to be reduced. 53 // 54 // On entry, a represents the n×(n-k+1) matrix A. On return, the elements on and 55 // above the k-th subdiagonal in the first nb columns are overwritten with the 56 // corresponding elements of the reduced matrix. The elements below the k-th 57 // subdiagonal, with the slice tau, represent the matrix Q as a product of 58 // elementary reflectors. The other columns of A are unchanged. 59 // 60 // tau will contain the scalar factors of the elementary reflectors. It must 61 // have length at least nb. 62 // 63 // t and ldt represent the nb×nb upper triangular matrix T, and y and ldy 64 // represent the n×nb matrix Y. 65 // 66 // Dlahr2 is an internal routine. It is exported for testing purposes. 67 func (impl Implementation) Dlahr2(n, k, nb int, a []float64, lda int, tau, t []float64, ldt int, y []float64, ldy int) { 68 switch { 69 case n < 0: 70 panic(nLT0) 71 case k < 0: 72 panic(kLT0) 73 case nb < 0: 74 panic(nbLT0) 75 case nb > n: 76 panic(nbGTN) 77 case lda < max(1, n-k+1): 78 panic(badLdA) 79 case ldt < max(1, nb): 80 panic(badLdT) 81 case ldy < max(1, nb): 82 panic(badLdY) 83 } 84 85 // Quick return if possible. 86 if n < 0 { 87 return 88 } 89 90 switch { 91 case len(a) < (n-1)*lda+n-k+1: 92 panic(shortA) 93 case len(tau) < nb: 94 panic(shortTau) 95 case len(t) < (nb-1)*ldt+nb: 96 panic(shortT) 97 case len(y) < (n-1)*ldy+nb: 98 panic(shortY) 99 } 100 101 // Quick return if possible. 102 if n == 1 { 103 return 104 } 105 106 bi := blas64.Implementation() 107 var ei float64 108 for i := 0; i < nb; i++ { 109 if i > 0 { 110 // Update A[k:n,i]. 111 112 // Update i-th column of A - Y * Vᵀ. 113 bi.Dgemv(blas.NoTrans, n-k, i, 114 -1, y[k*ldy:], ldy, 115 a[(k+i-1)*lda:], 1, 116 1, a[k*lda+i:], lda) 117 118 // Apply I - V * Tᵀ * Vᵀ to this column (call it b) 119 // from the left, using the last column of T as 120 // workspace. 121 // Let V = [ V1 ] and b = [ b1 ] (first i rows) 122 // [ V2 ] [ b2 ] 123 // where V1 is unit lower triangular. 124 // 125 // w := V1ᵀ * b1. 126 bi.Dcopy(i, a[k*lda+i:], lda, t[nb-1:], ldt) 127 bi.Dtrmv(blas.Lower, blas.Trans, blas.Unit, i, 128 a[k*lda:], lda, t[nb-1:], ldt) 129 130 // w := w + V2ᵀ * b2. 131 bi.Dgemv(blas.Trans, n-k-i, i, 132 1, a[(k+i)*lda:], lda, 133 a[(k+i)*lda+i:], lda, 134 1, t[nb-1:], ldt) 135 136 // w := Tᵀ * w. 137 bi.Dtrmv(blas.Upper, blas.Trans, blas.NonUnit, i, 138 t, ldt, t[nb-1:], ldt) 139 140 // b2 := b2 - V2*w. 141 bi.Dgemv(blas.NoTrans, n-k-i, i, 142 -1, a[(k+i)*lda:], lda, 143 t[nb-1:], ldt, 144 1, a[(k+i)*lda+i:], lda) 145 146 // b1 := b1 - V1*w. 147 bi.Dtrmv(blas.Lower, blas.NoTrans, blas.Unit, i, 148 a[k*lda:], lda, t[nb-1:], ldt) 149 bi.Daxpy(i, -1, t[nb-1:], ldt, a[k*lda+i:], lda) 150 151 a[(k+i-1)*lda+i-1] = ei 152 } 153 154 // Generate the elementary reflector H_i to annihilate 155 // A[k+i+1:n,i]. 156 ei, tau[i] = impl.Dlarfg(n-k-i, a[(k+i)*lda+i], a[min(k+i+1, n-1)*lda+i:], lda) 157 a[(k+i)*lda+i] = 1 158 159 // Compute Y[k:n,i]. 160 bi.Dgemv(blas.NoTrans, n-k, n-k-i, 161 1, a[k*lda+i+1:], lda, 162 a[(k+i)*lda+i:], lda, 163 0, y[k*ldy+i:], ldy) 164 bi.Dgemv(blas.Trans, n-k-i, i, 165 1, a[(k+i)*lda:], lda, 166 a[(k+i)*lda+i:], lda, 167 0, t[i:], ldt) 168 bi.Dgemv(blas.NoTrans, n-k, i, 169 -1, y[k*ldy:], ldy, 170 t[i:], ldt, 171 1, y[k*ldy+i:], ldy) 172 bi.Dscal(n-k, tau[i], y[k*ldy+i:], ldy) 173 174 // Compute T[0:i,i]. 175 bi.Dscal(i, -tau[i], t[i:], ldt) 176 bi.Dtrmv(blas.Upper, blas.NoTrans, blas.NonUnit, i, 177 t, ldt, t[i:], ldt) 178 179 t[i*ldt+i] = tau[i] 180 } 181 a[(k+nb-1)*lda+nb-1] = ei 182 183 // Compute Y[0:k,0:nb]. 184 impl.Dlacpy(blas.All, k, nb, a[1:], lda, y, ldy) 185 bi.Dtrmm(blas.Right, blas.Lower, blas.NoTrans, blas.Unit, k, nb, 186 1, a[k*lda:], lda, y, ldy) 187 if n > k+nb { 188 bi.Dgemm(blas.NoTrans, blas.NoTrans, k, nb, n-k-nb, 189 1, a[1+nb:], lda, 190 a[(k+nb)*lda:], lda, 191 1, y, ldy) 192 } 193 bi.Dtrmm(blas.Right, blas.Upper, blas.NoTrans, blas.NonUnit, k, nb, 194 1, t, ldt, y, ldy) 195 }