github.com/jingcheng-WU/gonum@v0.9.1-0.20210323123734-f1a2a11a8f7b/mat/dense_test.go (about)

     1  // Copyright ©2013 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 mat
     6  
     7  import (
     8  	"fmt"
     9  	"math"
    10  	"reflect"
    11  	"strings"
    12  	"testing"
    13  
    14  	"golang.org/x/exp/rand"
    15  
    16  	"github.com/jingcheng-WU/gonum/blas/blas64"
    17  	"github.com/jingcheng-WU/gonum/floats"
    18  )
    19  
    20  func TestNewDense(t *testing.T) {
    21  	t.Parallel()
    22  	for i, test := range []struct {
    23  		a          []float64
    24  		rows, cols int
    25  		min, max   float64
    26  		fro        float64
    27  		mat        *Dense
    28  	}{
    29  		{
    30  			[]float64{
    31  				0, 0, 0,
    32  				0, 0, 0,
    33  				0, 0, 0,
    34  			},
    35  			3, 3,
    36  			0, 0,
    37  			0,
    38  			&Dense{
    39  				mat: blas64.General{
    40  					Rows: 3, Cols: 3,
    41  					Stride: 3,
    42  					Data:   []float64{0, 0, 0, 0, 0, 0, 0, 0, 0},
    43  				},
    44  				capRows: 3, capCols: 3,
    45  			},
    46  		},
    47  		{
    48  			[]float64{
    49  				1, 1, 1,
    50  				1, 1, 1,
    51  				1, 1, 1,
    52  			},
    53  			3, 3,
    54  			1, 1,
    55  			3,
    56  			&Dense{
    57  				mat: blas64.General{
    58  					Rows: 3, Cols: 3,
    59  					Stride: 3,
    60  					Data:   []float64{1, 1, 1, 1, 1, 1, 1, 1, 1},
    61  				},
    62  				capRows: 3, capCols: 3,
    63  			},
    64  		},
    65  		{
    66  			[]float64{
    67  				1, 0, 0,
    68  				0, 1, 0,
    69  				0, 0, 1,
    70  			},
    71  			3, 3,
    72  			0, 1,
    73  			1.7320508075688772,
    74  			&Dense{
    75  				mat: blas64.General{
    76  					Rows: 3, Cols: 3,
    77  					Stride: 3,
    78  					Data:   []float64{1, 0, 0, 0, 1, 0, 0, 0, 1},
    79  				},
    80  				capRows: 3, capCols: 3,
    81  			},
    82  		},
    83  		{
    84  			[]float64{
    85  				-1, 0, 0,
    86  				0, -1, 0,
    87  				0, 0, -1,
    88  			},
    89  			3, 3,
    90  			-1, 0,
    91  			1.7320508075688772,
    92  			&Dense{
    93  				mat: blas64.General{
    94  					Rows: 3, Cols: 3,
    95  					Stride: 3,
    96  					Data:   []float64{-1, 0, 0, 0, -1, 0, 0, 0, -1},
    97  				},
    98  				capRows: 3, capCols: 3,
    99  			},
   100  		},
   101  		{
   102  			[]float64{
   103  				1, 2, 3,
   104  				4, 5, 6,
   105  			},
   106  			2, 3,
   107  			1, 6,
   108  			9.539392014169458,
   109  			&Dense{
   110  				mat: blas64.General{
   111  					Rows: 2, Cols: 3,
   112  					Stride: 3,
   113  					Data:   []float64{1, 2, 3, 4, 5, 6},
   114  				},
   115  				capRows: 2, capCols: 3,
   116  			},
   117  		},
   118  		{
   119  			[]float64{
   120  				1, 2,
   121  				3, 4,
   122  				5, 6,
   123  			},
   124  			3, 2,
   125  			1, 6,
   126  			9.539392014169458,
   127  			&Dense{
   128  				mat: blas64.General{
   129  					Rows: 3, Cols: 2,
   130  					Stride: 2,
   131  					Data:   []float64{1, 2, 3, 4, 5, 6},
   132  				},
   133  				capRows: 3, capCols: 2,
   134  			},
   135  		},
   136  	} {
   137  		m := NewDense(test.rows, test.cols, test.a)
   138  		rows, cols := m.Dims()
   139  		if rows != test.rows {
   140  			t.Errorf("unexpected number of rows for test %d: got: %d want: %d", i, rows, test.rows)
   141  		}
   142  		if cols != test.cols {
   143  			t.Errorf("unexpected number of cols for test %d: got: %d want: %d", i, cols, test.cols)
   144  		}
   145  		if min := Min(m); min != test.min {
   146  			t.Errorf("unexpected min for test %d: got: %v want: %v", i, min, test.min)
   147  		}
   148  		if max := Max(m); max != test.max {
   149  			t.Errorf("unexpected max for test %d: got: %v want: %v", i, max, test.max)
   150  		}
   151  		if fro := Norm(m, 2); math.Abs(Norm(m, 2)-test.fro) > 1e-14 {
   152  			t.Errorf("unexpected Frobenius norm for test %d: got: %v want: %v", i, fro, test.fro)
   153  		}
   154  		if !reflect.DeepEqual(m, test.mat) {
   155  			t.Errorf("unexpected matrix for test %d", i)
   156  		}
   157  		if !Equal(m, test.mat) {
   158  			t.Errorf("matrix does not equal expected matrix for test %d", i)
   159  		}
   160  	}
   161  }
   162  
   163  func TestDenseAtSet(t *testing.T) {
   164  	t.Parallel()
   165  	for test, af := range [][][]float64{
   166  		{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // even
   167  		{{1, 2}, {4, 5}, {7, 8}},          // wide
   168  		{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, //skinny
   169  	} {
   170  		m := NewDense(flatten(af))
   171  		rows, cols := m.Dims()
   172  		for i := 0; i < rows; i++ {
   173  			for j := 0; j < cols; j++ {
   174  				if m.At(i, j) != af[i][j] {
   175  					t.Errorf("unexpected value for At(%d, %d) for test %d: got: %v want: %v",
   176  						i, j, test, m.At(i, j), af[i][j])
   177  				}
   178  
   179  				v := float64(i * j)
   180  				m.Set(i, j, v)
   181  				if m.At(i, j) != v {
   182  					t.Errorf("unexpected value for At(%d, %d) after Set(%[1]d, %d, %v) for test %d: got: %v want: %[3]v",
   183  						i, j, v, test, m.At(i, j))
   184  				}
   185  			}
   186  		}
   187  		// Check access out of bounds fails
   188  		for _, row := range []int{-1, rows, rows + 1} {
   189  			panicked, message := panics(func() { m.At(row, 0) })
   190  			if !panicked || message != ErrRowAccess.Error() {
   191  				t.Errorf("expected panic for invalid row access N=%d r=%d", rows, row)
   192  			}
   193  		}
   194  		for _, col := range []int{-1, cols, cols + 1} {
   195  			panicked, message := panics(func() { m.At(0, col) })
   196  			if !panicked || message != ErrColAccess.Error() {
   197  				t.Errorf("expected panic for invalid column access N=%d c=%d", cols, col)
   198  			}
   199  		}
   200  
   201  		// Check Set out of bounds
   202  		for _, row := range []int{-1, rows, rows + 1} {
   203  			panicked, message := panics(func() { m.Set(row, 0, 1.2) })
   204  			if !panicked || message != ErrRowAccess.Error() {
   205  				t.Errorf("expected panic for invalid row access N=%d r=%d", rows, row)
   206  			}
   207  		}
   208  		for _, col := range []int{-1, cols, cols + 1} {
   209  			panicked, message := panics(func() { m.Set(0, col, 1.2) })
   210  			if !panicked || message != ErrColAccess.Error() {
   211  				t.Errorf("expected panic for invalid column access N=%d c=%d", cols, col)
   212  			}
   213  		}
   214  	}
   215  }
   216  
   217  func TestDenseSetRowColumn(t *testing.T) {
   218  	t.Parallel()
   219  	for _, as := range [][][]float64{
   220  		{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}},
   221  		{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}, {10, 11, 12}},
   222  		{{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}},
   223  	} {
   224  		for ri, row := range as {
   225  			a := NewDense(flatten(as))
   226  			m := &Dense{}
   227  			m.CloneFrom(a)
   228  			a.SetRow(ri, make([]float64, a.mat.Cols))
   229  			m.Sub(m, a)
   230  			nt := Norm(m, 2)
   231  			nr := floats.Norm(row, 2)
   232  			if math.Abs(nt-nr) > 1e-14 {
   233  				t.Errorf("Row %d norm mismatch, want: %g, got: %g", ri, nr, nt)
   234  			}
   235  		}
   236  
   237  		for ci := range as[0] {
   238  			a := NewDense(flatten(as))
   239  			m := &Dense{}
   240  			m.CloneFrom(a)
   241  			a.SetCol(ci, make([]float64, a.mat.Rows))
   242  			col := make([]float64, a.mat.Rows)
   243  			for j := range col {
   244  				col[j] = float64(ci + 1 + j*a.mat.Cols)
   245  			}
   246  			m.Sub(m, a)
   247  			nt := Norm(m, 2)
   248  			nc := floats.Norm(col, 2)
   249  			if math.Abs(nt-nc) > 1e-14 {
   250  				t.Errorf("Column %d norm mismatch, want: %g, got: %g", ci, nc, nt)
   251  			}
   252  		}
   253  	}
   254  }
   255  
   256  func TestDenseZero(t *testing.T) {
   257  	t.Parallel()
   258  	// Elements that equal 1 should be set to zero, elements that equal -1
   259  	// should remain unchanged.
   260  	for _, test := range []*Dense{
   261  		{
   262  			mat: blas64.General{
   263  				Rows:   4,
   264  				Cols:   3,
   265  				Stride: 5,
   266  				Data: []float64{
   267  					1, 1, 1, -1, -1,
   268  					1, 1, 1, -1, -1,
   269  					1, 1, 1, -1, -1,
   270  					1, 1, 1, -1, -1,
   271  				},
   272  			},
   273  		},
   274  	} {
   275  		dataCopy := make([]float64, len(test.mat.Data))
   276  		copy(dataCopy, test.mat.Data)
   277  		test.Zero()
   278  		for i, v := range test.mat.Data {
   279  			if dataCopy[i] != -1 && v != 0 {
   280  				t.Errorf("Matrix not zeroed in bounds")
   281  			}
   282  			if dataCopy[i] == -1 && v != -1 {
   283  				t.Errorf("Matrix zeroed out of bounds")
   284  			}
   285  		}
   286  	}
   287  }
   288  
   289  func TestDenseRowColView(t *testing.T) {
   290  	t.Parallel()
   291  	for _, test := range []struct {
   292  		mat [][]float64
   293  	}{
   294  		{
   295  			mat: [][]float64{
   296  				{1, 2, 3, 4, 5},
   297  				{6, 7, 8, 9, 10},
   298  				{11, 12, 13, 14, 15},
   299  				{16, 17, 18, 19, 20},
   300  				{21, 22, 23, 24, 25},
   301  			},
   302  		},
   303  		{
   304  			mat: [][]float64{
   305  				{1, 2, 3, 4},
   306  				{6, 7, 8, 9},
   307  				{11, 12, 13, 14},
   308  				{16, 17, 18, 19},
   309  				{21, 22, 23, 24},
   310  			},
   311  		},
   312  		{
   313  			mat: [][]float64{
   314  				{1, 2, 3, 4, 5},
   315  				{6, 7, 8, 9, 10},
   316  				{11, 12, 13, 14, 15},
   317  				{16, 17, 18, 19, 20},
   318  			},
   319  		},
   320  	} {
   321  		// This over cautious approach to building a matrix data
   322  		// slice is to ensure that changes to flatten in the future
   323  		// do not mask a regression to the issue identified in
   324  		// gonum/matrix#110.
   325  		rows, cols, flat := flatten(test.mat)
   326  		m := NewDense(rows, cols, flat[:len(flat):len(flat)])
   327  
   328  		for _, row := range []int{-1, rows, rows + 1} {
   329  			panicked, message := panics(func() { m.At(row, 0) })
   330  			if !panicked || message != ErrRowAccess.Error() {
   331  				t.Errorf("expected panic for invalid row access rows=%d r=%d", rows, row)
   332  			}
   333  		}
   334  		for _, col := range []int{-1, cols, cols + 1} {
   335  			panicked, message := panics(func() { m.At(0, col) })
   336  			if !panicked || message != ErrColAccess.Error() {
   337  				t.Errorf("expected panic for invalid column access cols=%d c=%d", cols, col)
   338  			}
   339  		}
   340  
   341  		for i := 0; i < rows; i++ {
   342  			vr := m.RowView(i)
   343  			if vr.Len() != cols {
   344  				t.Errorf("unexpected number of columns: got: %d want: %d", vr.Len(), cols)
   345  			}
   346  			for j := 0; j < cols; j++ {
   347  				if got := vr.At(j, 0); got != test.mat[i][j] {
   348  					t.Errorf("unexpected value for row.At(%d, 0): got: %v want: %v",
   349  						j, got, test.mat[i][j])
   350  				}
   351  			}
   352  		}
   353  		for j := 0; j < cols; j++ {
   354  			vc := m.ColView(j)
   355  			if vc.Len() != rows {
   356  				t.Errorf("unexpected number of rows: got: %d want: %d", vc.Len(), rows)
   357  			}
   358  			for i := 0; i < rows; i++ {
   359  				if got := vc.At(i, 0); got != test.mat[i][j] {
   360  					t.Errorf("unexpected value for col.At(%d, 0): got: %v want: %v",
   361  						i, got, test.mat[i][j])
   362  				}
   363  			}
   364  		}
   365  		m = m.Slice(1, rows-1, 1, cols-1).(*Dense)
   366  		for i := 1; i < rows-1; i++ {
   367  			vr := m.RowView(i - 1)
   368  			if vr.Len() != cols-2 {
   369  				t.Errorf("unexpected number of columns: got: %d want: %d", vr.Len(), cols-2)
   370  			}
   371  			for j := 1; j < cols-1; j++ {
   372  				if got := vr.At(j-1, 0); got != test.mat[i][j] {
   373  					t.Errorf("unexpected value for row.At(%d, 0): got: %v want: %v",
   374  						j-1, got, test.mat[i][j])
   375  				}
   376  			}
   377  		}
   378  		for j := 1; j < cols-1; j++ {
   379  			vc := m.ColView(j - 1)
   380  			if vc.Len() != rows-2 {
   381  				t.Errorf("unexpected number of rows: got: %d want: %d", vc.Len(), rows-2)
   382  			}
   383  			for i := 1; i < rows-1; i++ {
   384  				if got := vc.At(i-1, 0); got != test.mat[i][j] {
   385  					t.Errorf("unexpected value for col.At(%d, 0): got: %v want: %v",
   386  						i-1, got, test.mat[i][j])
   387  				}
   388  			}
   389  		}
   390  	}
   391  }
   392  
   393  func TestDenseDiagView(t *testing.T) {
   394  	t.Parallel()
   395  	for cas, test := range []*Dense{
   396  		NewDense(1, 1, []float64{1}),
   397  		NewDense(2, 2, []float64{1, 2, 3, 4}),
   398  		NewDense(3, 4, []float64{
   399  			1, 2, 3, 4,
   400  			5, 6, 7, 8,
   401  			9, 10, 11, 12,
   402  		}),
   403  		NewDense(4, 3, []float64{
   404  			1, 2, 3,
   405  			4, 5, 6,
   406  			7, 8, 9,
   407  			10, 11, 12,
   408  		}),
   409  	} {
   410  		testDiagView(t, cas, test)
   411  	}
   412  }
   413  
   414  func TestDenseGrow(t *testing.T) {
   415  	t.Parallel()
   416  	m := &Dense{}
   417  	m = m.Grow(10, 10).(*Dense)
   418  	rows, cols := m.Dims()
   419  	capRows, capCols := m.Caps()
   420  	if rows != 10 {
   421  		t.Errorf("unexpected value for rows: got: %d want: 10", rows)
   422  	}
   423  	if cols != 10 {
   424  		t.Errorf("unexpected value for cols: got: %d want: 10", cols)
   425  	}
   426  	if capRows != 10 {
   427  		t.Errorf("unexpected value for capRows: got: %d want: 10", capRows)
   428  	}
   429  	if capCols != 10 {
   430  		t.Errorf("unexpected value for capCols: got: %d want: 10", capCols)
   431  	}
   432  
   433  	// Test grow within caps is in-place.
   434  	m.Set(1, 1, 1)
   435  	v := m.Slice(1, 5, 1, 5).(*Dense)
   436  	if v.At(0, 0) != m.At(1, 1) {
   437  		t.Errorf("unexpected viewed element value: got: %v want: %v", v.At(0, 0), m.At(1, 1))
   438  	}
   439  	v = v.Grow(5, 5).(*Dense)
   440  	if !Equal(v, m.Slice(1, 10, 1, 10)) {
   441  		t.Error("unexpected view value after grow")
   442  	}
   443  
   444  	// Test grow bigger than caps copies.
   445  	v = v.Grow(5, 5).(*Dense)
   446  	if !Equal(v.Slice(0, 9, 0, 9), m.Slice(1, 10, 1, 10)) {
   447  		t.Error("unexpected mismatched common view value after grow")
   448  	}
   449  	v.Set(0, 0, 0)
   450  	if Equal(v.Slice(0, 9, 0, 9), m.Slice(1, 10, 1, 10)) {
   451  		t.Error("unexpected matching view value after grow past capacity")
   452  	}
   453  
   454  	// Test grow uses existing data slice when matrix is zero size.
   455  	v.Reset()
   456  	p, l := &v.mat.Data[:1][0], cap(v.mat.Data)
   457  	*p = 1 // This element is at position (-1, -1) relative to v and so should not be visible.
   458  	v = v.Grow(5, 5).(*Dense)
   459  	if &v.mat.Data[:1][0] != p {
   460  		t.Error("grow unexpectedly copied slice within cap limit")
   461  	}
   462  	if cap(v.mat.Data) != l {
   463  		t.Errorf("unexpected change in data slice capacity: got: %d want: %d", cap(v.mat.Data), l)
   464  	}
   465  	if v.At(0, 0) != 0 {
   466  		t.Errorf("unexpected value for At(0, 0): got: %v want: 0", v.At(0, 0))
   467  	}
   468  }
   469  
   470  func TestDenseAdd(t *testing.T) {
   471  	t.Parallel()
   472  	for i, test := range []struct {
   473  		a, b, r [][]float64
   474  	}{
   475  		{
   476  			[][]float64{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
   477  			[][]float64{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
   478  			[][]float64{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
   479  		},
   480  		{
   481  			[][]float64{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}},
   482  			[][]float64{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}},
   483  			[][]float64{{2, 2, 2}, {2, 2, 2}, {2, 2, 2}},
   484  		},
   485  		{
   486  			[][]float64{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}},
   487  			[][]float64{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}},
   488  			[][]float64{{2, 0, 0}, {0, 2, 0}, {0, 0, 2}},
   489  		},
   490  		{
   491  			[][]float64{{-1, 0, 0}, {0, -1, 0}, {0, 0, -1}},
   492  			[][]float64{{-1, 0, 0}, {0, -1, 0}, {0, 0, -1}},
   493  			[][]float64{{-2, 0, 0}, {0, -2, 0}, {0, 0, -2}},
   494  		},
   495  		{
   496  			[][]float64{{1, 2, 3}, {4, 5, 6}},
   497  			[][]float64{{1, 2, 3}, {4, 5, 6}},
   498  			[][]float64{{2, 4, 6}, {8, 10, 12}},
   499  		},
   500  	} {
   501  		a := NewDense(flatten(test.a))
   502  		b := NewDense(flatten(test.b))
   503  		r := NewDense(flatten(test.r))
   504  
   505  		var temp Dense
   506  		temp.Add(a, b)
   507  		if !Equal(&temp, r) {
   508  			t.Errorf("unexpected result from Add for test %d %v Add %v: got: %v want: %v",
   509  				i, test.a, test.b, unflatten(temp.mat.Rows, temp.mat.Cols, temp.mat.Data), test.r)
   510  		}
   511  
   512  		zero(temp.mat.Data)
   513  		temp.Add(a, b)
   514  		if !Equal(&temp, r) {
   515  			t.Errorf("unexpected result from Add for test %d %v Add %v: got: %v want: %v",
   516  				i, test.a, test.b, unflatten(temp.mat.Rows, temp.mat.Cols, temp.mat.Data), test.r)
   517  		}
   518  
   519  		// These probably warrant a better check and failure. They should never happen in the wild though.
   520  		temp.mat.Data = nil
   521  		panicked, message := panics(func() { temp.Add(a, b) })
   522  		if !panicked || !strings.HasPrefix(message, "runtime error: index out of range") {
   523  			t.Error("exected runtime panic for nil data slice")
   524  		}
   525  
   526  		a.Add(a, b)
   527  		if !Equal(a, r) {
   528  			t.Errorf("unexpected result from Add for test %d %v Add %v: got: %v want: %v",
   529  				i, test.a, test.b, unflatten(a.mat.Rows, a.mat.Cols, a.mat.Data), test.r)
   530  		}
   531  	}
   532  
   533  	panicked, message := panics(func() {
   534  		m := NewDense(10, 10, nil)
   535  		a := NewDense(5, 5, nil)
   536  		m.Slice(1, 6, 1, 6).(*Dense).Add(a, m.Slice(2, 7, 2, 7))
   537  	})
   538  	if !panicked {
   539  		t.Error("expected panic for overlapping matrices")
   540  	}
   541  	if message != regionOverlap {
   542  		t.Errorf("unexpected panic message: got: %q want: %q", message, regionOverlap)
   543  	}
   544  
   545  	method := func(receiver, a, b Matrix) {
   546  		type Adder interface {
   547  			Add(a, b Matrix)
   548  		}
   549  		rd := receiver.(Adder)
   550  		rd.Add(a, b)
   551  	}
   552  	denseComparison := func(receiver, a, b *Dense) {
   553  		receiver.Add(a, b)
   554  	}
   555  	testTwoInput(t, "Add", &Dense{}, method, denseComparison, legalTypesAll, legalSizeSameRectangular, 1e-14)
   556  }
   557  
   558  func TestDenseSub(t *testing.T) {
   559  	t.Parallel()
   560  	for i, test := range []struct {
   561  		a, b, r [][]float64
   562  	}{
   563  		{
   564  			[][]float64{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
   565  			[][]float64{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
   566  			[][]float64{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
   567  		},
   568  		{
   569  			[][]float64{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}},
   570  			[][]float64{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}},
   571  			[][]float64{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
   572  		},
   573  		{
   574  			[][]float64{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}},
   575  			[][]float64{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}},
   576  			[][]float64{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
   577  		},
   578  		{
   579  			[][]float64{{-1, 0, 0}, {0, -1, 0}, {0, 0, -1}},
   580  			[][]float64{{-1, 0, 0}, {0, -1, 0}, {0, 0, -1}},
   581  			[][]float64{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
   582  		},
   583  		{
   584  			[][]float64{{1, 2, 3}, {4, 5, 6}},
   585  			[][]float64{{1, 2, 3}, {4, 5, 6}},
   586  			[][]float64{{0, 0, 0}, {0, 0, 0}},
   587  		},
   588  	} {
   589  		a := NewDense(flatten(test.a))
   590  		b := NewDense(flatten(test.b))
   591  		r := NewDense(flatten(test.r))
   592  
   593  		var temp Dense
   594  		temp.Sub(a, b)
   595  		if !Equal(&temp, r) {
   596  			t.Errorf("unexpected result from Sub for test %d %v Sub %v: got: %v want: %v",
   597  				i, test.a, test.b, unflatten(temp.mat.Rows, temp.mat.Cols, temp.mat.Data), test.r)
   598  		}
   599  
   600  		zero(temp.mat.Data)
   601  		temp.Sub(a, b)
   602  		if !Equal(&temp, r) {
   603  			t.Errorf("unexpected result from Sub for test %d %v Sub %v: got: %v want: %v",
   604  				i, test.a, test.b, unflatten(temp.mat.Rows, temp.mat.Cols, temp.mat.Data), test.r)
   605  		}
   606  
   607  		// These probably warrant a better check and failure. They should never happen in the wild though.
   608  		temp.mat.Data = nil
   609  		panicked, message := panics(func() { temp.Sub(a, b) })
   610  		if !panicked || !strings.HasPrefix(message, "runtime error: index out of range") {
   611  			t.Error("exected runtime panic for nil data slice")
   612  		}
   613  
   614  		a.Sub(a, b)
   615  		if !Equal(a, r) {
   616  			t.Errorf("unexpected result from Sub for test %d %v Sub %v: got: %v want: %v",
   617  				i, test.a, test.b, unflatten(a.mat.Rows, a.mat.Cols, a.mat.Data), test.r)
   618  		}
   619  	}
   620  
   621  	panicked, message := panics(func() {
   622  		m := NewDense(10, 10, nil)
   623  		a := NewDense(5, 5, nil)
   624  		m.Slice(1, 6, 1, 6).(*Dense).Sub(a, m.Slice(2, 7, 2, 7))
   625  	})
   626  	if !panicked {
   627  		t.Error("expected panic for overlapping matrices")
   628  	}
   629  	if message != regionOverlap {
   630  		t.Errorf("unexpected panic message: got: %q want: %q", message, regionOverlap)
   631  	}
   632  
   633  	method := func(receiver, a, b Matrix) {
   634  		type Suber interface {
   635  			Sub(a, b Matrix)
   636  		}
   637  		rd := receiver.(Suber)
   638  		rd.Sub(a, b)
   639  	}
   640  	denseComparison := func(receiver, a, b *Dense) {
   641  		receiver.Sub(a, b)
   642  	}
   643  	testTwoInput(t, "Sub", &Dense{}, method, denseComparison, legalTypesAll, legalSizeSameRectangular, 1e-14)
   644  }
   645  
   646  func TestDenseMulElem(t *testing.T) {
   647  	t.Parallel()
   648  	for i, test := range []struct {
   649  		a, b, r [][]float64
   650  	}{
   651  		{
   652  			[][]float64{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
   653  			[][]float64{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
   654  			[][]float64{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
   655  		},
   656  		{
   657  			[][]float64{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}},
   658  			[][]float64{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}},
   659  			[][]float64{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}},
   660  		},
   661  		{
   662  			[][]float64{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}},
   663  			[][]float64{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}},
   664  			[][]float64{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}},
   665  		},
   666  		{
   667  			[][]float64{{-1, 0, 0}, {0, -1, 0}, {0, 0, -1}},
   668  			[][]float64{{-1, 0, 0}, {0, -1, 0}, {0, 0, -1}},
   669  			[][]float64{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}},
   670  		},
   671  		{
   672  			[][]float64{{1, 2, 3}, {4, 5, 6}},
   673  			[][]float64{{1, 2, 3}, {4, 5, 6}},
   674  			[][]float64{{1, 4, 9}, {16, 25, 36}},
   675  		},
   676  	} {
   677  		a := NewDense(flatten(test.a))
   678  		b := NewDense(flatten(test.b))
   679  		r := NewDense(flatten(test.r))
   680  
   681  		var temp Dense
   682  		temp.MulElem(a, b)
   683  		if !Equal(&temp, r) {
   684  			t.Errorf("unexpected result from MulElem for test %d %v MulElem %v: got: %v want: %v",
   685  				i, test.a, test.b, unflatten(temp.mat.Rows, temp.mat.Cols, temp.mat.Data), test.r)
   686  		}
   687  
   688  		zero(temp.mat.Data)
   689  		temp.MulElem(a, b)
   690  		if !Equal(&temp, r) {
   691  			t.Errorf("unexpected result from MulElem for test %d %v MulElem %v: got: %v want: %v",
   692  				i, test.a, test.b, unflatten(temp.mat.Rows, temp.mat.Cols, temp.mat.Data), test.r)
   693  		}
   694  
   695  		// These probably warrant a better check and failure. They should never happen in the wild though.
   696  		temp.mat.Data = nil
   697  		panicked, message := panics(func() { temp.MulElem(a, b) })
   698  		if !panicked || !strings.HasPrefix(message, "runtime error: index out of range") {
   699  			t.Error("exected runtime panic for nil data slice")
   700  		}
   701  
   702  		a.MulElem(a, b)
   703  		if !Equal(a, r) {
   704  			t.Errorf("unexpected result from MulElem for test %d %v MulElem %v: got: %v want: %v",
   705  				i, test.a, test.b, unflatten(a.mat.Rows, a.mat.Cols, a.mat.Data), test.r)
   706  		}
   707  	}
   708  
   709  	panicked, message := panics(func() {
   710  		m := NewDense(10, 10, nil)
   711  		a := NewDense(5, 5, nil)
   712  		m.Slice(1, 6, 1, 6).(*Dense).MulElem(a, m.Slice(2, 7, 2, 7))
   713  	})
   714  	if !panicked {
   715  		t.Error("expected panic for overlapping matrices")
   716  	}
   717  	if message != regionOverlap {
   718  		t.Errorf("unexpected panic message: got: %q want: %q", message, regionOverlap)
   719  	}
   720  
   721  	method := func(receiver, a, b Matrix) {
   722  		type ElemMuler interface {
   723  			MulElem(a, b Matrix)
   724  		}
   725  		rd := receiver.(ElemMuler)
   726  		rd.MulElem(a, b)
   727  	}
   728  	denseComparison := func(receiver, a, b *Dense) {
   729  		receiver.MulElem(a, b)
   730  	}
   731  	testTwoInput(t, "MulElem", &Dense{}, method, denseComparison, legalTypesAll, legalSizeSameRectangular, 1e-14)
   732  }
   733  
   734  // A comparison that treats NaNs as equal, for testing.
   735  func (m *Dense) same(b Matrix) bool {
   736  	br, bc := b.Dims()
   737  	if br != m.mat.Rows || bc != m.mat.Cols {
   738  		return false
   739  	}
   740  	for r := 0; r < br; r++ {
   741  		for c := 0; c < bc; c++ {
   742  			if av, bv := m.At(r, c), b.At(r, c); av != bv && !(math.IsNaN(av) && math.IsNaN(bv)) {
   743  				return false
   744  			}
   745  		}
   746  	}
   747  	return true
   748  }
   749  
   750  func TestDenseDivElem(t *testing.T) {
   751  	t.Parallel()
   752  	for i, test := range []struct {
   753  		a, b, r [][]float64
   754  	}{
   755  		{
   756  			[][]float64{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}},
   757  			[][]float64{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
   758  			[][]float64{{math.Inf(1), math.NaN(), math.NaN()}, {math.NaN(), math.Inf(1), math.NaN()}, {math.NaN(), math.NaN(), math.Inf(1)}},
   759  		},
   760  		{
   761  			[][]float64{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}},
   762  			[][]float64{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}},
   763  			[][]float64{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}},
   764  		},
   765  		{
   766  			[][]float64{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}},
   767  			[][]float64{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}},
   768  			[][]float64{{1, math.NaN(), math.NaN()}, {math.NaN(), 1, math.NaN()}, {math.NaN(), math.NaN(), 1}},
   769  		},
   770  		{
   771  			[][]float64{{-1, 0, 0}, {0, -1, 0}, {0, 0, -1}},
   772  			[][]float64{{-1, 0, 0}, {0, -1, 0}, {0, 0, -1}},
   773  			[][]float64{{1, math.NaN(), math.NaN()}, {math.NaN(), 1, math.NaN()}, {math.NaN(), math.NaN(), 1}},
   774  		},
   775  		{
   776  			[][]float64{{1, 2, 3}, {4, 5, 6}},
   777  			[][]float64{{1, 2, 3}, {4, 5, 6}},
   778  			[][]float64{{1, 1, 1}, {1, 1, 1}},
   779  		},
   780  	} {
   781  		a := NewDense(flatten(test.a))
   782  		b := NewDense(flatten(test.b))
   783  		r := NewDense(flatten(test.r))
   784  
   785  		var temp Dense
   786  		temp.DivElem(a, b)
   787  		if !temp.same(r) {
   788  			t.Errorf("unexpected result from DivElem for test %d %v DivElem %v: got: %v want: %v",
   789  				i, test.a, test.b, unflatten(temp.mat.Rows, temp.mat.Cols, temp.mat.Data), test.r)
   790  		}
   791  
   792  		zero(temp.mat.Data)
   793  		temp.DivElem(a, b)
   794  		if !temp.same(r) {
   795  			t.Errorf("unexpected result from DivElem for test %d %v DivElem %v: got: %v want: %v",
   796  				i, test.a, test.b, unflatten(temp.mat.Rows, temp.mat.Cols, temp.mat.Data), test.r)
   797  		}
   798  
   799  		// These probably warrant a better check and failure. They should never happen in the wild though.
   800  		temp.mat.Data = nil
   801  		panicked, message := panics(func() { temp.DivElem(a, b) })
   802  		if !panicked || !strings.HasPrefix(message, "runtime error: index out of range") {
   803  			t.Error("exected runtime panic for nil data slice")
   804  		}
   805  
   806  		a.DivElem(a, b)
   807  		if !a.same(r) {
   808  			t.Errorf("unexpected result from DivElem for test %d %v DivElem %v: got: %v want: %v",
   809  				i, test.a, test.b, unflatten(a.mat.Rows, a.mat.Cols, a.mat.Data), test.r)
   810  		}
   811  	}
   812  
   813  	panicked, message := panics(func() {
   814  		m := NewDense(10, 10, nil)
   815  		a := NewDense(5, 5, nil)
   816  		m.Slice(1, 6, 1, 6).(*Dense).DivElem(a, m.Slice(2, 7, 2, 7))
   817  	})
   818  	if !panicked {
   819  		t.Error("expected panic for overlapping matrices")
   820  	}
   821  	if message != regionOverlap {
   822  		t.Errorf("unexpected panic message: got: %q want: %q", message, regionOverlap)
   823  	}
   824  
   825  	method := func(receiver, a, b Matrix) {
   826  		type ElemDiver interface {
   827  			DivElem(a, b Matrix)
   828  		}
   829  		rd := receiver.(ElemDiver)
   830  		rd.DivElem(a, b)
   831  	}
   832  	denseComparison := func(receiver, a, b *Dense) {
   833  		receiver.DivElem(a, b)
   834  	}
   835  	testTwoInput(t, "DivElem", &Dense{}, method, denseComparison, legalTypesAll, legalSizeSameRectangular, 1e-14)
   836  }
   837  
   838  func TestDenseMul(t *testing.T) {
   839  	t.Parallel()
   840  	for i, test := range []struct {
   841  		a, b, r [][]float64
   842  	}{
   843  		{
   844  			[][]float64{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
   845  			[][]float64{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
   846  			[][]float64{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
   847  		},
   848  		{
   849  			[][]float64{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}},
   850  			[][]float64{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}},
   851  			[][]float64{{3, 3, 3}, {3, 3, 3}, {3, 3, 3}},
   852  		},
   853  		{
   854  			[][]float64{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}},
   855  			[][]float64{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}},
   856  			[][]float64{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}},
   857  		},
   858  		{
   859  			[][]float64{{-1, 0, 0}, {0, -1, 0}, {0, 0, -1}},
   860  			[][]float64{{-1, 0, 0}, {0, -1, 0}, {0, 0, -1}},
   861  			[][]float64{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}},
   862  		},
   863  		{
   864  			[][]float64{{1, 2, 3}, {4, 5, 6}},
   865  			[][]float64{{1, 2}, {3, 4}, {5, 6}},
   866  			[][]float64{{22, 28}, {49, 64}},
   867  		},
   868  		{
   869  			[][]float64{{0, 1, 1}, {0, 1, 1}, {0, 1, 1}},
   870  			[][]float64{{0, 1, 1}, {0, 1, 1}, {0, 1, 1}},
   871  			[][]float64{{0, 2, 2}, {0, 2, 2}, {0, 2, 2}},
   872  		},
   873  	} {
   874  		a := NewDense(flatten(test.a))
   875  		b := NewDense(flatten(test.b))
   876  		r := NewDense(flatten(test.r))
   877  
   878  		var temp Dense
   879  		temp.Mul(a, b)
   880  		if !Equal(&temp, r) {
   881  			t.Errorf("unexpected result from Mul for test %d %v Mul %v: got: %v want: %v",
   882  				i, test.a, test.b, unflatten(temp.mat.Rows, temp.mat.Cols, temp.mat.Data), test.r)
   883  		}
   884  
   885  		zero(temp.mat.Data)
   886  		temp.Mul(a, b)
   887  		if !Equal(&temp, r) {
   888  			t.Errorf("unexpected result from Mul for test %d %v Mul %v: got: %v want: %v",
   889  				i, test.a, test.b, unflatten(temp.mat.Rows, temp.mat.Cols, temp.mat.Data), test.r)
   890  		}
   891  
   892  		// These probably warrant a better check and failure. They should never happen in the wild though.
   893  		temp.mat.Data = nil
   894  		panicked, message := panics(func() { temp.Mul(a, b) })
   895  		if !panicked || message != "blas: insufficient length of c" {
   896  			if message != "" {
   897  				t.Errorf("expected runtime panic for nil data slice: got %q", message)
   898  			} else {
   899  				t.Error("expected runtime panic for nil data slice")
   900  			}
   901  		}
   902  	}
   903  
   904  	panicked, message := panics(func() {
   905  		m := NewDense(10, 10, nil)
   906  		a := NewDense(5, 5, nil)
   907  		m.Slice(1, 6, 1, 6).(*Dense).Mul(a, m.Slice(2, 7, 2, 7))
   908  	})
   909  	if !panicked {
   910  		t.Error("expected panic for overlapping matrices")
   911  	}
   912  	if message != regionOverlap {
   913  		t.Errorf("unexpected panic message: got: %q want: %q", message, regionOverlap)
   914  	}
   915  
   916  	method := func(receiver, a, b Matrix) {
   917  		type Muler interface {
   918  			Mul(a, b Matrix)
   919  		}
   920  		rd := receiver.(Muler)
   921  		rd.Mul(a, b)
   922  	}
   923  	denseComparison := func(receiver, a, b *Dense) {
   924  		receiver.Mul(a, b)
   925  	}
   926  	legalSizeMul := func(ar, ac, br, bc int) bool {
   927  		return ac == br
   928  	}
   929  	testTwoInput(t, "Mul", &Dense{}, method, denseComparison, legalTypesAll, legalSizeMul, 1e-14)
   930  }
   931  
   932  func randDense(size int, rho float64, src rand.Source) (*Dense, error) {
   933  	if size == 0 {
   934  		return nil, ErrZeroLength
   935  	}
   936  	d := &Dense{
   937  		mat: blas64.General{
   938  			Rows: size, Cols: size, Stride: size,
   939  			Data: make([]float64, size*size),
   940  		},
   941  		capRows: size, capCols: size,
   942  	}
   943  	rnd := rand.New(src)
   944  	for i := 0; i < size; i++ {
   945  		for j := 0; j < size; j++ {
   946  			if rnd.Float64() < rho {
   947  				d.Set(i, j, rnd.NormFloat64())
   948  			}
   949  		}
   950  	}
   951  	return d, nil
   952  }
   953  
   954  func TestDenseExp(t *testing.T) {
   955  	t.Parallel()
   956  	for i, test := range []struct {
   957  		a    [][]float64
   958  		want [][]float64
   959  		mod  func(*Dense)
   960  	}{
   961  		// Expected values obtained from scipy.linalg.expm with the equivalent numpy.array.
   962  		{
   963  			a:    [][]float64{{-49, 24}, {-64, 31}},
   964  			want: [][]float64{{-0.735758758144758, 0.551819099658100}, {-1.471517599088267, 1.103638240715576}},
   965  		},
   966  		{
   967  			a:    [][]float64{{-49, 24}, {-64, 31}},
   968  			want: [][]float64{{-0.735758758144758, 0.551819099658100}, {-1.471517599088267, 1.103638240715576}},
   969  			mod: func(a *Dense) {
   970  				d := make([]float64, 100)
   971  				for i := range d {
   972  					d[i] = math.NaN()
   973  				}
   974  				*a = *NewDense(10, 10, d).Slice(1, 3, 1, 3).(*Dense)
   975  			},
   976  		},
   977  		{
   978  			a:    [][]float64{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}},
   979  			want: [][]float64{{2.71828182845905, 0, 0}, {0, 2.71828182845905, 0}, {0, 0, 2.71828182845905}},
   980  		},
   981  		{
   982  			a: [][]float64{
   983  				{-200, 100, 100, 0},
   984  				{100, -200, 0, 100},
   985  				{100, 0, -200, 100},
   986  				{0, 100, 100, -200},
   987  			},
   988  			want: [][]float64{
   989  				{0.25, 0.25, 0.25, 0.25},
   990  				{0.25, 0.25, 0.25, 0.25},
   991  				{0.25, 0.25, 0.25, 0.25},
   992  				{0.25, 0.25, 0.25, 0.25},
   993  			},
   994  		},
   995  	} {
   996  		var got Dense
   997  		if test.mod != nil {
   998  			test.mod(&got)
   999  		}
  1000  		got.Exp(NewDense(flatten(test.a)))
  1001  		want := NewDense(flatten(test.want))
  1002  		if !EqualApprox(&got, want, 1e-14) {
  1003  			t.Errorf("unexpected result for Exp test %d\ngot:\n%v\nwant:\n%v",
  1004  				i, Formatted(&got), Formatted(want))
  1005  		}
  1006  	}
  1007  }
  1008  
  1009  func TestDensePow(t *testing.T) {
  1010  	t.Parallel()
  1011  	for i, test := range []struct {
  1012  		a    [][]float64
  1013  		n    int
  1014  		mod  func(*Dense)
  1015  		want [][]float64
  1016  	}{
  1017  		{
  1018  			a:    [][]float64{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}},
  1019  			n:    0,
  1020  			want: [][]float64{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}},
  1021  		},
  1022  		{
  1023  			a:    [][]float64{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}},
  1024  			n:    0,
  1025  			want: [][]float64{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}},
  1026  			mod: func(a *Dense) {
  1027  				d := make([]float64, 100)
  1028  				for i := range d {
  1029  					d[i] = math.NaN()
  1030  				}
  1031  				*a = *NewDense(10, 10, d).Slice(1, 4, 1, 4).(*Dense)
  1032  			},
  1033  		},
  1034  		{
  1035  			a:    [][]float64{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}},
  1036  			n:    1,
  1037  			want: [][]float64{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}},
  1038  		},
  1039  		{
  1040  			a:    [][]float64{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}},
  1041  			n:    1,
  1042  			want: [][]float64{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}},
  1043  			mod: func(a *Dense) {
  1044  				d := make([]float64, 100)
  1045  				for i := range d {
  1046  					d[i] = math.NaN()
  1047  				}
  1048  				*a = *NewDense(10, 10, d).Slice(1, 4, 1, 4).(*Dense)
  1049  			},
  1050  		},
  1051  		{
  1052  			a:    [][]float64{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}},
  1053  			n:    2,
  1054  			want: [][]float64{{30, 36, 42}, {66, 81, 96}, {102, 126, 150}},
  1055  		},
  1056  		{
  1057  			a:    [][]float64{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}},
  1058  			n:    2,
  1059  			want: [][]float64{{30, 36, 42}, {66, 81, 96}, {102, 126, 150}},
  1060  			mod: func(a *Dense) {
  1061  				d := make([]float64, 100)
  1062  				for i := range d {
  1063  					d[i] = math.NaN()
  1064  				}
  1065  				*a = *NewDense(10, 10, d).Slice(1, 4, 1, 4).(*Dense)
  1066  			},
  1067  		},
  1068  		{
  1069  			a:    [][]float64{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}},
  1070  			n:    3,
  1071  			want: [][]float64{{468, 576, 684}, {1062, 1305, 1548}, {1656, 2034, 2412}},
  1072  		},
  1073  		{
  1074  			a:    [][]float64{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}},
  1075  			n:    3,
  1076  			want: [][]float64{{468, 576, 684}, {1062, 1305, 1548}, {1656, 2034, 2412}},
  1077  			mod: func(a *Dense) {
  1078  				d := make([]float64, 100)
  1079  				for i := range d {
  1080  					d[i] = math.NaN()
  1081  				}
  1082  				*a = *NewDense(10, 10, d).Slice(1, 4, 1, 4).(*Dense)
  1083  			},
  1084  		},
  1085  	} {
  1086  		var got Dense
  1087  		if test.mod != nil {
  1088  			test.mod(&got)
  1089  		}
  1090  		got.Pow(NewDense(flatten(test.a)), test.n)
  1091  		if !EqualApprox(&got, NewDense(flatten(test.want)), 1e-12) {
  1092  			t.Errorf("unexpected result for Pow test %d", i)
  1093  		}
  1094  	}
  1095  }
  1096  
  1097  func TestDenseKronecker(t *testing.T) {
  1098  	t.Parallel()
  1099  	for i, test := range []struct {
  1100  		a, b Matrix
  1101  		want *Dense
  1102  	}{
  1103  		{
  1104  			a: NewDense(1, 3, []float64{1, 2, 3}),
  1105  			b: NewDense(3, 1, []float64{1, 2, 3}),
  1106  			want: NewDense(3, 3, []float64{
  1107  				1, 2, 3,
  1108  				2, 4, 6,
  1109  				3, 6, 9,
  1110  			}),
  1111  		},
  1112  		{
  1113  			a: NewDense(3, 1, []float64{1, 2, 3}),
  1114  			b: NewDense(1, 3, []float64{1, 2, 3}),
  1115  			want: NewDense(3, 3, []float64{
  1116  				1, 2, 3,
  1117  				2, 4, 6,
  1118  				3, 6, 9,
  1119  			}),
  1120  		},
  1121  		{
  1122  			a: NewDense(1, 3, []float64{1, 2, 3}),
  1123  			b: NewDense(2, 1, []float64{1, 2}),
  1124  			want: NewDense(2, 3, []float64{
  1125  				1, 2, 3,
  1126  				2, 4, 6,
  1127  			}),
  1128  		},
  1129  		{
  1130  			a: NewDense(2, 1, []float64{1, 2}),
  1131  			b: NewDense(1, 3, []float64{1, 2, 3}),
  1132  			want: NewDense(2, 3, []float64{
  1133  				1, 2, 3,
  1134  				2, 4, 6,
  1135  			}),
  1136  		},
  1137  		{
  1138  			a: NewDense(1, 2, []float64{1, 2}),
  1139  			b: NewDense(3, 1, []float64{1, 2, 3}),
  1140  			want: NewDense(3, 2, []float64{
  1141  				1, 2,
  1142  				2, 4,
  1143  				3, 6,
  1144  			}),
  1145  		},
  1146  		{
  1147  			a: NewDense(3, 1, []float64{1, 2, 3}),
  1148  			b: NewDense(1, 2, []float64{1, 2}),
  1149  			want: NewDense(3, 2, []float64{
  1150  				1, 2,
  1151  				2, 4,
  1152  				3, 6,
  1153  			}),
  1154  		},
  1155  
  1156  		// Examples from https://en.wikipedia.org/wiki/Kronecker_product.
  1157  		{
  1158  			a: NewDense(2, 2, []float64{1, 2, 3, 4}),
  1159  			b: NewDense(2, 2, []float64{0, 5, 6, 7}),
  1160  			want: NewDense(4, 4, []float64{
  1161  				0, 5, 0, 10,
  1162  				6, 7, 12, 14,
  1163  				0, 15, 0, 20,
  1164  				18, 21, 24, 28,
  1165  			}),
  1166  		},
  1167  		{
  1168  			a: NewDense(2, 3, []float64{
  1169  				1, -4, 7,
  1170  				-2, 3, 3,
  1171  			}),
  1172  			b: NewDense(4, 4, []float64{
  1173  				8, -9, -6, 5,
  1174  				1, -3, -4, 7,
  1175  				2, 8, -8, -3,
  1176  				1, 2, -5, -1,
  1177  			}),
  1178  			want: NewDense(8, 12, []float64{
  1179  				8, -9, -6, 5, -32, 36, 24, -20, 56, -63, -42, 35,
  1180  				1, -3, -4, 7, -4, 12, 16, -28, 7, -21, -28, 49,
  1181  				2, 8, -8, -3, -8, -32, 32, 12, 14, 56, -56, -21,
  1182  				1, 2, -5, -1, -4, -8, 20, 4, 7, 14, -35, -7,
  1183  				-16, 18, 12, -10, 24, -27, -18, 15, 24, -27, -18, 15,
  1184  				-2, 6, 8, -14, 3, -9, -12, 21, 3, -9, -12, 21,
  1185  				-4, -16, 16, 6, 6, 24, -24, -9, 6, 24, -24, -9,
  1186  				-2, -4, 10, 2, 3, 6, -15, -3, 3, 6, -15, -3,
  1187  			}),
  1188  		},
  1189  	} {
  1190  		var got Dense
  1191  		got.Kronecker(test.a, test.b)
  1192  		if !Equal(&got, test.want) {
  1193  			t.Errorf("unexpected result for test %d\ngot:%#v want:%#v", i, &got, test.want)
  1194  		}
  1195  	}
  1196  }
  1197  
  1198  func TestDenseScale(t *testing.T) {
  1199  	t.Parallel()
  1200  	for _, f := range []float64{0.5, 1, 3} {
  1201  		method := func(receiver, a Matrix) {
  1202  			type Scaler interface {
  1203  				Scale(f float64, a Matrix)
  1204  			}
  1205  			rd := receiver.(Scaler)
  1206  			rd.Scale(f, a)
  1207  		}
  1208  		denseComparison := func(receiver, a *Dense) {
  1209  			receiver.Scale(f, a)
  1210  		}
  1211  		testOneInput(t, "Scale", &Dense{}, method, denseComparison, isAnyType, isAnySize, 1e-14)
  1212  	}
  1213  }
  1214  
  1215  func TestDensePowN(t *testing.T) {
  1216  	t.Parallel()
  1217  	for i, test := range []struct {
  1218  		a   [][]float64
  1219  		mod func(*Dense)
  1220  	}{
  1221  		{
  1222  			a: [][]float64{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}},
  1223  		},
  1224  		{
  1225  			a: [][]float64{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}},
  1226  			mod: func(a *Dense) {
  1227  				d := make([]float64, 100)
  1228  				for i := range d {
  1229  					d[i] = math.NaN()
  1230  				}
  1231  				*a = *NewDense(10, 10, d).Slice(1, 4, 1, 4).(*Dense)
  1232  			},
  1233  		},
  1234  	} {
  1235  		for n := 1; n <= 14; n++ {
  1236  			var got, want Dense
  1237  			if test.mod != nil {
  1238  				test.mod(&got)
  1239  			}
  1240  			got.Pow(NewDense(flatten(test.a)), n)
  1241  			want.iterativePow(NewDense(flatten(test.a)), n)
  1242  			if !Equal(&got, &want) {
  1243  				t.Errorf("unexpected result for iterative Pow test %d", i)
  1244  			}
  1245  		}
  1246  	}
  1247  }
  1248  
  1249  func (m *Dense) iterativePow(a Matrix, n int) {
  1250  	m.CloneFrom(a)
  1251  	for i := 1; i < n; i++ {
  1252  		m.Mul(m, a)
  1253  	}
  1254  }
  1255  
  1256  func TestDenseCloneT(t *testing.T) {
  1257  	t.Parallel()
  1258  	for i, test := range []struct {
  1259  		a, want [][]float64
  1260  	}{
  1261  		{
  1262  			[][]float64{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
  1263  			[][]float64{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
  1264  		},
  1265  		{
  1266  			[][]float64{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}},
  1267  			[][]float64{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}},
  1268  		},
  1269  		{
  1270  			[][]float64{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}},
  1271  			[][]float64{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}},
  1272  		},
  1273  		{
  1274  			[][]float64{{-1, 0, 0}, {0, -1, 0}, {0, 0, -1}},
  1275  			[][]float64{{-1, 0, 0}, {0, -1, 0}, {0, 0, -1}},
  1276  		},
  1277  		{
  1278  			[][]float64{{1, 2, 3}, {4, 5, 6}},
  1279  			[][]float64{{1, 4}, {2, 5}, {3, 6}},
  1280  		},
  1281  	} {
  1282  		a := NewDense(flatten(test.a))
  1283  		want := NewDense(flatten(test.want))
  1284  
  1285  		var got, gotT Dense
  1286  
  1287  		for j := 0; j < 2; j++ {
  1288  			got.CloneFrom(a.T())
  1289  			if !Equal(&got, want) {
  1290  				t.Errorf("expected transpose for test %d iteration %d: %v transpose = %v",
  1291  					i, j, test.a, test.want)
  1292  			}
  1293  			gotT.CloneFrom(got.T())
  1294  			if !Equal(&gotT, a) {
  1295  				t.Errorf("expected transpose for test %d iteration %d: %v transpose = %v",
  1296  					i, j, test.a, test.want)
  1297  			}
  1298  
  1299  			zero(got.mat.Data)
  1300  		}
  1301  	}
  1302  }
  1303  
  1304  func TestDenseCopyT(t *testing.T) {
  1305  	t.Parallel()
  1306  	for i, test := range []struct {
  1307  		a, want [][]float64
  1308  	}{
  1309  		{
  1310  			[][]float64{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
  1311  			[][]float64{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
  1312  		},
  1313  		{
  1314  			[][]float64{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}},
  1315  			[][]float64{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}},
  1316  		},
  1317  		{
  1318  			[][]float64{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}},
  1319  			[][]float64{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}},
  1320  		},
  1321  		{
  1322  			[][]float64{{-1, 0, 0}, {0, -1, 0}, {0, 0, -1}},
  1323  			[][]float64{{-1, 0, 0}, {0, -1, 0}, {0, 0, -1}},
  1324  		},
  1325  		{
  1326  			[][]float64{{1, 2, 3}, {4, 5, 6}},
  1327  			[][]float64{{1, 4}, {2, 5}, {3, 6}},
  1328  		},
  1329  	} {
  1330  		a := NewDense(flatten(test.a))
  1331  		want := NewDense(flatten(test.want))
  1332  
  1333  		ar, ac := a.Dims()
  1334  		got := NewDense(ac, ar, nil)
  1335  		rr := NewDense(ar, ac, nil)
  1336  
  1337  		for j := 0; j < 2; j++ {
  1338  			got.Copy(a.T())
  1339  			if !Equal(got, want) {
  1340  				t.Errorf("expected transpose for test %d iteration %d: %v transpose = %v",
  1341  					i, j, test.a, test.want)
  1342  			}
  1343  			rr.Copy(got.T())
  1344  			if !Equal(rr, a) {
  1345  				t.Errorf("expected transpose for test %d iteration %d: %v transpose = %v",
  1346  					i, j, test.a, test.want)
  1347  			}
  1348  
  1349  			zero(got.mat.Data)
  1350  		}
  1351  	}
  1352  }
  1353  
  1354  func TestDenseCopyDenseAlias(t *testing.T) {
  1355  	t.Parallel()
  1356  	for _, trans := range []bool{false, true} {
  1357  		for di := 0; di < 2; di++ {
  1358  			for dj := 0; dj < 2; dj++ {
  1359  				for si := 0; si < 2; si++ {
  1360  					for sj := 0; sj < 2; sj++ {
  1361  						a := NewDense(3, 3, []float64{
  1362  							1, 2, 3,
  1363  							4, 5, 6,
  1364  							7, 8, 9,
  1365  						})
  1366  						src := a.Slice(si, si+2, sj, sj+2)
  1367  						want := DenseCopyOf(src)
  1368  						got := a.Slice(di, di+2, dj, dj+2).(*Dense)
  1369  
  1370  						if trans {
  1371  							panicked, _ := panics(func() { got.Copy(src.T()) })
  1372  							if !panicked {
  1373  								t.Errorf("expected panic for transpose aliased copy with offsets dst(%d,%d) src(%d,%d):\ngot:\n%v\nwant:\n%v",
  1374  									di, dj, si, sj, Formatted(got), Formatted(want),
  1375  								)
  1376  							}
  1377  							continue
  1378  						}
  1379  
  1380  						got.Copy(src)
  1381  						if !Equal(got, want) {
  1382  							t.Errorf("unexpected aliased copy result with offsets dst(%d,%d) src(%d,%d):\ngot:\n%v\nwant:\n%v",
  1383  								di, dj, si, sj, Formatted(got), Formatted(want),
  1384  							)
  1385  						}
  1386  					}
  1387  				}
  1388  			}
  1389  		}
  1390  	}
  1391  }
  1392  
  1393  func TestDenseCopyVecDenseAlias(t *testing.T) {
  1394  	t.Parallel()
  1395  	for _, horiz := range []bool{false, true} {
  1396  		for do := 0; do < 2; do++ {
  1397  			for di := 0; di < 3; di++ {
  1398  				for si := 0; si < 3; si++ {
  1399  					a := NewDense(3, 3, []float64{
  1400  						1, 2, 3,
  1401  						4, 5, 6,
  1402  						7, 8, 9,
  1403  					})
  1404  					var src Vector
  1405  					var want *Dense
  1406  					if horiz {
  1407  						src = a.RowView(si)
  1408  						want = DenseCopyOf(a.Slice(si, si+1, 0, 2))
  1409  					} else {
  1410  						src = a.ColView(si)
  1411  						want = DenseCopyOf(a.Slice(0, 2, si, si+1))
  1412  					}
  1413  
  1414  					var got *Dense
  1415  					if horiz {
  1416  						got = a.Slice(di, di+1, do, do+2).(*Dense)
  1417  						got.Copy(src.T())
  1418  					} else {
  1419  						got = a.Slice(do, do+2, di, di+1).(*Dense)
  1420  						got.Copy(src)
  1421  					}
  1422  
  1423  					if !Equal(got, want) {
  1424  						t.Errorf("unexpected aliased copy result with offsets dst(%d) src(%d):\ngot:\n%v\nwant:\n%v",
  1425  							di, si, Formatted(got), Formatted(want),
  1426  						)
  1427  					}
  1428  				}
  1429  			}
  1430  		}
  1431  	}
  1432  }
  1433  
  1434  func identity(r, c int, v float64) float64 { return v }
  1435  
  1436  func TestDenseApply(t *testing.T) {
  1437  	t.Parallel()
  1438  	for i, test := range []struct {
  1439  		a, want [][]float64
  1440  		fn      func(r, c int, v float64) float64
  1441  	}{
  1442  		{
  1443  			[][]float64{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
  1444  			[][]float64{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
  1445  			identity,
  1446  		},
  1447  		{
  1448  			[][]float64{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}},
  1449  			[][]float64{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}},
  1450  			identity,
  1451  		},
  1452  		{
  1453  			[][]float64{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}},
  1454  			[][]float64{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}},
  1455  			identity,
  1456  		},
  1457  		{
  1458  			[][]float64{{-1, 0, 0}, {0, -1, 0}, {0, 0, -1}},
  1459  			[][]float64{{-1, 0, 0}, {0, -1, 0}, {0, 0, -1}},
  1460  			identity,
  1461  		},
  1462  		{
  1463  			[][]float64{{1, 2, 3}, {4, 5, 6}},
  1464  			[][]float64{{1, 2, 3}, {4, 5, 6}},
  1465  			identity,
  1466  		},
  1467  		{
  1468  			[][]float64{{1, 2, 3}, {4, 5, 6}},
  1469  			[][]float64{{2, 4, 6}, {8, 10, 12}},
  1470  			func(r, c int, v float64) float64 { return v * 2 },
  1471  		},
  1472  		{
  1473  			[][]float64{{1, 2, 3}, {4, 5, 6}},
  1474  			[][]float64{{0, 2, 0}, {0, 5, 0}},
  1475  			func(r, c int, v float64) float64 {
  1476  				if c == 1 {
  1477  					return v
  1478  				}
  1479  				return 0
  1480  			},
  1481  		},
  1482  		{
  1483  			[][]float64{{1, 2, 3}, {4, 5, 6}},
  1484  			[][]float64{{0, 0, 0}, {4, 5, 6}},
  1485  			func(r, c int, v float64) float64 {
  1486  				if r == 1 {
  1487  					return v
  1488  				}
  1489  				return 0
  1490  			},
  1491  		},
  1492  	} {
  1493  		a := NewDense(flatten(test.a))
  1494  		want := NewDense(flatten(test.want))
  1495  
  1496  		var got Dense
  1497  
  1498  		for j := 0; j < 2; j++ {
  1499  			got.Apply(test.fn, a)
  1500  			if !Equal(&got, want) {
  1501  				t.Errorf("unexpected result for test %d iteration %d: got: %v want: %v", i, j, got.mat.Data, want.mat.Data)
  1502  			}
  1503  		}
  1504  	}
  1505  
  1506  	for _, fn := range []func(r, c int, v float64) float64{
  1507  		identity,
  1508  		func(r, c int, v float64) float64 {
  1509  			if r < c {
  1510  				return v
  1511  			}
  1512  			return -v
  1513  		},
  1514  		func(r, c int, v float64) float64 {
  1515  			if r%2 == 0 && c%2 == 0 {
  1516  				return v
  1517  			}
  1518  			return -v
  1519  		},
  1520  		func(_, _ int, v float64) float64 { return v * v },
  1521  		func(_, _ int, v float64) float64 { return -v },
  1522  	} {
  1523  		method := func(receiver, x Matrix) {
  1524  			type Applier interface {
  1525  				Apply(func(r, c int, v float64) float64, Matrix)
  1526  			}
  1527  			rd := receiver.(Applier)
  1528  			rd.Apply(fn, x)
  1529  		}
  1530  		denseComparison := func(receiver, x *Dense) {
  1531  			receiver.Apply(fn, x)
  1532  		}
  1533  		testOneInput(t, "Apply", &Dense{}, method, denseComparison, isAnyType, isAnySize, 0)
  1534  	}
  1535  }
  1536  
  1537  func TestDenseClone(t *testing.T) {
  1538  	t.Parallel()
  1539  	for i, test := range []struct {
  1540  		a    [][]float64
  1541  		i, j int
  1542  		v    float64
  1543  	}{
  1544  		{
  1545  			[][]float64{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
  1546  			1, 1,
  1547  			1,
  1548  		},
  1549  		{
  1550  			[][]float64{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}},
  1551  			0, 0,
  1552  			0,
  1553  		},
  1554  	} {
  1555  		a := NewDense(flatten(test.a))
  1556  		b := *a
  1557  		a.CloneFrom(a)
  1558  		a.Set(test.i, test.j, test.v)
  1559  
  1560  		if Equal(&b, a) {
  1561  			t.Errorf("unexpected mirror of write to cloned matrix for test %d: %v cloned and altered = %v",
  1562  				i, a, &b)
  1563  		}
  1564  	}
  1565  }
  1566  
  1567  // TODO(kortschak) Roll this into testOneInput when it exists.
  1568  func TestDenseCopyPanic(t *testing.T) {
  1569  	t.Parallel()
  1570  	for _, a := range []*Dense{
  1571  		{},
  1572  		{mat: blas64.General{Rows: 1}},
  1573  		{mat: blas64.General{Cols: 1}},
  1574  	} {
  1575  		var rows, cols int
  1576  		m := NewDense(1, 1, nil)
  1577  		panicked, message := panics(func() { rows, cols = m.Copy(a) })
  1578  		if panicked {
  1579  			t.Errorf("unexpected panic: %v", message)
  1580  		}
  1581  		if rows != 0 {
  1582  			t.Errorf("unexpected rows: got: %d want: 0", rows)
  1583  		}
  1584  		if cols != 0 {
  1585  			t.Errorf("unexpected cols: got: %d want: 0", cols)
  1586  		}
  1587  	}
  1588  }
  1589  
  1590  func TestDenseStack(t *testing.T) {
  1591  	t.Parallel()
  1592  	for i, test := range []struct {
  1593  		a, b, e [][]float64
  1594  	}{
  1595  		{
  1596  			[][]float64{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
  1597  			[][]float64{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
  1598  			[][]float64{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
  1599  		},
  1600  		{
  1601  			[][]float64{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}},
  1602  			[][]float64{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}},
  1603  			[][]float64{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}, {1, 1, 1}, {1, 1, 1}, {1, 1, 1}},
  1604  		},
  1605  		{
  1606  			[][]float64{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}},
  1607  			[][]float64{{0, 1, 0}, {0, 0, 1}, {1, 0, 0}},
  1608  			[][]float64{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}, {0, 1, 0}, {0, 0, 1}, {1, 0, 0}},
  1609  		},
  1610  	} {
  1611  		a := NewDense(flatten(test.a))
  1612  		b := NewDense(flatten(test.b))
  1613  
  1614  		var s Dense
  1615  		s.Stack(a, b)
  1616  
  1617  		if !Equal(&s, NewDense(flatten(test.e))) {
  1618  			t.Errorf("unexpected result for Stack test %d: %v stack %v = %v", i, a, b, s)
  1619  		}
  1620  	}
  1621  
  1622  	method := func(receiver, a, b Matrix) {
  1623  		type Stacker interface {
  1624  			Stack(a, b Matrix)
  1625  		}
  1626  		rd := receiver.(Stacker)
  1627  		rd.Stack(a, b)
  1628  	}
  1629  	denseComparison := func(receiver, a, b *Dense) {
  1630  		receiver.Stack(a, b)
  1631  	}
  1632  	testTwoInput(t, "Stack", &Dense{}, method, denseComparison, legalTypesAll, legalSizeSameWidth, 0)
  1633  }
  1634  
  1635  func TestDenseAugment(t *testing.T) {
  1636  	t.Parallel()
  1637  	for i, test := range []struct {
  1638  		a, b, e [][]float64
  1639  	}{
  1640  		{
  1641  			[][]float64{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
  1642  			[][]float64{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
  1643  			[][]float64{{0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}},
  1644  		},
  1645  		{
  1646  			[][]float64{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}},
  1647  			[][]float64{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}},
  1648  			[][]float64{{1, 1, 1, 1, 1, 1}, {1, 1, 1, 1, 1, 1}, {1, 1, 1, 1, 1, 1}},
  1649  		},
  1650  		{
  1651  			[][]float64{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}},
  1652  			[][]float64{{0, 1, 0}, {0, 0, 1}, {1, 0, 0}},
  1653  			[][]float64{{1, 0, 0, 0, 1, 0}, {0, 1, 0, 0, 0, 1}, {0, 0, 1, 1, 0, 0}},
  1654  		},
  1655  	} {
  1656  		a := NewDense(flatten(test.a))
  1657  		b := NewDense(flatten(test.b))
  1658  
  1659  		var s Dense
  1660  		s.Augment(a, b)
  1661  
  1662  		if !Equal(&s, NewDense(flatten(test.e))) {
  1663  			t.Errorf("unexpected result for Augment test %d: %v augment %v = %v", i, a, b, s)
  1664  		}
  1665  	}
  1666  
  1667  	method := func(receiver, a, b Matrix) {
  1668  		type Augmenter interface {
  1669  			Augment(a, b Matrix)
  1670  		}
  1671  		rd := receiver.(Augmenter)
  1672  		rd.Augment(a, b)
  1673  	}
  1674  	denseComparison := func(receiver, a, b *Dense) {
  1675  		receiver.Augment(a, b)
  1676  	}
  1677  	testTwoInput(t, "Augment", &Dense{}, method, denseComparison, legalTypesAll, legalSizeSameHeight, 0)
  1678  }
  1679  
  1680  func TestDenseRankOne(t *testing.T) {
  1681  	t.Parallel()
  1682  	for i, test := range []struct {
  1683  		x     []float64
  1684  		y     []float64
  1685  		m     [][]float64
  1686  		alpha float64
  1687  	}{
  1688  		{
  1689  			x:     []float64{5},
  1690  			y:     []float64{10},
  1691  			m:     [][]float64{{2}},
  1692  			alpha: -3,
  1693  		},
  1694  		{
  1695  			x:     []float64{5, 6, 1},
  1696  			y:     []float64{10},
  1697  			m:     [][]float64{{2}, {-3}, {5}},
  1698  			alpha: -3,
  1699  		},
  1700  
  1701  		{
  1702  			x:     []float64{5},
  1703  			y:     []float64{10, 15, 8},
  1704  			m:     [][]float64{{2, -3, 5}},
  1705  			alpha: -3,
  1706  		},
  1707  		{
  1708  			x: []float64{1, 5},
  1709  			y: []float64{10, 15},
  1710  			m: [][]float64{
  1711  				{2, -3},
  1712  				{4, -1},
  1713  			},
  1714  			alpha: -3,
  1715  		},
  1716  		{
  1717  			x: []float64{2, 3, 9},
  1718  			y: []float64{8, 9},
  1719  			m: [][]float64{
  1720  				{2, 3},
  1721  				{4, 5},
  1722  				{6, 7},
  1723  			},
  1724  			alpha: -3,
  1725  		},
  1726  		{
  1727  			x: []float64{2, 3},
  1728  			y: []float64{8, 9, 9},
  1729  			m: [][]float64{
  1730  				{2, 3, 6},
  1731  				{4, 5, 7},
  1732  			},
  1733  			alpha: -3,
  1734  		},
  1735  	} {
  1736  		want := &Dense{}
  1737  		xm := NewDense(len(test.x), 1, test.x)
  1738  		ym := NewDense(1, len(test.y), test.y)
  1739  
  1740  		want.Mul(xm, ym)
  1741  		want.Scale(test.alpha, want)
  1742  		want.Add(want, NewDense(flatten(test.m)))
  1743  
  1744  		a := NewDense(flatten(test.m))
  1745  		m := &Dense{}
  1746  		// Check with a new matrix
  1747  		m.RankOne(a, test.alpha, NewVecDense(len(test.x), test.x), NewVecDense(len(test.y), test.y))
  1748  		if !Equal(m, want) {
  1749  			t.Errorf("unexpected result for RankOne test %d iteration 0: got: %+v want: %+v", i, m, want)
  1750  		}
  1751  		// Check with the same matrix
  1752  		a.RankOne(a, test.alpha, NewVecDense(len(test.x), test.x), NewVecDense(len(test.y), test.y))
  1753  		if !Equal(a, want) {
  1754  			t.Errorf("unexpected result for RankOne test %d iteration 1: got: %+v want: %+v", i, m, want)
  1755  		}
  1756  	}
  1757  }
  1758  
  1759  func TestDenseOuter(t *testing.T) {
  1760  	t.Parallel()
  1761  	for i, test := range []struct {
  1762  		x []float64
  1763  		y []float64
  1764  	}{
  1765  		{
  1766  			x: []float64{5},
  1767  			y: []float64{10},
  1768  		},
  1769  		{
  1770  			x: []float64{5, 6, 1},
  1771  			y: []float64{10},
  1772  		},
  1773  
  1774  		{
  1775  			x: []float64{5},
  1776  			y: []float64{10, 15, 8},
  1777  		},
  1778  		{
  1779  			x: []float64{1, 5},
  1780  			y: []float64{10, 15},
  1781  		},
  1782  		{
  1783  			x: []float64{2, 3, 9},
  1784  			y: []float64{8, 9},
  1785  		},
  1786  		{
  1787  			x: []float64{2, 3},
  1788  			y: []float64{8, 9, 9},
  1789  		},
  1790  	} {
  1791  		for _, f := range []float64{0.5, 1, 3} {
  1792  			want := &Dense{}
  1793  			xm := NewDense(len(test.x), 1, test.x)
  1794  			ym := NewDense(1, len(test.y), test.y)
  1795  
  1796  			want.Mul(xm, ym)
  1797  			want.Scale(f, want)
  1798  
  1799  			var m Dense
  1800  			for j := 0; j < 2; j++ {
  1801  				// Check with a new matrix - and then again.
  1802  				m.Outer(f, NewVecDense(len(test.x), test.x), NewVecDense(len(test.y), test.y))
  1803  				if !Equal(&m, want) {
  1804  					t.Errorf("unexpected result for Outer test %d iteration %d scale %v: got: %+v want: %+v", i, j, f, m, want)
  1805  				}
  1806  			}
  1807  		}
  1808  	}
  1809  
  1810  	for _, alpha := range []float64{0, 1, -1, 2.3, -2.3} {
  1811  		method := func(receiver, x, y Matrix) {
  1812  			type outerer interface {
  1813  				Outer(alpha float64, x, y Vector)
  1814  			}
  1815  			m := receiver.(outerer)
  1816  			m.Outer(alpha, x.(Vector), y.(Vector))
  1817  		}
  1818  		denseComparison := func(receiver, x, y *Dense) {
  1819  			receiver.Mul(x, y.T())
  1820  			receiver.Scale(alpha, receiver)
  1821  		}
  1822  		testTwoInput(t, "Outer", &Dense{}, method, denseComparison, legalTypesVectorVector, legalSizeVector, 1e-12)
  1823  	}
  1824  }
  1825  
  1826  func TestDenseInverse(t *testing.T) {
  1827  	t.Parallel()
  1828  	for i, test := range []struct {
  1829  		a    Matrix
  1830  		want Matrix // nil indicates that a is singular.
  1831  		tol  float64
  1832  	}{
  1833  		{
  1834  			a: NewDense(3, 3, []float64{
  1835  				8, 1, 6,
  1836  				3, 5, 7,
  1837  				4, 9, 2,
  1838  			}),
  1839  			want: NewDense(3, 3, []float64{
  1840  				0.147222222222222, -0.144444444444444, 0.063888888888889,
  1841  				-0.061111111111111, 0.022222222222222, 0.105555555555556,
  1842  				-0.019444444444444, 0.188888888888889, -0.102777777777778,
  1843  			}),
  1844  			tol: 1e-14,
  1845  		},
  1846  		{
  1847  			a: NewDense(3, 3, []float64{
  1848  				8, 1, 6,
  1849  				3, 5, 7,
  1850  				4, 9, 2,
  1851  			}).T(),
  1852  			want: NewDense(3, 3, []float64{
  1853  				0.147222222222222, -0.144444444444444, 0.063888888888889,
  1854  				-0.061111111111111, 0.022222222222222, 0.105555555555556,
  1855  				-0.019444444444444, 0.188888888888889, -0.102777777777778,
  1856  			}).T(),
  1857  			tol: 1e-14,
  1858  		},
  1859  
  1860  		// This case does not fail, but we do not guarantee that. The success
  1861  		// is because the receiver and the input are aligned in the call to
  1862  		// inverse. If there was a misalignment, the result would likely be
  1863  		// incorrect and no shadowing panic would occur.
  1864  		{
  1865  			a: asBasicMatrix(NewDense(3, 3, []float64{
  1866  				8, 1, 6,
  1867  				3, 5, 7,
  1868  				4, 9, 2,
  1869  			})),
  1870  			want: NewDense(3, 3, []float64{
  1871  				0.147222222222222, -0.144444444444444, 0.063888888888889,
  1872  				-0.061111111111111, 0.022222222222222, 0.105555555555556,
  1873  				-0.019444444444444, 0.188888888888889, -0.102777777777778,
  1874  			}),
  1875  			tol: 1e-14,
  1876  		},
  1877  
  1878  		// The following case fails as it does not follow the shadowing rules.
  1879  		// Specifically, the test extracts the underlying *Dense, and uses
  1880  		// it as a receiver with the basicMatrix as input. The basicMatrix type
  1881  		// allows shadowing of the input data without providing the Raw method
  1882  		// required for detection of shadowing.
  1883  		//
  1884  		// We specifically state we do not check this case.
  1885  		//
  1886  		// {
  1887  		// 	a: asBasicMatrix(NewDense(3, 3, []float64{
  1888  		// 		8, 1, 6,
  1889  		// 		3, 5, 7,
  1890  		// 		4, 9, 2,
  1891  		// 	})).T(),
  1892  		// 	want: NewDense(3, 3, []float64{
  1893  		// 		0.147222222222222, -0.144444444444444, 0.063888888888889,
  1894  		// 		-0.061111111111111, 0.022222222222222, 0.105555555555556,
  1895  		// 		-0.019444444444444, 0.188888888888889, -0.102777777777778,
  1896  		// 	}).T(),
  1897  		// 	tol: 1e-14,
  1898  		// },
  1899  
  1900  		{
  1901  			a: NewDense(4, 4, []float64{
  1902  				5, 2, 8, 7,
  1903  				4, 5, 8, 2,
  1904  				8, 5, 3, 2,
  1905  				8, 7, 7, 5,
  1906  			}),
  1907  			want: NewDense(4, 4, []float64{
  1908  				0.100548446069470, 0.021937842778793, 0.334552102376599, -0.283363802559415,
  1909  				-0.226691042047532, -0.067641681901280, -0.281535648994515, 0.457038391224863,
  1910  				0.080438756855576, 0.217550274223035, 0.067641681901280, -0.226691042047532,
  1911  				0.043875685557587, -0.244972577696527, -0.235831809872029, 0.330895795246801,
  1912  			}),
  1913  			tol: 1e-14,
  1914  		},
  1915  
  1916  		// Tests with singular matrix.
  1917  		{
  1918  			a: NewDense(1, 1, []float64{
  1919  				0,
  1920  			}),
  1921  		},
  1922  		{
  1923  			a: NewDense(2, 2, []float64{
  1924  				0, 0,
  1925  				0, 0,
  1926  			}),
  1927  		},
  1928  		{
  1929  			a: NewDense(2, 2, []float64{
  1930  				0, 0,
  1931  				0, 1,
  1932  			}),
  1933  		},
  1934  		{
  1935  			a: NewDense(3, 3, []float64{
  1936  				0, 0, 0,
  1937  				0, 0, 0,
  1938  				0, 0, 0,
  1939  			}),
  1940  		},
  1941  		{
  1942  			a: NewDense(4, 4, []float64{
  1943  				0, 0, 0, 0,
  1944  				0, 0, 0, 0,
  1945  				0, 0, 0, 0,
  1946  				0, 0, 0, 0,
  1947  			}),
  1948  		},
  1949  		{
  1950  			a: NewDense(4, 4, []float64{
  1951  				0, 0, 0, 0,
  1952  				0, 0, 0, 0,
  1953  				0, 0, 20, 20,
  1954  				0, 0, 20, 20,
  1955  			}),
  1956  		},
  1957  		{
  1958  			a: NewDense(4, 4, []float64{
  1959  				0, 1, 0, 0,
  1960  				0, 0, 1, 0,
  1961  				0, 0, 0, 1,
  1962  				0, 0, 0, 0,
  1963  			}),
  1964  		},
  1965  		{
  1966  			a: NewDense(4, 4, []float64{
  1967  				1, 1, 1, 1,
  1968  				1, 1, 1, 1,
  1969  				1, 1, 1, 1,
  1970  				1, 1, 1, 1,
  1971  			}),
  1972  		},
  1973  		{
  1974  			a: NewDense(5, 5, []float64{
  1975  				0, 1, 0, 0, 0,
  1976  				4, 0, 2, 0, 0,
  1977  				0, 3, 0, 3, 0,
  1978  				0, 0, 2, 0, 4,
  1979  				0, 0, 0, 1, 0,
  1980  			}),
  1981  		},
  1982  		{
  1983  			a: NewDense(5, 5, []float64{
  1984  				4, -1, -1, -1, -1,
  1985  				-1, 4, -1, -1, -1,
  1986  				-1, -1, 4, -1, -1,
  1987  				-1, -1, -1, 4, -1,
  1988  				-1, -1, -1, -1, 4,
  1989  			}),
  1990  		},
  1991  		{
  1992  			a: NewDense(5, 5, []float64{
  1993  				2, -1, 0, 0, -1,
  1994  				-1, 2, -1, 0, 0,
  1995  				0, -1, 2, -1, 0,
  1996  				0, 0, -1, 2, -1,
  1997  				-1, 0, 0, -1, 2,
  1998  			}),
  1999  		},
  2000  		{
  2001  			a: NewDense(5, 5, []float64{
  2002  				1, 2, 3, 5, 8,
  2003  				2, 3, 5, 8, 13,
  2004  				3, 5, 8, 13, 21,
  2005  				5, 8, 13, 21, 34,
  2006  				8, 13, 21, 34, 55,
  2007  			}),
  2008  		},
  2009  		{
  2010  			a: NewDense(8, 8, []float64{
  2011  				611, 196, -192, 407, -8, -52, -49, 29,
  2012  				196, 899, 113, -192, -71, -43, -8, -44,
  2013  				-192, 113, 899, 196, 61, 49, 8, 52,
  2014  				407, -192, 196, 611, 8, 44, 59, -23,
  2015  				-8, -71, 61, 8, 411, -599, 208, 208,
  2016  				-52, -43, 49, 44, -599, 411, 208, 208,
  2017  				-49, -8, 8, 59, 208, 208, 99, -911,
  2018  				29, -44, 52, -23, 208, 208, -911, 99,
  2019  			}),
  2020  		},
  2021  	} {
  2022  		var got Dense
  2023  		err := got.Inverse(test.a)
  2024  		if test.want == nil {
  2025  			if err == nil {
  2026  				t.Errorf("Case %d: expected error for singular matrix", i)
  2027  			}
  2028  			continue
  2029  		}
  2030  		if err != nil {
  2031  			t.Errorf("Case %d: unexpected error: %v", i, err)
  2032  			continue
  2033  		}
  2034  		if !equalApprox(&got, test.want, test.tol, false) {
  2035  			t.Errorf("Case %d, inverse mismatch.", i)
  2036  		}
  2037  		var m Dense
  2038  		m.Mul(&got, test.a)
  2039  		r, _ := test.a.Dims()
  2040  		d := make([]float64, r*r)
  2041  		for i := 0; i < r*r; i += r + 1 {
  2042  			d[i] = 1
  2043  		}
  2044  		eye := NewDense(r, r, d)
  2045  		if !equalApprox(eye, &m, 1e-14, false) {
  2046  			t.Errorf("Case %d, A^-1 * A != I", i)
  2047  		}
  2048  
  2049  		var tmp Dense
  2050  		tmp.CloneFrom(test.a)
  2051  		aU, transposed := untranspose(test.a)
  2052  		if transposed {
  2053  			switch aU := aU.(type) {
  2054  			case *Dense:
  2055  				err = aU.Inverse(test.a)
  2056  			case *basicMatrix:
  2057  				err = (*Dense)(aU).Inverse(test.a)
  2058  			default:
  2059  				continue
  2060  			}
  2061  			m.Mul(aU, &tmp)
  2062  		} else {
  2063  			switch a := test.a.(type) {
  2064  			case *Dense:
  2065  				err = a.Inverse(test.a)
  2066  				m.Mul(a, &tmp)
  2067  			case *basicMatrix:
  2068  				err = (*Dense)(a).Inverse(test.a)
  2069  				m.Mul(a, &tmp)
  2070  			default:
  2071  				continue
  2072  			}
  2073  		}
  2074  		if err != nil {
  2075  			t.Errorf("Error computing inverse: %v", err)
  2076  		}
  2077  		if !equalApprox(eye, &m, 1e-14, false) {
  2078  			t.Errorf("Case %d, A^-1 * A != I", i)
  2079  			fmt.Println(Formatted(&m))
  2080  		}
  2081  	}
  2082  
  2083  	// Randomized tests
  2084  	const tol = 1e-16
  2085  	rnd := rand.New(rand.NewSource(1))
  2086  	for _, recvSameAsA := range []bool{false, true} {
  2087  		for _, trans := range []bool{false, true} {
  2088  			if trans && recvSameAsA {
  2089  				// Transposed argument cannot be a receiver.
  2090  				continue
  2091  			}
  2092  			for _, n := range []int{1, 2, 3, 5, 10, 50, 100} {
  2093  				name := fmt.Sprintf("n=%d,recvSameAsA=%v,trans=%v", n, recvSameAsA, trans)
  2094  
  2095  				// Generate the contents of a random dense matrix.
  2096  				data := make([]float64, n*n)
  2097  				for i := range data {
  2098  					data[i] = rnd.NormFloat64()
  2099  				}
  2100  
  2101  				var a Matrix
  2102  				var aInv Dense
  2103  				if recvSameAsA {
  2104  					aInv = *NewDense(n, n, data)
  2105  					a = &aInv
  2106  				} else {
  2107  					if trans {
  2108  						a = NewDense(n, n, data).T()
  2109  					} else {
  2110  						a = asBasicMatrix(NewDense(n, n, data))
  2111  					}
  2112  
  2113  				}
  2114  				var aOrig Dense
  2115  				aOrig.CloneFrom(a)
  2116  
  2117  				err := aInv.Inverse(a)
  2118  				if err != nil {
  2119  					t.Errorf("%v: unexpected failure of Inverse, %v", name, err)
  2120  					continue
  2121  				}
  2122  
  2123  				// Compute the residual |I - A^{-1} * A| / (N * |A| * |A^{-1}).
  2124  				var aaInv Dense
  2125  				aaInv.Mul(&aInv, &aOrig)
  2126  				for i := 0; i < n; i++ {
  2127  					aaInv.Set(i, i, 1-aaInv.At(i, i))
  2128  				}
  2129  				resid := Norm(&aaInv, 1) / (float64(n) * Norm(&aOrig, 1) * Norm(&aInv, 1))
  2130  				if resid > tol {
  2131  					t.Errorf("%v: A*A^{-1} is not identity, resid=%v,want<=%v", name, resid, tol)
  2132  				}
  2133  			}
  2134  		}
  2135  	}
  2136  }
  2137  
  2138  var (
  2139  	wd *Dense
  2140  )
  2141  
  2142  func BenchmarkMulDense100Half(b *testing.B)        { denseMulBench(b, 100, 0.5) }
  2143  func BenchmarkMulDense100Tenth(b *testing.B)       { denseMulBench(b, 100, 0.1) }
  2144  func BenchmarkMulDense1000Half(b *testing.B)       { denseMulBench(b, 1000, 0.5) }
  2145  func BenchmarkMulDense1000Tenth(b *testing.B)      { denseMulBench(b, 1000, 0.1) }
  2146  func BenchmarkMulDense1000Hundredth(b *testing.B)  { denseMulBench(b, 1000, 0.01) }
  2147  func BenchmarkMulDense1000Thousandth(b *testing.B) { denseMulBench(b, 1000, 0.001) }
  2148  func denseMulBench(b *testing.B, size int, rho float64) {
  2149  	src := rand.NewSource(1)
  2150  	b.StopTimer()
  2151  	a, _ := randDense(size, rho, src)
  2152  	d, _ := randDense(size, rho, src)
  2153  	b.StartTimer()
  2154  	for i := 0; i < b.N; i++ {
  2155  		var n Dense
  2156  		n.Mul(a, d)
  2157  		wd = &n
  2158  	}
  2159  }
  2160  
  2161  func BenchmarkPreMulDense100Half(b *testing.B)        { densePreMulBench(b, 100, 0.5) }
  2162  func BenchmarkPreMulDense100Tenth(b *testing.B)       { densePreMulBench(b, 100, 0.1) }
  2163  func BenchmarkPreMulDense1000Half(b *testing.B)       { densePreMulBench(b, 1000, 0.5) }
  2164  func BenchmarkPreMulDense1000Tenth(b *testing.B)      { densePreMulBench(b, 1000, 0.1) }
  2165  func BenchmarkPreMulDense1000Hundredth(b *testing.B)  { densePreMulBench(b, 1000, 0.01) }
  2166  func BenchmarkPreMulDense1000Thousandth(b *testing.B) { densePreMulBench(b, 1000, 0.001) }
  2167  func densePreMulBench(b *testing.B, size int, rho float64) {
  2168  	src := rand.NewSource(1)
  2169  	b.StopTimer()
  2170  	a, _ := randDense(size, rho, src)
  2171  	d, _ := randDense(size, rho, src)
  2172  	wd = NewDense(size, size, nil)
  2173  	b.StartTimer()
  2174  	for i := 0; i < b.N; i++ {
  2175  		wd.Mul(a, d)
  2176  	}
  2177  }
  2178  
  2179  func BenchmarkDenseRow10(b *testing.B)   { rowDenseBench(b, 10) }
  2180  func BenchmarkDenseRow100(b *testing.B)  { rowDenseBench(b, 100) }
  2181  func BenchmarkDenseRow1000(b *testing.B) { rowDenseBench(b, 1000) }
  2182  
  2183  func rowDenseBench(b *testing.B, size int) {
  2184  	src := rand.NewSource(1)
  2185  	a, _ := randDense(size, 1, src)
  2186  	_, c := a.Dims()
  2187  	dst := make([]float64, c)
  2188  
  2189  	b.ResetTimer()
  2190  	for i := 0; i < b.N; i++ {
  2191  		Row(dst, 0, a)
  2192  	}
  2193  }
  2194  
  2195  func BenchmarkDenseExp10(b *testing.B)   { expDenseBench(b, 10) }
  2196  func BenchmarkDenseExp100(b *testing.B)  { expDenseBench(b, 100) }
  2197  func BenchmarkDenseExp1000(b *testing.B) { expDenseBench(b, 1000) }
  2198  
  2199  func expDenseBench(b *testing.B, size int) {
  2200  	src := rand.NewSource(1)
  2201  	a, _ := randDense(size, 1, src)
  2202  
  2203  	b.ResetTimer()
  2204  	var m Dense
  2205  	for i := 0; i < b.N; i++ {
  2206  		m.Exp(a)
  2207  	}
  2208  }
  2209  
  2210  func BenchmarkDensePow10_3(b *testing.B)   { powDenseBench(b, 10, 3) }
  2211  func BenchmarkDensePow100_3(b *testing.B)  { powDenseBench(b, 100, 3) }
  2212  func BenchmarkDensePow1000_3(b *testing.B) { powDenseBench(b, 1000, 3) }
  2213  func BenchmarkDensePow10_4(b *testing.B)   { powDenseBench(b, 10, 4) }
  2214  func BenchmarkDensePow100_4(b *testing.B)  { powDenseBench(b, 100, 4) }
  2215  func BenchmarkDensePow1000_4(b *testing.B) { powDenseBench(b, 1000, 4) }
  2216  func BenchmarkDensePow10_5(b *testing.B)   { powDenseBench(b, 10, 5) }
  2217  func BenchmarkDensePow100_5(b *testing.B)  { powDenseBench(b, 100, 5) }
  2218  func BenchmarkDensePow1000_5(b *testing.B) { powDenseBench(b, 1000, 5) }
  2219  func BenchmarkDensePow10_6(b *testing.B)   { powDenseBench(b, 10, 6) }
  2220  func BenchmarkDensePow100_6(b *testing.B)  { powDenseBench(b, 100, 6) }
  2221  func BenchmarkDensePow1000_6(b *testing.B) { powDenseBench(b, 1000, 6) }
  2222  func BenchmarkDensePow10_7(b *testing.B)   { powDenseBench(b, 10, 7) }
  2223  func BenchmarkDensePow100_7(b *testing.B)  { powDenseBench(b, 100, 7) }
  2224  func BenchmarkDensePow1000_7(b *testing.B) { powDenseBench(b, 1000, 7) }
  2225  func BenchmarkDensePow10_8(b *testing.B)   { powDenseBench(b, 10, 8) }
  2226  func BenchmarkDensePow100_8(b *testing.B)  { powDenseBench(b, 100, 8) }
  2227  func BenchmarkDensePow1000_8(b *testing.B) { powDenseBench(b, 1000, 8) }
  2228  func BenchmarkDensePow10_9(b *testing.B)   { powDenseBench(b, 10, 9) }
  2229  func BenchmarkDensePow100_9(b *testing.B)  { powDenseBench(b, 100, 9) }
  2230  func BenchmarkDensePow1000_9(b *testing.B) { powDenseBench(b, 1000, 9) }
  2231  
  2232  func powDenseBench(b *testing.B, size, n int) {
  2233  	src := rand.NewSource(1)
  2234  	a, _ := randDense(size, 1, src)
  2235  
  2236  	b.ResetTimer()
  2237  	var m Dense
  2238  	for i := 0; i < b.N; i++ {
  2239  		m.Pow(a, n)
  2240  	}
  2241  }
  2242  
  2243  func BenchmarkDenseMulTransDense100Half(b *testing.B)        { denseMulTransBench(b, 100, 0.5) }
  2244  func BenchmarkDenseMulTransDense100Tenth(b *testing.B)       { denseMulTransBench(b, 100, 0.1) }
  2245  func BenchmarkDenseMulTransDense1000Half(b *testing.B)       { denseMulTransBench(b, 1000, 0.5) }
  2246  func BenchmarkDenseMulTransDense1000Tenth(b *testing.B)      { denseMulTransBench(b, 1000, 0.1) }
  2247  func BenchmarkDenseMulTransDense1000Hundredth(b *testing.B)  { denseMulTransBench(b, 1000, 0.01) }
  2248  func BenchmarkDenseMulTransDense1000Thousandth(b *testing.B) { denseMulTransBench(b, 1000, 0.001) }
  2249  func denseMulTransBench(b *testing.B, size int, rho float64) {
  2250  	src := rand.NewSource(1)
  2251  	b.StopTimer()
  2252  	a, _ := randDense(size, rho, src)
  2253  	d, _ := randDense(size, rho, src)
  2254  	b.StartTimer()
  2255  	for i := 0; i < b.N; i++ {
  2256  		var n Dense
  2257  		n.Mul(a, d.T())
  2258  		wd = &n
  2259  	}
  2260  }
  2261  
  2262  func BenchmarkDenseMulTransDenseSym100Half(b *testing.B)       { denseMulTransSymBench(b, 100, 0.5) }
  2263  func BenchmarkDenseMulTransDenseSym100Tenth(b *testing.B)      { denseMulTransSymBench(b, 100, 0.1) }
  2264  func BenchmarkDenseMulTransDenseSym1000Half(b *testing.B)      { denseMulTransSymBench(b, 1000, 0.5) }
  2265  func BenchmarkDenseMulTransDenseSym1000Tenth(b *testing.B)     { denseMulTransSymBench(b, 1000, 0.1) }
  2266  func BenchmarkDenseMulTransDenseSym1000Hundredth(b *testing.B) { denseMulTransSymBench(b, 1000, 0.01) }
  2267  func BenchmarkDenseMulTransDenseSym1000Thousandth(b *testing.B) {
  2268  	denseMulTransSymBench(b, 1000, 0.001)
  2269  }
  2270  func denseMulTransSymBench(b *testing.B, size int, rho float64) {
  2271  	src := rand.NewSource(1)
  2272  	b.StopTimer()
  2273  	a, _ := randDense(size, rho, src)
  2274  	b.StartTimer()
  2275  	for i := 0; i < b.N; i++ {
  2276  		var n Dense
  2277  		n.Mul(a, a.T())
  2278  		wd = &n
  2279  	}
  2280  }
  2281  
  2282  func BenchmarkDenseSum1000(b *testing.B) { denseSumBench(b, 1000) }
  2283  
  2284  var denseSumForBench float64
  2285  
  2286  func denseSumBench(b *testing.B, size int) {
  2287  	src := rand.NewSource(1)
  2288  	a, _ := randDense(size, 1.0, src)
  2289  	b.ResetTimer()
  2290  	for i := 0; i < b.N; i++ {
  2291  		denseSumForBench = Sum(a)
  2292  	}
  2293  }