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