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.
11 "golang.org/x/exp/rand"
13 "gonum.org/v1/gonum/blas"
14 "gonum.org/v1/gonum/blas/blas64"
17 type Dgeqp3er interface {
19 Dgeqp3(m, n int, a []float64, lda int, jpvt []int, tau, work []float64, lwork int)
22 func Dgeqp3Test(t *testing.T, impl Dgeqp3er) {
23 rnd := rand.New(rand.NewSource(1))
24 for c, test := range []struct {
63 for _, free := range []int{all, some, none} {
64 a := make([]float64, m*lda)
68 aCopy := make([]float64, len(a))
70 jpvt := make([]int, n)
76 jpvt[j] = rnd.Intn(2) - 1
84 tau := make([]float64, k)
86 tau[i] = rnd.Float64()
88 work := make([]float64, 1)
89 impl.Dgeqp3(m, n, a, lda, jpvt, tau, work, -1)
91 work = make([]float64, lwork)
93 work[i] = rnd.Float64()
95 impl.Dgeqp3(m, n, a, lda, jpvt, tau, work, lwork)
97 // Test that the QR factorization has completed successfully. Compute
98 // Q based on the vectors.
99 q := constructQ("QR", m, n, a, lda, tau)
101 // Check that q is orthonormal
102 for i := 0; i < m; i++ {
103 nrm := blas64.Nrm2(m, blas64.Vector{Inc: 1, Data: q.Data[i*m:]})
104 if math.Abs(nrm-1) > 1e-13 {
105 t.Errorf("Case %v, q not normal", c)
107 for j := 0; j < i; j++ {
108 dot := blas64.Dot(m, blas64.Vector{Inc: 1, Data: q.Data[i*m:]}, blas64.Vector{Inc: 1, Data: q.Data[j*m:]})
109 if math.Abs(dot) > 1e-14 {
110 t.Errorf("Case %v, q not orthogonal", c)
114 // Check that A * P = Q * R
119 Data: make([]float64, m*n),
121 for i := 0; i < m; i++ {
122 for j := i; j < n; j++ {
123 r.Data[i*n+j] = a[i*lda+j]
126 got := nanGeneral(m, n, lda)
127 blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, q, r, 0, got)
129 want := blas64.General{Rows: m, Cols: n, Stride: lda, Data: aCopy}
130 impl.Dlapmt(true, want.Rows, want.Cols, want.Data, want.Stride, jpvt)
131 if !equalApproxGeneral(got, want, 1e-13) {
132 t.Errorf("Case %v, Q*R != A*P\nQ*R=%v\nA*P=%v", c, got, want)