gonum.org/v1/gonum@v0.14.0/blas/blas64/conv_symmetric_test.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 blas64
     6  
     7  import (
     8  	"math"
     9  	"testing"
    10  
    11  	"gonum.org/v1/gonum/blas"
    12  )
    13  
    14  func newSymmetricFrom(a SymmetricCols) Symmetric {
    15  	t := Symmetric{
    16  		N:      a.N,
    17  		Stride: a.N,
    18  		Data:   make([]float64, a.N*a.N),
    19  		Uplo:   a.Uplo,
    20  	}
    21  	t.From(a)
    22  	return t
    23  }
    24  
    25  func (m Symmetric) n() int { return m.N }
    26  func (m Symmetric) at(i, j int) float64 {
    27  	if m.Uplo == blas.Lower && i < j && j < m.N {
    28  		i, j = j, i
    29  	}
    30  	if m.Uplo == blas.Upper && i > j {
    31  		i, j = j, i
    32  	}
    33  	return m.Data[i*m.Stride+j]
    34  }
    35  func (m Symmetric) uplo() blas.Uplo { return m.Uplo }
    36  
    37  func newSymmetricColsFrom(a Symmetric) SymmetricCols {
    38  	t := SymmetricCols{
    39  		N:      a.N,
    40  		Stride: a.N,
    41  		Data:   make([]float64, a.N*a.N),
    42  		Uplo:   a.Uplo,
    43  	}
    44  	t.From(a)
    45  	return t
    46  }
    47  
    48  func (m SymmetricCols) n() int { return m.N }
    49  func (m SymmetricCols) at(i, j int) float64 {
    50  	if m.Uplo == blas.Lower && i < j {
    51  		i, j = j, i
    52  	}
    53  	if m.Uplo == blas.Upper && i > j && i < m.N {
    54  		i, j = j, i
    55  	}
    56  	return m.Data[i+j*m.Stride]
    57  }
    58  func (m SymmetricCols) uplo() blas.Uplo { return m.Uplo }
    59  
    60  type symmetric interface {
    61  	n() int
    62  	at(i, j int) float64
    63  	uplo() blas.Uplo
    64  }
    65  
    66  func sameSymmetric(a, b symmetric) bool {
    67  	an := a.n()
    68  	bn := b.n()
    69  	if an != bn {
    70  		return false
    71  	}
    72  	if a.uplo() != b.uplo() {
    73  		return false
    74  	}
    75  	for i := 0; i < an; i++ {
    76  		for j := 0; j < an; j++ {
    77  			if a.at(i, j) != b.at(i, j) || math.IsNaN(a.at(i, j)) != math.IsNaN(b.at(i, j)) {
    78  				return false
    79  			}
    80  		}
    81  	}
    82  	return true
    83  }
    84  
    85  var symmetricTests = []Symmetric{
    86  	{N: 3, Stride: 3, Data: []float64{
    87  		1, 2, 3,
    88  		4, 5, 6,
    89  		7, 8, 9,
    90  	}},
    91  	{N: 3, Stride: 5, Data: []float64{
    92  		1, 2, 3, 0, 0,
    93  		4, 5, 6, 0, 0,
    94  		7, 8, 9, 0, 0,
    95  	}},
    96  }
    97  
    98  func TestConvertSymmetric(t *testing.T) {
    99  	for _, test := range symmetricTests {
   100  		for _, uplo := range []blas.Uplo{blas.Upper, blas.Lower} {
   101  			test.Uplo = uplo
   102  			colmajor := newSymmetricColsFrom(test)
   103  			if !sameSymmetric(colmajor, test) {
   104  				t.Errorf("unexpected result for row major to col major conversion:\n\tgot: %#v\n\tfrom:%#v",
   105  					colmajor, test)
   106  			}
   107  			rowmajor := newSymmetricFrom(colmajor)
   108  			if !sameSymmetric(rowmajor, test) {
   109  				t.Errorf("unexpected result for col major to row major conversion:\n\tgot: %#v\n\twant:%#v",
   110  					rowmajor, test)
   111  			}
   112  		}
   113  	}
   114  }
   115  func newSymmetricBandFrom(a SymmetricBandCols) SymmetricBand {
   116  	t := SymmetricBand{
   117  		N:      a.N,
   118  		K:      a.K,
   119  		Stride: a.K + 1,
   120  		Data:   make([]float64, a.N*(a.K+1)),
   121  		Uplo:   a.Uplo,
   122  	}
   123  	for i := range t.Data {
   124  		t.Data[i] = math.NaN()
   125  	}
   126  	t.From(a)
   127  	return t
   128  }
   129  
   130  func (m SymmetricBand) n() (n int) { return m.N }
   131  func (m SymmetricBand) at(i, j int) float64 {
   132  	b := Band{
   133  		Rows: m.N, Cols: m.N,
   134  		Stride: m.Stride,
   135  		Data:   m.Data,
   136  	}
   137  	switch m.Uplo {
   138  	default:
   139  		panic("blas64: bad BLAS uplo")
   140  	case blas.Upper:
   141  		b.KU = m.K
   142  		if i > j {
   143  			i, j = j, i
   144  		}
   145  	case blas.Lower:
   146  		b.KL = m.K
   147  		if i < j {
   148  			i, j = j, i
   149  		}
   150  	}
   151  	return b.at(i, j)
   152  }
   153  func (m SymmetricBand) bandwidth() (k int) { return m.K }
   154  func (m SymmetricBand) uplo() blas.Uplo    { return m.Uplo }
   155  
   156  func newSymmetricBandColsFrom(a SymmetricBand) SymmetricBandCols {
   157  	t := SymmetricBandCols{
   158  		N:      a.N,
   159  		K:      a.K,
   160  		Stride: a.K + 1,
   161  		Data:   make([]float64, a.N*(a.K+1)),
   162  		Uplo:   a.Uplo,
   163  	}
   164  	for i := range t.Data {
   165  		t.Data[i] = math.NaN()
   166  	}
   167  	t.From(a)
   168  	return t
   169  }
   170  
   171  func (m SymmetricBandCols) n() (n int) { return m.N }
   172  func (m SymmetricBandCols) at(i, j int) float64 {
   173  	b := BandCols{
   174  		Rows: m.N, Cols: m.N,
   175  		Stride: m.Stride,
   176  		Data:   m.Data,
   177  	}
   178  	switch m.Uplo {
   179  	default:
   180  		panic("blas64: bad BLAS uplo")
   181  	case blas.Upper:
   182  		b.KU = m.K
   183  		if i > j {
   184  			i, j = j, i
   185  		}
   186  	case blas.Lower:
   187  		b.KL = m.K
   188  		if i < j {
   189  			i, j = j, i
   190  		}
   191  	}
   192  	return b.at(i, j)
   193  }
   194  func (m SymmetricBandCols) bandwidth() (k int) { return m.K }
   195  func (m SymmetricBandCols) uplo() blas.Uplo    { return m.Uplo }
   196  
   197  type symmetricBand interface {
   198  	n() (n int)
   199  	at(i, j int) float64
   200  	bandwidth() (k int)
   201  	uplo() blas.Uplo
   202  }
   203  
   204  func sameSymmetricBand(a, b symmetricBand) bool {
   205  	an := a.n()
   206  	bn := b.n()
   207  	if an != bn {
   208  		return false
   209  	}
   210  	if a.uplo() != b.uplo() {
   211  		return false
   212  	}
   213  	ak := a.bandwidth()
   214  	bk := b.bandwidth()
   215  	if ak != bk {
   216  		return false
   217  	}
   218  	for i := 0; i < an; i++ {
   219  		for j := 0; j < an; j++ {
   220  			if a.at(i, j) != b.at(i, j) || math.IsNaN(a.at(i, j)) != math.IsNaN(b.at(i, j)) {
   221  				return false
   222  			}
   223  		}
   224  	}
   225  	return true
   226  }
   227  
   228  var symmetricBandTests = []SymmetricBand{
   229  	{N: 3, K: 0, Stride: 1, Uplo: blas.Upper, Data: []float64{
   230  		1,
   231  		2,
   232  		3,
   233  	}},
   234  	{N: 3, K: 0, Stride: 1, Uplo: blas.Lower, Data: []float64{
   235  		1,
   236  		2,
   237  		3,
   238  	}},
   239  	{N: 3, K: 1, Stride: 2, Uplo: blas.Upper, Data: []float64{
   240  		1, 2,
   241  		3, 4,
   242  		5, -1,
   243  	}},
   244  	{N: 3, K: 1, Stride: 2, Uplo: blas.Lower, Data: []float64{
   245  		-1, 1,
   246  		2, 3,
   247  		4, 5,
   248  	}},
   249  	{N: 3, K: 2, Stride: 3, Uplo: blas.Upper, Data: []float64{
   250  		1, 2, 3,
   251  		4, 5, -1,
   252  		6, -2, -3,
   253  	}},
   254  	{N: 3, K: 2, Stride: 3, Uplo: blas.Lower, Data: []float64{
   255  		-2, -1, 1,
   256  		-3, 2, 4,
   257  		3, 5, 6,
   258  	}},
   259  
   260  	{N: 3, K: 0, Stride: 5, Uplo: blas.Upper, Data: []float64{
   261  		1, 0, 0, 0, 0,
   262  		2, 0, 0, 0, 0,
   263  		3, 0, 0, 0, 0,
   264  	}},
   265  	{N: 3, K: 0, Stride: 5, Uplo: blas.Lower, Data: []float64{
   266  		1, 0, 0, 0, 0,
   267  		2, 0, 0, 0, 0,
   268  		3, 0, 0, 0, 0,
   269  	}},
   270  	{N: 3, K: 1, Stride: 5, Uplo: blas.Upper, Data: []float64{
   271  		1, 2, 0, 0, 0,
   272  		3, 4, 0, 0, 0,
   273  		5, -1, 0, 0, 0,
   274  	}},
   275  	{N: 3, K: 1, Stride: 5, Uplo: blas.Lower, Data: []float64{
   276  		-1, 1, 0, 0, 0,
   277  		2, 3, 0, 0, 0,
   278  		4, 5, 0, 0, 0,
   279  	}},
   280  	{N: 3, K: 2, Stride: 5, Uplo: blas.Upper, Data: []float64{
   281  		1, 2, 3, 0, 0,
   282  		4, 5, -1, 0, 0,
   283  		6, -2, -3, 0, 0,
   284  	}},
   285  	{N: 3, K: 2, Stride: 5, Uplo: blas.Lower, Data: []float64{
   286  		-2, -1, 1, 0, 0,
   287  		-3, 2, 4, 0, 0,
   288  		3, 5, 6, 0, 0,
   289  	}},
   290  }
   291  
   292  func TestConvertSymBand(t *testing.T) {
   293  	for _, test := range symmetricBandTests {
   294  		colmajor := newSymmetricBandColsFrom(test)
   295  		if !sameSymmetricBand(colmajor, test) {
   296  			t.Errorf("unexpected result for row major to col major conversion:\n\tgot: %#v\n\tfrom:%#v",
   297  				colmajor, test)
   298  		}
   299  		rowmajor := newSymmetricBandFrom(colmajor)
   300  		if !sameSymmetricBand(rowmajor, test) {
   301  			t.Errorf("unexpected result for col major to row major conversion:\n\tgot: %#v\n\twant:%#v",
   302  				rowmajor, test)
   303  		}
   304  	}
   305  }