gonum.org/v1/gonum@v0.14.0/lapack/testlapack/dlange.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  	"math"
     9  	"testing"
    10  
    11  	"golang.org/x/exp/rand"
    12  
    13  	"gonum.org/v1/gonum/blas/blas64"
    14  	"gonum.org/v1/gonum/lapack"
    15  )
    16  
    17  type Dlanger interface {
    18  	Dlange(norm lapack.MatrixNorm, m, n int, a []float64, lda int, work []float64) float64
    19  }
    20  
    21  func DlangeTest(t *testing.T, impl Dlanger) {
    22  	rnd := rand.New(rand.NewSource(1))
    23  	for _, test := range []struct {
    24  		m, n, lda int
    25  	}{
    26  		{4, 3, 0},
    27  		{3, 4, 0},
    28  		{4, 3, 100},
    29  		{3, 4, 100},
    30  	} {
    31  		m := test.m
    32  		n := test.n
    33  		lda := test.lda
    34  		if lda == 0 {
    35  			lda = n
    36  		}
    37  		// Allocate m×n matrix A and fill it with random numbers from [-0.5, 0.5).
    38  		a := make([]float64, m*lda)
    39  		for i := range a {
    40  			a[i] = rnd.Float64() - 0.5
    41  		}
    42  		// Store a copy of A for later comparison.
    43  		aCopy := make([]float64, len(a))
    44  		copy(aCopy, a)
    45  
    46  		// Allocate workspace slice.
    47  		work := make([]float64, n)
    48  		for i := range work {
    49  			work[i] = rnd.Float64()
    50  		}
    51  
    52  		// Test various norms by comparing the result from Dlange with
    53  		// explicit calculation.
    54  
    55  		// Test MaxAbs norm.
    56  		norm := impl.Dlange(lapack.MaxAbs, m, n, a, lda, work)
    57  		var ans float64
    58  		for i := 0; i < m; i++ {
    59  			idx := blas64.Iamax(blas64.Vector{N: n, Inc: 1, Data: aCopy[i*lda:]})
    60  			ans = math.Max(ans, math.Abs(a[i*lda+idx]))
    61  		}
    62  		// Should be strictly equal because there is no floating point summation error.
    63  		if ans != norm {
    64  			t.Errorf("MaxAbs mismatch. Want %v, got %v.", ans, norm)
    65  		}
    66  
    67  		// Test MaxColumnSum norm.
    68  		norm = impl.Dlange(lapack.MaxColumnSum, m, n, a, lda, work)
    69  		ans = 0
    70  		for i := 0; i < n; i++ {
    71  			sum := blas64.Asum(blas64.Vector{N: m, Inc: lda, Data: aCopy[i:]})
    72  			ans = math.Max(ans, sum)
    73  		}
    74  		if math.Abs(norm-ans) > 1e-14 {
    75  			t.Errorf("MaxColumnSum mismatch. Want %v, got %v.", ans, norm)
    76  		}
    77  
    78  		// Test MaxRowSum norm.
    79  		norm = impl.Dlange(lapack.MaxRowSum, m, n, a, lda, work)
    80  		ans = 0
    81  		for i := 0; i < m; i++ {
    82  			sum := blas64.Asum(blas64.Vector{N: n, Inc: 1, Data: aCopy[i*lda:]})
    83  			ans = math.Max(ans, sum)
    84  		}
    85  		if math.Abs(norm-ans) > 1e-14 {
    86  			t.Errorf("MaxRowSum mismatch. Want %v, got %v.", ans, norm)
    87  		}
    88  
    89  		// Test Frobenius norm.
    90  		norm = impl.Dlange(lapack.Frobenius, m, n, a, lda, work)
    91  		ans = 0
    92  		for i := 0; i < m; i++ {
    93  			sum := blas64.Nrm2(blas64.Vector{N: n, Inc: 1, Data: aCopy[i*lda:]})
    94  			ans += sum * sum
    95  		}
    96  		ans = math.Sqrt(ans)
    97  		if math.Abs(norm-ans) > 1e-14 {
    98  			t.Errorf("Frobenius norm mismatch. Want %v, got %v.", ans, norm)
    99  		}
   100  	}
   101  }