github.com/gopherd/gonum@v0.0.4/lapack/testlapack/dlarfx.go (about) 1 // Copyright ©2016 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 "math/rand" 12 13 "github.com/gopherd/gonum/blas" 14 "github.com/gopherd/gonum/blas/blas64" 15 ) 16 17 type Dlarfxer interface { 18 Dlarfx(side blas.Side, m, n int, v []float64, tau float64, c []float64, ldc int, work []float64) 19 } 20 21 func DlarfxTest(t *testing.T, impl Dlarfxer) { 22 rnd := rand.New(rand.NewSource(1)) 23 for _, side := range []blas.Side{blas.Right, blas.Left} { 24 // For m and n greater than 10 we are testing Dlarf, so avoid unnecessary work. 25 for m := 1; m < 12; m++ { 26 for n := 1; n < 12; n++ { 27 for _, extra := range []int{0, 1, 11} { 28 for cas := 0; cas < 10; cas++ { 29 testDlarfx(t, impl, side, m, n, extra, rnd) 30 } 31 } 32 } 33 } 34 } 35 } 36 37 func testDlarfx(t *testing.T, impl Dlarfxer, side blas.Side, m, n, extra int, rnd *rand.Rand) { 38 const tol = 1e-13 39 40 // Generate random input data. 41 var v []float64 42 if side == blas.Left { 43 v = randomSlice(m, rnd) 44 } else { 45 v = randomSlice(n, rnd) 46 } 47 tau := rnd.NormFloat64() 48 ldc := n + extra 49 c := randomGeneral(m, n, ldc, rnd) 50 51 // Compute the matrix H explicitly as H := I - tau * v * vᵀ. 52 var h blas64.General 53 if side == blas.Left { 54 h = eye(m, m+extra) 55 } else { 56 h = eye(n, n+extra) 57 } 58 blas64.Ger(-tau, blas64.Vector{Inc: 1, Data: v}, blas64.Vector{Inc: 1, Data: v}, h) 59 60 // Compute the product H * C or C * H explicitly. 61 cWant := nanGeneral(m, n, ldc) 62 if side == blas.Left { 63 blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, h, c, 0, cWant) 64 } else { 65 blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, c, h, 0, cWant) 66 } 67 68 var work []float64 69 if h.Rows > 10 { 70 // Allocate work only if H has order > 10. 71 if side == blas.Left { 72 work = make([]float64, n) 73 } else { 74 work = make([]float64, m) 75 } 76 } 77 78 impl.Dlarfx(side, m, n, v, tau, c.Data, c.Stride, work) 79 80 prefix := fmt.Sprintf("Case side=%c, m=%v, n=%v, extra=%v", side, m, n, extra) 81 82 // Check any invalid modifications of c. 83 if !generalOutsideAllNaN(c) { 84 t.Errorf("%v: out-of-range write to C\n%v", prefix, c.Data) 85 } 86 87 if !equalApproxGeneral(c, cWant, tol) { 88 t.Errorf("%v: unexpected C\n%v", prefix, c.Data) 89 } 90 }