github.com/gonum/lapack@v0.0.0-20181123203213-e4cdc5a0bff9/testlapack/dorghr.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 "math" 10 "math/rand" 11 "testing" 12 13 "github.com/gonum/blas" 14 "github.com/gonum/blas/blas64" 15 ) 16 17 type Dorghrer interface { 18 Dorghr(n, ilo, ihi int, a []float64, lda int, tau, work []float64, lwork int) 19 20 Dgehrder 21 } 22 23 func DorghrTest(t *testing.T, impl Dorghrer) { 24 rnd := rand.New(rand.NewSource(1)) 25 26 for _, n := range []int{1, 2, 3, 4, 5, 6, 7, 8, 23, 34} { 27 for _, extra := range []int{0, 1, 13} { 28 for _, optwork := range []bool{true, false} { 29 for cas := 0; cas < 100; cas++ { 30 ilo := rnd.Intn(n) 31 ihi := rnd.Intn(n) 32 if ilo > ihi { 33 ilo, ihi = ihi, ilo 34 } 35 testDorghr(t, impl, n, ilo, ihi, extra, optwork, rnd) 36 } 37 } 38 } 39 } 40 testDorghr(t, impl, 0, 0, -1, 0, false, rnd) 41 testDorghr(t, impl, 0, 0, -1, 0, true, rnd) 42 } 43 44 func testDorghr(t *testing.T, impl Dorghrer, n, ilo, ihi, extra int, optwork bool, rnd *rand.Rand) { 45 const tol = 1e-14 46 47 // Construct the matrix A with elementary reflectors and scalar factors tau. 48 a := randomGeneral(n, n, n+extra, rnd) 49 var tau []float64 50 if n > 1 { 51 tau = nanSlice(n - 1) 52 } 53 work := nanSlice(max(1, n)) // Minimum work for Dgehrd. 54 impl.Dgehrd(n, ilo, ihi, a.Data, a.Stride, tau, work, len(work)) 55 56 // Extract Q for later comparison. 57 q := eye(n, n) 58 qCopy := cloneGeneral(q) 59 for j := ilo; j < ihi; j++ { 60 h := eye(n, n) 61 v := blas64.Vector{ 62 Inc: 1, 63 Data: make([]float64, n), 64 } 65 v.Data[j+1] = 1 66 for i := j + 2; i < ihi+1; i++ { 67 v.Data[i] = a.Data[i*a.Stride+j] 68 } 69 blas64.Ger(-tau[j], v, v, h) 70 copy(qCopy.Data, q.Data) 71 blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, qCopy, h, 0, q) 72 } 73 74 if optwork { 75 work = nanSlice(1) 76 impl.Dorghr(n, ilo, ihi, a.Data, a.Stride, tau, work, -1) 77 work = nanSlice(int(work[0])) 78 } else { 79 work = nanSlice(max(1, ihi-ilo)) 80 } 81 impl.Dorghr(n, ilo, ihi, a.Data, a.Stride, tau, work, len(work)) 82 83 prefix := fmt.Sprintf("Case n=%v, ilo=%v, ihi=%v, extra=%v, optwork=%v", n, ilo, ihi, extra, optwork) 84 if !generalOutsideAllNaN(a) { 85 t.Errorf("%v: out-of-range write to A\n%v", prefix, a.Data) 86 } 87 if !isOrthonormal(a) { 88 t.Errorf("%v: A is not orthogonal\n%v", prefix, a.Data) 89 } 90 for i := 0; i < n; i++ { 91 for j := 0; j < n; j++ { 92 aij := a.Data[i*a.Stride+j] 93 qij := q.Data[i*q.Stride+j] 94 if math.Abs(aij-qij) > tol { 95 t.Errorf("%v: unexpected value of A[%v,%v]. want %v, got %v", prefix, i, j, qij, aij) 96 } 97 } 98 } 99 }