gonum.org/v1/gonum@v0.14.0/lapack/testlapack/dlangt.go (about) 1 // Copyright ©2020 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 "testing" 11 12 "golang.org/x/exp/rand" 13 14 "gonum.org/v1/gonum/floats" 15 "gonum.org/v1/gonum/lapack" 16 ) 17 18 type Dlangter interface { 19 Dlangt(norm lapack.MatrixNorm, n int, dl, d, du []float64) float64 20 } 21 22 func DlangtTest(t *testing.T, impl Dlangter) { 23 rnd := rand.New(rand.NewSource(1)) 24 for _, norm := range []lapack.MatrixNorm{lapack.MaxAbs, lapack.MaxRowSum, lapack.MaxColumnSum, lapack.Frobenius} { 25 t.Run(normToString(norm), func(t *testing.T) { 26 for _, n := range []int{0, 1, 2, 3, 4, 5, 10} { 27 for iter := 0; iter < 10; iter++ { 28 dlangtTest(t, impl, rnd, norm, n) 29 } 30 } 31 }) 32 } 33 } 34 35 func dlangtTest(t *testing.T, impl Dlangter, rnd *rand.Rand, norm lapack.MatrixNorm, n int) { 36 const ( 37 tol = 1e-14 38 extra = 10 39 ) 40 41 name := fmt.Sprintf("n=%v", n) 42 43 // Generate three random diagonals. 44 dl := randomSlice(n+extra, rnd) 45 dlCopy := make([]float64, len(dl)) 46 copy(dlCopy, dl) 47 48 d := randomSlice(n+1+extra, rnd) 49 // Sometimes put a NaN into the matrix. 50 if n > 0 && rnd.Float64() < 0.5 { 51 d[rnd.Intn(n)] = math.NaN() 52 } 53 dCopy := make([]float64, len(d)) 54 copy(dCopy, d) 55 56 du := randomSlice(n+extra, rnd) 57 duCopy := make([]float64, len(du)) 58 copy(duCopy, du) 59 60 // Deal with zero-sized matrices early. 61 if n == 0 { 62 got := impl.Dlangt(norm, n, nil, nil, nil) 63 if got != 0 { 64 t.Errorf("%v: unexpected result for zero-sized matrix with nil input", name) 65 } 66 got = impl.Dlangt(norm, n, dl, d, du) 67 if !floats.Same(dl, dlCopy) { 68 t.Errorf("%v: unexpected modification in dl", name) 69 } 70 if !floats.Same(d, dCopy) { 71 t.Errorf("%v: unexpected modification in d", name) 72 } 73 if !floats.Same(du, duCopy) { 74 t.Errorf("%v: unexpected modification in du", name) 75 } 76 if got != 0 { 77 t.Errorf("%v: unexpected result for zero-sized matrix with non-nil input", name) 78 } 79 return 80 } 81 82 // Generate a dense representation of the matrix and compute the wanted result. 83 a := zeros(n, n, n) 84 for i := 0; i < n-1; i++ { 85 a.Data[i*a.Stride+i] = d[i] 86 a.Data[i*a.Stride+i+1] = du[i] 87 a.Data[(i+1)*a.Stride+i] = dl[i] 88 } 89 a.Data[(n-1)*a.Stride+n-1] = d[n-1] 90 91 got := impl.Dlangt(norm, n, dl, d, du) 92 93 if !floats.Same(dl, dlCopy) { 94 t.Errorf("%v: unexpected modification in dl", name) 95 } 96 if !floats.Same(d, dCopy) { 97 t.Errorf("%v: unexpected modification in d", name) 98 } 99 if !floats.Same(du, duCopy) { 100 t.Errorf("%v: unexpected modification in du", name) 101 } 102 103 want := dlange(norm, n, n, a.Data, a.Stride) 104 105 if math.IsNaN(want) { 106 if !math.IsNaN(got) { 107 t.Errorf("%v: unexpected result with NaN element; got %v, want %v", name, got, want) 108 } 109 return 110 } 111 112 if norm == lapack.MaxAbs { 113 if got != want { 114 t.Errorf("%v: unexpected result; got %v, want %v", name, got, want) 115 } 116 return 117 } 118 diff := math.Abs(got - want) 119 if diff > tol { 120 t.Errorf("%v: unexpected result; got %v, want %v, diff=%v", name, got, want, diff) 121 } 122 }