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.
8 "gonum.org/v1/gonum/blas"
9 "gonum.org/v1/gonum/blas/blas64"
10 "gonum.org/v1/gonum/lapack"
13 // Dlarft forms the triangular factor T of a block reflector H, storing the answer
15 // H = I - V * T * V^T if store == lapack.ColumnWise
16 // H = I - V^T * T * V if store == lapack.RowWise
17 // H is defined by a product of the elementary reflectors where
18 // H = H_0 * H_1 * ... * H_{k-1} if direct == lapack.Forward
19 // H = H_{k-1} * ... * H_1 * H_0 if direct == lapack.Backward
21 // t is a k×k triangular matrix. t is upper triangular if direct = lapack.Forward
22 // and lower triangular otherwise. This function will panic if t is not of
25 // store describes the storage of the elementary reflectors in v. See
26 // Dlarfb for a description of layout.
28 // tau contains the scalar factors of the elementary reflectors H_i.
30 // Dlarft is an internal routine. It is exported for testing purposes.
31 func (Implementation) Dlarft(direct lapack.Direct, store lapack.StoreV, n, k int,
32 v []float64, ldv int, tau []float64, t []float64, ldt int) {
39 if direct != lapack.Forward && direct != lapack.Backward {
42 if store != lapack.RowWise && store != lapack.ColumnWise {
48 checkMatrix(k, k, t, ldt)
49 bi := blas64.Implementation()
50 // TODO(btracey): There are a number of minor obvious loop optimizations here.
51 // TODO(btracey): It may be possible to rearrange some of the code so that
52 // index of 1 is more common in the Dgemv.
53 if direct == lapack.Forward {
55 for i := 0; i < k; i++ {
56 prevlastv = max(i, prevlastv)
58 for j := 0; j <= i; j++ {
64 if store == lapack.ColumnWise {
65 // skip trailing zeros
66 for lastv = n - 1; lastv >= i+1; lastv-- {
67 if v[lastv*ldv+i] != 0 {
71 for j := 0; j < i; j++ {
72 t[j*ldt+i] = -tau[i] * v[i*ldv+j]
74 j := min(lastv, prevlastv)
75 bi.Dgemv(blas.Trans, j-i, i,
76 -tau[i], v[(i+1)*ldv:], ldv, v[(i+1)*ldv+i:], ldv,
79 for lastv = n - 1; lastv >= i+1; lastv-- {
80 if v[i*ldv+lastv] != 0 {
84 for j := 0; j < i; j++ {
85 t[j*ldt+i] = -tau[i] * v[j*ldv+i]
87 j := min(lastv, prevlastv)
88 bi.Dgemv(blas.NoTrans, i, j-i,
89 -tau[i], v[i+1:], ldv, v[i*ldv+i+1:], 1,
92 bi.Dtrmv(blas.Upper, blas.NoTrans, blas.NonUnit, i, t, ldt, t[i:], ldt)
95 prevlastv = max(prevlastv, lastv)
103 for i := k - 1; i >= 0; i-- {
105 for j := i; j < k; j++ {
112 if store == lapack.ColumnWise {
113 for lastv = 0; lastv < i; lastv++ {
114 if v[lastv*ldv+i] != 0 {
118 for j := i + 1; j < k; j++ {
119 t[j*ldt+i] = -tau[i] * v[(n-k+i)*ldv+j]
121 j := max(lastv, prevlastv)
122 bi.Dgemv(blas.Trans, n-k+i-j, k-i-1,
123 -tau[i], v[j*ldv+i+1:], ldv, v[j*ldv+i:], ldv,
124 1, t[(i+1)*ldt+i:], ldt)
126 for lastv = 0; lastv < i; lastv++ {
127 if v[i*ldv+lastv] != 0 {
131 for j := i + 1; j < k; j++ {
132 t[j*ldt+i] = -tau[i] * v[j*ldv+n-k+i]
134 j := max(lastv, prevlastv)
135 bi.Dgemv(blas.NoTrans, k-i-1, n-k+i-j,
136 -tau[i], v[(i+1)*ldv+j:], ldv, v[i*ldv+j:], 1,
137 1, t[(i+1)*ldt+i:], ldt)
139 bi.Dtrmv(blas.Lower, blas.NoTrans, blas.NonUnit, k-i-1,
140 t[(i+1)*ldt+i+1:], ldt,
141 t[(i+1)*ldt+i:], ldt)
143 prevlastv = min(prevlastv, lastv)