gonum.org/v1/gonum@v0.15.1-0.20240517103525-f853624cb1bb/lapack/testlapack/dgeqrf.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 "testing" 9 10 "golang.org/x/exp/rand" 11 12 "gonum.org/v1/gonum/floats" 13 ) 14 15 type Dgeqrfer interface { 16 Dgeqr2er 17 Dgeqrf(m, n int, a []float64, lda int, tau, work []float64, lwork int) 18 } 19 20 func DgeqrfTest(t *testing.T, impl Dgeqrfer) { 21 const tol = 1e-12 22 rnd := rand.New(rand.NewSource(1)) 23 for c, test := range []struct { 24 m, n, lda int 25 }{ 26 {10, 5, 0}, 27 {5, 10, 0}, 28 {10, 10, 0}, 29 {300, 5, 0}, 30 {3, 500, 0}, 31 {200, 200, 0}, 32 {300, 200, 0}, 33 {204, 300, 0}, 34 {1, 3000, 0}, 35 {3000, 1, 0}, 36 {10, 5, 20}, 37 {5, 10, 20}, 38 {10, 10, 20}, 39 {300, 5, 400}, 40 {3, 500, 600}, 41 {200, 200, 300}, 42 {300, 200, 300}, 43 {204, 300, 400}, 44 {1, 3000, 4000}, 45 {3000, 1, 4000}, 46 } { 47 m := test.m 48 n := test.n 49 lda := test.lda 50 if lda == 0 { 51 lda = test.n 52 } 53 54 // Allocate m×n matrix A and fill it with random numbers. 55 a := make([]float64, m*lda) 56 for i := range a { 57 a[i] = rnd.NormFloat64() 58 } 59 // Store a copy of A for later comparison. 60 aCopy := make([]float64, len(a)) 61 copy(aCopy, a) 62 63 // Allocate a slice for scalar factors of elementary reflectors 64 // and fill it with random numbers. 65 k := min(m, n) 66 tau := make([]float64, k) 67 for i := range tau { 68 tau[i] = rnd.Float64() 69 } 70 71 // Compute the expected result using unblocked QR algorithm and 72 // store it in want. 73 want := make([]float64, len(a)) 74 copy(want, a) 75 impl.Dgeqr2(m, n, want, lda, tau, make([]float64, n)) 76 77 for _, wl := range []worklen{minimumWork, mediumWork, optimumWork} { 78 copy(a, aCopy) 79 80 var lwork int 81 switch wl { 82 case minimumWork: 83 lwork = n 84 case mediumWork: 85 work := make([]float64, 1) 86 impl.Dgeqrf(m, n, a, lda, tau, work, -1) 87 lwork = int(work[0]) - 2*n 88 case optimumWork: 89 work := make([]float64, 1) 90 impl.Dgeqrf(m, n, a, lda, tau, work, -1) 91 lwork = int(work[0]) 92 } 93 work := make([]float64, lwork) 94 95 // Compute the QR factorization of A. 96 impl.Dgeqrf(m, n, a, lda, tau, work, len(work)) 97 // Compare the result with Dgeqr2. 98 if !floats.EqualApprox(want, a, tol) { 99 t.Errorf("Case %v, workspace %v, unexpected result.", c, wl) 100 } 101 } 102 } 103 }