gonum.org/v1/gonum@v0.14.0/lapack/testlapack/dlaqp2.go (about) 1 // Copyright ©2017 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 Dlaqp2er interface { 19 Dlapmter 20 Dlaqp2(m, n, offset int, a []float64, lda int, jpvt []int, tau, vn1, vn2, work []float64) 21 } 22 23 func Dlaqp2Test(t *testing.T, impl Dlaqp2er) { 24 const tol = 1e-14 25 26 rnd := rand.New(rand.NewSource(1)) 27 for ti, test := range []struct { 28 m, n, offset int 29 }{ 30 {m: 4, n: 3, offset: 0}, 31 {m: 4, n: 3, offset: 2}, 32 {m: 4, n: 3, offset: 4}, 33 {m: 3, n: 4, offset: 0}, 34 {m: 3, n: 4, offset: 1}, 35 {m: 3, n: 4, offset: 2}, 36 {m: 8, n: 3, offset: 0}, 37 {m: 8, n: 3, offset: 4}, 38 {m: 8, n: 3, offset: 8}, 39 {m: 3, n: 8, offset: 0}, 40 {m: 3, n: 8, offset: 1}, 41 {m: 3, n: 8, offset: 2}, 42 {m: 10, n: 10, offset: 0}, 43 {m: 10, n: 10, offset: 5}, 44 {m: 10, n: 10, offset: 10}, 45 } { 46 m := test.m 47 n := test.n 48 jpiv := make([]int, n) 49 50 for _, extra := range []int{0, 11} { 51 a := randomGeneral(m, n, n+extra, rnd) 52 aCopy := cloneGeneral(a) 53 54 for j := range jpiv { 55 jpiv[j] = j 56 } 57 58 tau := make([]float64, n) 59 vn1 := columnNorms(m, n, a.Data, a.Stride) 60 vn2 := columnNorms(m, n, a.Data, a.Stride) 61 work := make([]float64, n) 62 63 impl.Dlaqp2(m, n, test.offset, a.Data, a.Stride, jpiv, tau, vn1, vn2, work) 64 65 prefix := fmt.Sprintf("Case %v (offset=%d,m=%v,n=%v,extra=%v)", ti, test.offset, m, n, extra) 66 if !generalOutsideAllNaN(a) { 67 t.Errorf("%v: out-of-range write to A", prefix) 68 } 69 70 mo := m - test.offset 71 if mo == 0 { 72 continue 73 } 74 q := constructQ("QR", mo, n, a.Data[test.offset*a.Stride:], a.Stride, tau) 75 76 // Check that Q is orthogonal. 77 if resid := residualOrthogonal(q, false); resid > tol { 78 t.Errorf("%v: Q is not orthogonal; resid=%v, want<=%v", prefix, resid, tol) 79 } 80 81 // Check that |A*P - Q*R| is small. 82 impl.Dlapmt(true, aCopy.Rows, aCopy.Cols, aCopy.Data, aCopy.Stride, jpiv) 83 qrap := blas64.General{ 84 Rows: mo, 85 Cols: aCopy.Cols, 86 Stride: aCopy.Stride, 87 Data: aCopy.Data[test.offset*aCopy.Stride:], 88 } 89 r := zeros(mo, n, n) 90 for i := 0; i < mo; i++ { 91 for j := i; j < n; j++ { 92 r.Data[i*r.Stride+j] = a.Data[(test.offset+i)*a.Stride+j] 93 } 94 } 95 blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, q, r, -1, qrap) 96 resid := dlange(lapack.MaxColumnSum, qrap.Rows, qrap.Cols, qrap.Data, qrap.Stride) 97 if resid > tol { 98 t.Errorf("%v: |Q*R - A*P|=%v, want<=%v", prefix, resid, tol) 99 } 100 } 101 } 102 }