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.
12 "golang.org/x/exp/rand"
14 "gonum.org/v1/gonum/blas"
15 "gonum.org/v1/gonum/blas/blas64"
18 type Dorghrer interface {
19 Dorghr(n, ilo, ihi int, a []float64, lda int, tau, work []float64, lwork int)
24 func DorghrTest(t *testing.T, impl Dorghrer) {
25 rnd := rand.New(rand.NewSource(1))
27 for _, n := range []int{1, 2, 3, 4, 5, 6, 7, 8, 23, 34} {
28 for _, extra := range []int{0, 1, 13} {
29 for _, optwork := range []bool{true, false} {
30 for cas := 0; cas < 100; cas++ {
36 testDorghr(t, impl, n, ilo, ihi, extra, optwork, rnd)
41 testDorghr(t, impl, 0, 0, -1, 0, false, rnd)
42 testDorghr(t, impl, 0, 0, -1, 0, true, rnd)
45 func testDorghr(t *testing.T, impl Dorghrer, n, ilo, ihi, extra int, optwork bool, rnd *rand.Rand) {
48 // Construct the matrix A with elementary reflectors and scalar factors tau.
49 a := randomGeneral(n, n, n+extra, rnd)
54 work := nanSlice(max(1, n)) // Minimum work for Dgehrd.
55 impl.Dgehrd(n, ilo, ihi, a.Data, a.Stride, tau, work, len(work))
57 // Extract Q for later comparison.
59 qCopy := cloneGeneral(q)
60 for j := ilo; j < ihi; j++ {
64 Data: make([]float64, n),
67 for i := j + 2; i < ihi+1; i++ {
68 v.Data[i] = a.Data[i*a.Stride+j]
70 blas64.Ger(-tau[j], v, v, h)
71 copy(qCopy.Data, q.Data)
72 blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, qCopy, h, 0, q)
77 impl.Dorghr(n, ilo, ihi, a.Data, a.Stride, tau, work, -1)
78 work = nanSlice(int(work[0]))
80 work = nanSlice(max(1, ihi-ilo))
82 impl.Dorghr(n, ilo, ihi, a.Data, a.Stride, tau, work, len(work))
84 prefix := fmt.Sprintf("Case n=%v, ilo=%v, ihi=%v, extra=%v, optwork=%v", n, ilo, ihi, extra, optwork)
85 if !generalOutsideAllNaN(a) {
86 t.Errorf("%v: out-of-range write to A\n%v", prefix, a.Data)
88 if !isOrthonormal(a) {
89 t.Errorf("%v: A is not orthogonal\n%v", prefix, a.Data)
91 for i := 0; i < n; i++ {
92 for j := 0; j < n; j++ {
93 aij := a.Data[i*a.Stride+j]
94 qij := q.Data[i*q.Stride+j]
95 if math.Abs(aij-qij) > tol {
96 t.Errorf("%v: unexpected value of A[%v,%v]. want %v, got %v", prefix, i, j, qij, aij)