github.com/gonum/lapack@v0.0.0-20181123203213-e4cdc5a0bff9/testlapack/dtrcon.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  	"math/rand"
    10  	"testing"
    11  
    12  	"github.com/gonum/blas"
    13  	"github.com/gonum/floats"
    14  	"github.com/gonum/lapack"
    15  )
    16  
    17  type Dtrconer interface {
    18  	Dgeconer
    19  	Dtrcon(norm lapack.MatrixNorm, uplo blas.Uplo, diag blas.Diag, n int, a []float64, lda int, work []float64, iwork []int) float64
    20  }
    21  
    22  func DtrconTest(t *testing.T, impl Dtrconer) {
    23  	rnd := rand.New(rand.NewSource(1))
    24  	// Hand crafted tests.
    25  	for _, test := range []struct {
    26  		a       []float64
    27  		n       int
    28  		uplo    blas.Uplo
    29  		diag    blas.Diag
    30  		condOne float64
    31  		condInf float64
    32  	}{
    33  		{
    34  			a: []float64{
    35  				8, 5, 6,
    36  				0, 7, 8,
    37  				0, 0, 6,
    38  			},
    39  			n:       3,
    40  			uplo:    blas.Upper,
    41  			diag:    blas.Unit,
    42  			condOne: 1.0 / 645,
    43  			condInf: 1.0 / 480,
    44  		},
    45  		{
    46  			a: []float64{
    47  				8, 5, 6,
    48  				0, 7, 8,
    49  				0, 0, 6,
    50  			},
    51  			n:       3,
    52  			uplo:    blas.Upper,
    53  			diag:    blas.NonUnit,
    54  			condOne: 0.137704918032787,
    55  			condInf: 0.157894736842105,
    56  		},
    57  		{
    58  			a: []float64{
    59  				8, 0, 0,
    60  				5, 7, 0,
    61  				6, 8, 6,
    62  			},
    63  			n:       3,
    64  			uplo:    blas.Lower,
    65  			diag:    blas.Unit,
    66  			condOne: 1.0 / 480,
    67  			condInf: 1.0 / 645,
    68  		},
    69  		{
    70  			a: []float64{
    71  				8, 0, 0,
    72  				5, 7, 0,
    73  				6, 8, 6,
    74  			},
    75  			n:       3,
    76  			uplo:    blas.Lower,
    77  			diag:    blas.NonUnit,
    78  			condOne: 0.157894736842105,
    79  			condInf: 0.137704918032787,
    80  		},
    81  	} {
    82  		lda := test.n
    83  		work := make([]float64, 3*test.n)
    84  		for i := range work {
    85  			work[i] = rnd.Float64()
    86  		}
    87  		iwork := make([]int, test.n)
    88  		for i := range iwork {
    89  			iwork[i] = int(rnd.Int31())
    90  		}
    91  		aCopy := make([]float64, len(test.a))
    92  		copy(aCopy, test.a)
    93  		condOne := impl.Dtrcon(lapack.MaxColumnSum, test.uplo, test.diag, test.n, test.a, lda, work, iwork)
    94  		if math.Abs(condOne-test.condOne) > 1e-14 {
    95  			t.Errorf("One norm mismatch. Want %v, got %v.", test.condOne, condOne)
    96  		}
    97  		if !floats.Equal(aCopy, test.a) {
    98  			t.Errorf("a modified during call")
    99  		}
   100  		condInf := impl.Dtrcon(lapack.MaxRowSum, test.uplo, test.diag, test.n, test.a, lda, work, iwork)
   101  		if math.Abs(condInf-test.condInf) > 1e-14 {
   102  			t.Errorf("Inf norm mismatch. Want %v, got %v.", test.condInf, condInf)
   103  		}
   104  		if !floats.Equal(aCopy, test.a) {
   105  			t.Errorf("a modified during call")
   106  		}
   107  	}
   108  
   109  	// Dtrcon does not match the Dgecon output in many cases. See
   110  	// https://github.com/xianyi/OpenBLAS/issues/636
   111  	// TODO(btracey): Uncomment this when the mismatch between Dgecon and Dtrcon
   112  	// is understood.
   113  	/*
   114  		// Randomized tests against Dgecon.
   115  		for _, uplo := range []blas.Uplo{blas.Lower, blas.Upper} {
   116  			for _, diag := range []blas.Diag{blas.NonUnit, blas.Unit} {
   117  				for _, test := range []struct {
   118  					n, lda int
   119  				}{
   120  					{3, 0},
   121  					{4, 9},
   122  				} {
   123  					for trial := 0; trial < 1; trial++ {
   124  						n := test.n
   125  						lda := test.lda
   126  						if lda == 0 {
   127  							lda = n
   128  						}
   129  						a := make([]float64, n*lda)
   130  						if trial == 0 {
   131  							for i := range a {
   132  								a[i] = float64(i + 2)
   133  							}
   134  						} else {
   135  							for i := range a {
   136  								a[i] = rnd.NormFloat64()
   137  							}
   138  						}
   139  
   140  						aDense := make([]float64, len(a))
   141  						if uplo == blas.Upper {
   142  							for i := 0; i < n; i++ {
   143  								for j := i; j < n; j++ {
   144  									aDense[i*lda+j] = a[i*lda+j]
   145  								}
   146  							}
   147  						} else {
   148  							for i := 0; i < n; i++ {
   149  								for j := 0; j <= i; j++ {
   150  									aDense[i*lda+j] = a[i*lda+j]
   151  								}
   152  							}
   153  						}
   154  						if diag == blas.Unit {
   155  							for i := 0; i < n; i++ {
   156  								aDense[i*lda+i] = 1
   157  							}
   158  						}
   159  
   160  						ipiv := make([]int, n)
   161  						work := make([]float64, 4*n)
   162  						denseOne := impl.Dlange(lapack.MaxColumnSum, n, n, aDense, lda, work)
   163  						denseInf := impl.Dlange(lapack.MaxRowSum, n, n, aDense, lda, work)
   164  
   165  						aDenseLU := make([]float64, len(aDense))
   166  						copy(aDenseLU, aDense)
   167  						impl.Dgetrf(n, n, aDenseLU, lda, ipiv)
   168  						iwork := make([]int, n)
   169  						want := impl.Dgecon(lapack.MaxColumnSum, n, aDenseLU, lda, denseOne, work, iwork)
   170  						got := impl.Dtrcon(lapack.MaxColumnSum, uplo, diag, n, a, lda, work, iwork)
   171  						if math.Abs(want-got) > 1e-14 {
   172  							t.Errorf("One norm mismatch. Upper = %v, unit = %v, want %v, got %v", uplo == blas.Upper, diag == blas.Unit, want, got)
   173  						}
   174  						want = impl.Dgecon(lapack.MaxRowSum, n, aDenseLU, lda, denseInf, work, iwork)
   175  						got = impl.Dtrcon(lapack.MaxRowSum, uplo, diag, n, a, lda, work, iwork)
   176  						if math.Abs(want-got) > 1e-14 {
   177  							t.Errorf("Inf norm mismatch. Upper = %v, unit = %v, want %v, got %v", uplo == blas.Upper, diag == blas.Unit, want, got)
   178  						}
   179  					}
   180  				}
   181  			}
   182  		}
   183  	*/
   184  }