gonum.org/v1/gonum@v0.14.0/lapack/testlapack/dlauu2.go (about) 1 // Copyright ©2018 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 "golang.org/x/exp/rand" 12 13 "gonum.org/v1/gonum/blas" 14 "gonum.org/v1/gonum/blas/blas64" 15 "gonum.org/v1/gonum/lapack" 16 ) 17 18 type Dlauu2er interface { 19 Dlauu2(uplo blas.Uplo, n int, a []float64, lda int) 20 } 21 22 func Dlauu2Test(t *testing.T, impl Dlauu2er) { 23 for _, uplo := range []blas.Uplo{blas.Upper, blas.Lower} { 24 name := uploToString(uplo) 25 t.Run(name, func(t *testing.T) { 26 ns := []int{0, 1, 2, 3, 4, 5, 10, 25} 27 dlauuTest(t, impl.Dlauu2, uplo, ns) 28 }) 29 } 30 } 31 32 func dlauuTest(t *testing.T, dlauu func(blas.Uplo, int, []float64, int), uplo blas.Uplo, ns []int) { 33 const tol = 1e-13 34 35 bi := blas64.Implementation() 36 rnd := rand.New(rand.NewSource(1)) 37 38 for _, n := range ns { 39 for _, lda := range []int{max(1, n), n + 11} { 40 prefix := fmt.Sprintf("n=%v,lda=%v", n, lda) 41 42 // Allocate n×n matrix A and fill it with random numbers. 43 // Only its uplo triangle will be used below. 44 a := make([]float64, n*lda) 45 for i := range a { 46 a[i] = rnd.NormFloat64() 47 } 48 // Create a copy of A. 49 aCopy := make([]float64, len(a)) 50 copy(aCopy, a) 51 52 // Compute U*Uᵀ or Lᵀ*L using Dlauu?. 53 dlauu(uplo, n, a, lda) 54 55 if n == 0 { 56 continue 57 } 58 59 // * Check that the triangle of A opposite to uplo has not been modified. 60 // * Convert the result of Dlauu? into a dense symmetric matrix. 61 // * Zero out the triangle in aCopy opposite to uplo. 62 if uplo == blas.Upper { 63 if !sameLowerTri(n, aCopy, lda, a, lda) { 64 t.Errorf("%v: unexpected modification in lower triangle", prefix) 65 continue 66 } 67 for i := 1; i < n; i++ { 68 for j := 0; j < i; j++ { 69 a[i*lda+j] = a[j*lda+i] 70 aCopy[i*lda+j] = 0 71 } 72 } 73 } else { 74 if !sameUpperTri(n, aCopy, lda, a, lda) { 75 t.Errorf("%v: unexpected modification in upper triangle", prefix) 76 continue 77 } 78 for i := 0; i < n-1; i++ { 79 for j := i + 1; j < n; j++ { 80 a[i*lda+j] = a[j*lda+i] 81 aCopy[i*lda+j] = 0 82 } 83 } 84 } 85 86 // Compute U*Uᵀ or Lᵀ*L using Dgemm with U and L 87 // represented as dense triangular matrices. 88 r := cloneGeneral(blas64.General{Rows: n, Cols: n, Data: a, Stride: lda}) 89 if uplo == blas.Upper { 90 // Use aCopy as a dense representation of the upper triangular U. 91 u := aCopy 92 ldu := lda 93 // Compute U*Uᵀ - A and store the result into R. 94 bi.Dgemm(blas.NoTrans, blas.Trans, n, n, n, 95 1, u, ldu, u, ldu, -1, r.Data, r.Stride) 96 } else { 97 // Use aCopy as a dense representation of the lower triangular L. 98 l := aCopy 99 ldl := lda 100 // Compute Lᵀ*L - A and store the result into R. 101 bi.Dgemm(blas.Trans, blas.NoTrans, n, n, n, 102 1, l, ldl, l, ldl, -1, r.Data, r.Stride) 103 } 104 resid := dlange(lapack.MaxColumnSum, r.Rows, r.Cols, r.Data, r.Stride) 105 if resid > tol*float64(n) { 106 t.Errorf("%v: unexpected result", prefix) 107 } 108 } 109 } 110 }