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  }