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