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.
10 "golang.org/x/exp/rand"
12 "gonum.org/v1/gonum/blas"
13 "gonum.org/v1/gonum/blas/blas64"
14 "gonum.org/v1/gonum/floats"
15 "gonum.org/v1/gonum/lapack"
18 type Dormbrer interface {
19 Dormbr(vect lapack.DecompUpdate, side blas.Side, trans blas.Transpose, m, n, k int, a []float64, lda int, tau, c []float64, ldc int, work []float64, lwork int)
23 func DormbrTest(t *testing.T, impl Dormbrer) {
24 rnd := rand.New(rand.NewSource(1))
25 bi := blas64.Implementation()
26 for _, vect := range []lapack.DecompUpdate{lapack.ApplyQ, lapack.ApplyP} {
27 for _, side := range []blas.Side{blas.Left, blas.Right} {
28 for _, trans := range []blas.Transpose{blas.NoTrans, blas.Trans} {
29 for _, wl := range []worklen{minimumWork, mediumWork, optimumWork} {
30 for _, test := range []struct {
47 {150, 140, 130, 0, 0},
58 if side == blas.Left {
63 // Compute a decomposition.
66 if vect == lapack.ApplyQ {
77 a = make([]float64, ma*lda)
79 a[i] = rnd.NormFloat64()
82 tauP := make([]float64, nTau)
83 tauQ := make([]float64, nTau)
84 d := make([]float64, nTau)
85 e := make([]float64, nTau)
87 work := make([]float64, 1)
88 impl.Dgebrd(ma, na, a, lda, d, e, tauQ, tauP, work, -1)
89 work = make([]float64, int(work[0]))
90 impl.Dgebrd(ma, na, a, lda, d, e, tauQ, tauP, work, len(work))
92 // Apply and compare update.
93 c := make([]float64, m*ldc)
95 c[i] = rnd.NormFloat64()
97 cCopy := make([]float64, len(c))
105 impl.Dormbr(vect, side, trans, m, n, k, a, lda, tauQ, c, ldc, work, -1)
108 work := make([]float64, 1)
109 impl.Dormbr(vect, side, trans, m, n, k, a, lda, tauQ, c, ldc, work, -1)
110 lwork = (int(work[0]) + nw) / 2
112 lwork = max(1, lwork)
113 work = make([]float64, lwork)
115 if vect == lapack.ApplyQ {
116 impl.Dormbr(vect, side, trans, m, n, k, a, lda, tauQ, c, ldc, work, lwork)
118 impl.Dormbr(vect, side, trans, m, n, k, a, lda, tauP, c, ldc, work, lwork)
121 // Check that the multiplication was correct.
122 cOrig := blas64.General{
126 Data: make([]float64, len(cCopy)),
128 copy(cOrig.Data, cCopy)
129 cAns := blas64.General{
133 Data: make([]float64, len(cCopy)),
135 copy(cAns.Data, cCopy)
137 var mulMat blas64.General
138 if vect == lapack.ApplyQ {
139 mulMat = constructQPBidiagonal(lapack.ApplyQ, ma, na, nb, a, lda, tauQ)
141 mulMat = constructQPBidiagonal(lapack.ApplyP, ma, na, nb, a, lda, tauP)
146 if side == blas.Left {
147 bi.Dgemm(mulTrans, blas.NoTrans, m, n, m, 1, mulMat.Data, mulMat.Stride, cOrig.Data, cOrig.Stride, 0, cAns.Data, cAns.Stride)
149 bi.Dgemm(blas.NoTrans, mulTrans, m, n, n, 1, cOrig.Data, cOrig.Stride, mulMat.Data, mulMat.Stride, 0, cAns.Data, cAns.Stride)
152 if !floats.EqualApprox(cAns.Data, c, 1e-13) {
153 isApplyQ := vect == lapack.ApplyQ
154 isLeft := side == blas.Left
155 isTrans := trans == blas.Trans
157 t.Errorf("C mismatch. isApplyQ: %v, isLeft: %v, isTrans: %v, m = %v, n = %v, k = %v, lda = %v, ldc = %v",
158 isApplyQ, isLeft, isTrans, m, n, k, lda, ldc)