github.com/gonum/lapack@v0.0.0-20181123203213-e4cdc5a0bff9/testlapack/dorm2r.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" 12 "github.com/gonum/blas/blas64" 13 "github.com/gonum/floats" 14 ) 15 16 type Dorm2rer interface { 17 Dgeqrfer 18 Dorm2r(side blas.Side, trans blas.Transpose, m, n, k int, a []float64, lda int, tau, c []float64, ldc int, work []float64) 19 } 20 21 func Dorm2rTest(t *testing.T, impl Dorm2rer) { 22 rnd := rand.New(rand.NewSource(1)) 23 for _, side := range []blas.Side{blas.Left, blas.Right} { 24 for _, trans := range []blas.Transpose{blas.NoTrans, blas.Trans} { 25 for _, test := range []struct { 26 common, adim, cdim, lda, ldc int 27 }{ 28 {3, 4, 5, 0, 0}, 29 {3, 5, 4, 0, 0}, 30 {4, 3, 5, 0, 0}, 31 {4, 5, 3, 0, 0}, 32 {5, 3, 4, 0, 0}, 33 {5, 4, 3, 0, 0}, 34 {3, 4, 5, 6, 20}, 35 {3, 5, 4, 6, 20}, 36 {4, 3, 5, 6, 20}, 37 {4, 5, 3, 6, 20}, 38 {5, 3, 4, 6, 20}, 39 {5, 4, 3, 6, 20}, 40 {3, 4, 5, 20, 6}, 41 {3, 5, 4, 20, 6}, 42 {4, 3, 5, 20, 6}, 43 {4, 5, 3, 20, 6}, 44 {5, 3, 4, 20, 6}, 45 {5, 4, 3, 20, 6}, 46 } { 47 var ma, na, mc, nc int 48 if side == blas.Left { 49 ma = test.common 50 na = test.adim 51 mc = test.common 52 nc = test.cdim 53 } else { 54 ma = test.common 55 na = test.adim 56 mc = test.cdim 57 nc = test.common 58 } 59 60 // Generate a random matrix 61 lda := test.lda 62 if lda == 0 { 63 lda = na 64 } 65 a := make([]float64, ma*lda) 66 for i := range a { 67 a[i] = rnd.Float64() 68 } 69 ldc := test.ldc 70 if ldc == 0 { 71 ldc = nc 72 } 73 // Compute random C matrix 74 c := make([]float64, mc*ldc) 75 for i := range c { 76 c[i] = rnd.Float64() 77 } 78 79 // Compute QR 80 k := min(ma, na) 81 tau := make([]float64, k) 82 work := make([]float64, 1) 83 impl.Dgeqrf(ma, na, a, lda, tau, work, -1) 84 work = make([]float64, int(work[0])) 85 impl.Dgeqrf(ma, na, a, lda, tau, work, len(work)) 86 87 // Build Q from result 88 q := constructQ("QR", ma, na, a, lda, tau) 89 90 cMat := blas64.General{ 91 Rows: mc, 92 Cols: nc, 93 Stride: ldc, 94 Data: make([]float64, len(c)), 95 } 96 copy(cMat.Data, c) 97 cMatCopy := blas64.General{ 98 Rows: cMat.Rows, 99 Cols: cMat.Cols, 100 Stride: cMat.Stride, 101 Data: make([]float64, len(cMat.Data)), 102 } 103 copy(cMatCopy.Data, cMat.Data) 104 switch { 105 default: 106 panic("bad test") 107 case side == blas.Left && trans == blas.NoTrans: 108 blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, q, cMatCopy, 0, cMat) 109 case side == blas.Left && trans == blas.Trans: 110 blas64.Gemm(blas.Trans, blas.NoTrans, 1, q, cMatCopy, 0, cMat) 111 case side == blas.Right && trans == blas.NoTrans: 112 blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, cMatCopy, q, 0, cMat) 113 case side == blas.Right && trans == blas.Trans: 114 blas64.Gemm(blas.NoTrans, blas.Trans, 1, cMatCopy, q, 0, cMat) 115 } 116 // Do Dorm2r ard compare 117 if side == blas.Left { 118 work = make([]float64, nc) 119 } else { 120 work = make([]float64, mc) 121 } 122 aCopy := make([]float64, len(a)) 123 copy(aCopy, a) 124 tauCopy := make([]float64, len(tau)) 125 copy(tauCopy, tau) 126 impl.Dorm2r(side, trans, mc, nc, k, a, lda, tau, c, ldc, work) 127 if !floats.Equal(a, aCopy) { 128 t.Errorf("a changed in call") 129 } 130 if !floats.Equal(tau, tauCopy) { 131 t.Errorf("tau changed in call") 132 } 133 if !floats.EqualApprox(cMat.Data, c, 1e-14) { 134 t.Errorf("Multiplication mismatch.\n Want %v \n got %v.", cMat.Data, c) 135 } 136 } 137 } 138 } 139 }