github.com/gonum/lapack@v0.0.0-20181123203213-e4cdc5a0bff9/testlapack/dorgbr.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 "math/rand" 9 "testing" 10 11 "github.com/gonum/blas/blas64" 12 "github.com/gonum/floats" 13 "github.com/gonum/lapack" 14 ) 15 16 type Dorgbrer interface { 17 Dorgbr(vect lapack.DecompUpdate, m, n, k int, a []float64, lda int, tau, work []float64, lwork int) 18 Dgebrder 19 } 20 21 func DorgbrTest(t *testing.T, impl Dorgbrer) { 22 rnd := rand.New(rand.NewSource(1)) 23 for _, vect := range []lapack.DecompUpdate{lapack.ApplyQ, lapack.ApplyP} { 24 for _, test := range []struct { 25 m, n, k, lda int 26 }{ 27 {5, 5, 5, 0}, 28 {5, 5, 3, 0}, 29 {5, 3, 5, 0}, 30 {3, 5, 5, 0}, 31 {3, 4, 5, 0}, 32 {3, 5, 4, 0}, 33 {4, 3, 5, 0}, 34 {4, 5, 3, 0}, 35 {5, 3, 4, 0}, 36 {5, 4, 3, 0}, 37 38 {5, 5, 5, 10}, 39 {5, 5, 3, 10}, 40 {5, 3, 5, 10}, 41 {3, 5, 5, 10}, 42 {3, 4, 5, 10}, 43 {3, 5, 4, 10}, 44 {4, 3, 5, 10}, 45 {4, 5, 3, 10}, 46 {5, 3, 4, 10}, 47 {5, 4, 3, 10}, 48 } { 49 m := test.m 50 n := test.n 51 k := test.k 52 lda := test.lda 53 // Filter out bad tests 54 if vect == lapack.ApplyQ { 55 if m < n || n < min(m, k) || m < min(m, k) { 56 continue 57 } 58 } else { 59 if n < m || m < min(n, k) || n < min(n, k) { 60 continue 61 } 62 } 63 // Sizes for Dorgbr. 64 var ma, na int 65 if vect == lapack.ApplyQ { 66 if m >= k { 67 ma = m 68 na = k 69 } else { 70 ma = m 71 na = m 72 } 73 } else { 74 if n >= k { 75 ma = k 76 na = n 77 } else { 78 ma = n 79 na = n 80 } 81 } 82 // a eventually needs to store either P or Q, so it must be 83 // sufficiently big. 84 var a []float64 85 if vect == lapack.ApplyQ { 86 lda = max(m, lda) 87 a = make([]float64, m*lda) 88 } else { 89 lda = max(n, lda) 90 a = make([]float64, n*lda) 91 } 92 for i := range a { 93 a[i] = rnd.NormFloat64() 94 } 95 96 nTau := min(ma, na) 97 tauP := make([]float64, nTau) 98 tauQ := make([]float64, nTau) 99 d := make([]float64, nTau) 100 e := make([]float64, nTau) 101 lwork := -1 102 work := make([]float64, 1) 103 impl.Dgebrd(ma, na, a, lda, d, e, tauQ, tauP, work, lwork) 104 work = make([]float64, int(work[0])) 105 lwork = len(work) 106 impl.Dgebrd(ma, na, a, lda, d, e, tauQ, tauP, work, lwork) 107 108 aCopy := make([]float64, len(a)) 109 copy(aCopy, a) 110 111 var tau []float64 112 if vect == lapack.ApplyQ { 113 tau = tauQ 114 } else { 115 tau = tauP 116 } 117 118 impl.Dorgbr(vect, m, n, k, a, lda, tau, work, -1) 119 work = make([]float64, int(work[0])) 120 lwork = len(work) 121 impl.Dorgbr(vect, m, n, k, a, lda, tau, work, lwork) 122 123 var ans blas64.General 124 var nRows, nCols int 125 equal := true 126 if vect == lapack.ApplyQ { 127 nRows = m 128 nCols = m 129 if m >= k { 130 nCols = n 131 } 132 ans = constructQPBidiagonal(vect, ma, na, min(m, k), aCopy, lda, tau) 133 } else { 134 nRows = n 135 if k < n { 136 nRows = m 137 } 138 nCols = n 139 ansTmp := constructQPBidiagonal(vect, ma, na, min(k, n), aCopy, lda, tau) 140 // Dorgbr actually computes P^T 141 ans = transposeGeneral(ansTmp) 142 } 143 for i := 0; i < nRows; i++ { 144 for j := 0; j < nCols; j++ { 145 if !floats.EqualWithinAbsOrRel(a[i*lda+j], ans.Data[i*ans.Stride+j], 1e-8, 1e-8) { 146 equal = false 147 } 148 } 149 } 150 if !equal { 151 applyQ := vect == lapack.ApplyQ 152 t.Errorf("Extracted matrix mismatch. applyQ: %v, m = %v, n = %v, k = %v", applyQ, m, n, k) 153 } 154 } 155 } 156 }