gonum.org/v1/gonum@v0.14.0/lapack/testlapack/dgerqf.go (about) 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. 4 5 package testlapack 6 7 import ( 8 "fmt" 9 "testing" 10 11 "golang.org/x/exp/rand" 12 13 "gonum.org/v1/gonum/blas" 14 "gonum.org/v1/gonum/blas/blas64" 15 "gonum.org/v1/gonum/lapack" 16 ) 17 18 type Dgerqfer interface { 19 Dgerqf(m, n int, a []float64, lda int, tau, work []float64, lwork int) 20 } 21 22 func DgerqfTest(t *testing.T, impl Dgerqfer) { 23 rnd := rand.New(rand.NewSource(1)) 24 for _, m := range []int{0, 1, 2, 3, 4, 5, 6, 12, 129, 160} { 25 for _, n := range []int{0, 1, 2, 3, 4, 5, 6, 12, 129, 160} { 26 for _, lda := range []int{max(1, n), n + 4} { 27 dgerqfTest(t, impl, rnd, m, n, lda) 28 } 29 } 30 } 31 } 32 33 func dgerqfTest(t *testing.T, impl Dgerqfer, rnd *rand.Rand, m, n, lda int) { 34 const tol = 1e-14 35 36 a := randomGeneral(m, n, lda, rnd) 37 aCopy := cloneGeneral(a) 38 39 k := min(m, n) 40 tau := make([]float64, k) 41 for i := range tau { 42 tau[i] = rnd.Float64() 43 } 44 45 work := []float64{0} 46 impl.Dgerqf(m, n, a.Data, a.Stride, tau, work, -1) 47 lwkopt := int(work[0]) 48 for _, wk := range []struct { 49 name string 50 length int 51 }{ 52 {name: "short", length: m}, 53 {name: "medium", length: lwkopt - 1}, 54 {name: "long", length: lwkopt}, 55 } { 56 name := fmt.Sprintf("m=%d,n=%d,lda=%d,work=%v", m, n, lda, wk.name) 57 58 lwork := max(max(1, m), wk.length) 59 work = make([]float64, lwork) 60 for i := range work { 61 work[i] = rnd.Float64() 62 } 63 64 copyGeneral(a, aCopy) 65 impl.Dgerqf(m, n, a.Data, a.Stride, tau, work, lwork) 66 67 // Test that the RQ factorization has completed successfully. Compute 68 // Q based on the vectors. 69 q := constructQ("RQ", m, n, a.Data, a.Stride, tau) 70 71 // Check that Q is orthogonal. 72 if resid := residualOrthogonal(q, false); resid > tol*float64(m) { 73 t.Errorf("Case %v: Q not orthogonal; resid=%v, want<=%v", name, resid, tol*float64(m)) 74 } 75 76 // Check that A = R * Q 77 r := zeros(m, n, n) 78 for i := 0; i < m; i++ { 79 off := m - n 80 for j := max(0, i-off); j < n; j++ { 81 r.Data[i*r.Stride+j] = a.Data[i*a.Stride+j] 82 } 83 } 84 qra := cloneGeneral(aCopy) 85 blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, r, q, -1, qra) 86 resid := dlange(lapack.MaxColumnSum, qra.Rows, qra.Cols, qra.Data, qra.Stride) 87 if resid > tol*float64(m) { 88 t.Errorf("Case %v: |R*Q - A|=%v, want<=%v", name, resid, tol*float64(m)) 89 } 90 } 91 }