github.com/gopherd/gonum@v0.0.4/lapack/testlapack/dlangb.go (about) 1 // Copyright ©2021 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 "math/rand" 13 14 "github.com/gopherd/gonum/floats" 15 "github.com/gopherd/gonum/lapack" 16 ) 17 18 type Dlangber interface { 19 Dlangb(norm lapack.MatrixNorm, m, n, kl, ku int, ab []float64, ldab int) float64 20 } 21 22 func DlangbTest(t *testing.T, impl Dlangber) { 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 _, m := range []int{0, 1, 2, 3, 4, 5, 10} { 28 for _, kl := range []int{0, 1, 2, 3, 4, 5, 10} { 29 for _, ku := range []int{0, 1, 2, 3, 4, 5, 10} { 30 for _, ldab := range []int{kl + ku + 1, kl + ku + 1 + 7} { 31 dlangbTest(t, impl, rnd, norm, m, n, kl, ku, ldab) 32 } 33 } 34 } 35 } 36 } 37 }) 38 } 39 } 40 41 func dlangbTest(t *testing.T, impl Dlangber, rnd *rand.Rand, norm lapack.MatrixNorm, m, n, kl, ku, ldab int) { 42 const tol = 1e-14 43 44 name := fmt.Sprintf("m=%v,n=%v,kl=%v,ku=%v,ldab=%v", m, n, kl, ku, ldab) 45 46 // Generate a random band matrix. 47 ab := randomSlice(m*ldab, rnd) 48 // Sometimes put a NaN into the matrix. 49 if m > 0 && n > 0 && rnd.Float64() < 0.5 { 50 i := rnd.Intn(m) 51 ab[i*ldab+kl] = math.NaN() 52 } 53 abCopy := make([]float64, len(ab)) 54 copy(abCopy, ab) 55 56 // Deal with zero-sized matrices early. 57 if m == 0 || n == 0 { 58 got := impl.Dlangb(norm, m, n, kl, ku, nil, ldab) 59 if got != 0 { 60 t.Errorf("%v: unexpected result for zero-sized matrix with nil input", name) 61 } 62 got = impl.Dlangb(norm, m, n, kl, ku, ab, ldab) 63 if !floats.Same(ab, abCopy) { 64 t.Errorf("%v: unexpected modification in dl", name) 65 } 66 if got != 0 { 67 t.Errorf("%v: unexpected result for zero-sized matrix with non-nil input", name) 68 } 69 return 70 } 71 72 got := impl.Dlangb(norm, m, n, kl, ku, ab, ldab) 73 74 if !floats.Same(ab, abCopy) { 75 t.Errorf("%v: unexpected modification in ab", name) 76 } 77 78 // Generate a dense representation of the matrix and compute the wanted result. 79 a := zeros(m, n, n) 80 for i := 0; i < m; i++ { 81 for j := max(0, i-kl); j < min(i+ku+1, n); j++ { 82 a.Data[i*a.Stride+j] = ab[i*ldab+j-i+kl] 83 } 84 } 85 want := dlange(norm, a.Rows, a.Cols, a.Data, a.Stride) 86 87 if math.IsNaN(want) { 88 if !math.IsNaN(got) { 89 t.Errorf("%v: unexpected result with NaN element; got %v, want %v", name, got, want) 90 } 91 return 92 } 93 94 if math.IsNaN(got) { 95 t.Errorf("%v: unexpected NaN; want %v", name, want) 96 return 97 } 98 99 if norm == lapack.MaxAbs { 100 if got != want { 101 t.Errorf("%v: unexpected result; got %v, want %v", name, got, want) 102 } 103 return 104 } 105 diff := math.Abs(got - want) 106 if diff > tol { 107 t.Errorf("%v: unexpected result; got %v, want %v, diff=%v", name, got, want, diff) 108 } 109 }