mat: don't use global rand state

This commit is contained in:
Dan Kortschak
2020-03-17 21:02:32 +10:30
parent 3efb0d11ee
commit 7b6a63e4e7
15 changed files with 170 additions and 118 deletions

View File

@@ -331,10 +331,11 @@ func TestCloneCholesky(t *testing.T) {
func TestCholeskyInverseTo(t *testing.T) { func TestCholeskyInverseTo(t *testing.T) {
t.Parallel() t.Parallel()
rnd := rand.New(rand.NewSource(1))
for _, n := range []int{1, 3, 5, 9} { for _, n := range []int{1, 3, 5, 9} {
data := make([]float64, n*n) data := make([]float64, n*n)
for i := range data { for i := range data {
data[i] = rand.NormFloat64() data[i] = rnd.NormFloat64()
} }
var s SymDense var s SymDense
s.SymOuterK(1, NewDense(n, n, data)) s.SymOuterK(1, NewDense(n, n, data))
@@ -363,13 +364,13 @@ func TestCholeskyInverseTo(t *testing.T) {
func TestCholeskySymRankOne(t *testing.T) { func TestCholeskySymRankOne(t *testing.T) {
t.Parallel() t.Parallel()
rand.Seed(1) rnd := rand.New(rand.NewSource(1))
for _, n := range []int{1, 2, 3, 4, 5, 7, 10, 20, 50, 100} { for _, n := range []int{1, 2, 3, 4, 5, 7, 10, 20, 50, 100} {
for k := 0; k < 50; k++ { for k := 0; k < 50; k++ {
// Construct a random positive definite matrix. // Construct a random positive definite matrix.
data := make([]float64, n*n) data := make([]float64, n*n)
for i := range data { for i := range data {
data[i] = rand.NormFloat64() data[i] = rnd.NormFloat64()
} }
var a SymDense var a SymDense
a.SymOuterK(1, NewDense(n, n, data)) a.SymOuterK(1, NewDense(n, n, data))
@@ -377,10 +378,10 @@ func TestCholeskySymRankOne(t *testing.T) {
// Construct random data for updating. // Construct random data for updating.
xdata := make([]float64, n) xdata := make([]float64, n)
for i := range xdata { for i := range xdata {
xdata[i] = rand.NormFloat64() xdata[i] = rnd.NormFloat64()
} }
x := NewVecDense(n, xdata) x := NewVecDense(n, xdata)
alpha := rand.NormFloat64() alpha := rnd.NormFloat64()
// Compute the updated matrix directly. If alpha > 0, there are no // Compute the updated matrix directly. If alpha > 0, there are no
// issues. If alpha < 0, it could be that the final matrix is not // issues. If alpha < 0, it could be that the final matrix is not

View File

@@ -937,7 +937,7 @@ func TestDenseMul(t *testing.T) {
testTwoInput(t, "Mul", &Dense{}, method, denseComparison, legalTypesAll, legalSizeMul, 1e-14) testTwoInput(t, "Mul", &Dense{}, method, denseComparison, legalTypesAll, legalSizeMul, 1e-14)
} }
func randDense(size int, rho float64, rnd func() float64) (*Dense, error) { func randDense(size int, rho float64, src rand.Source) (*Dense, error) {
if size == 0 { if size == 0 {
return nil, ErrZeroLength return nil, ErrZeroLength
} }
@@ -948,10 +948,11 @@ func randDense(size int, rho float64, rnd func() float64) (*Dense, error) {
}, },
capRows: size, capCols: size, capRows: size, capCols: size,
} }
rnd := rand.New(src)
for i := 0; i < size; i++ { for i := 0; i < size; i++ {
for j := 0; j < size; j++ { for j := 0; j < size; j++ {
if rand.Float64() < rho { if rnd.Float64() < rho {
d.Set(i, j, rnd()) d.Set(i, j, rnd.NormFloat64())
} }
} }
} }
@@ -2099,9 +2100,10 @@ func BenchmarkMulDense1000Tenth(b *testing.B) { denseMulBench(b, 1000, 0.1)
func BenchmarkMulDense1000Hundredth(b *testing.B) { denseMulBench(b, 1000, 0.01) } func BenchmarkMulDense1000Hundredth(b *testing.B) { denseMulBench(b, 1000, 0.01) }
func BenchmarkMulDense1000Thousandth(b *testing.B) { denseMulBench(b, 1000, 0.001) } func BenchmarkMulDense1000Thousandth(b *testing.B) { denseMulBench(b, 1000, 0.001) }
func denseMulBench(b *testing.B, size int, rho float64) { func denseMulBench(b *testing.B, size int, rho float64) {
src := rand.NewSource(1)
b.StopTimer() b.StopTimer()
a, _ := randDense(size, rho, rand.NormFloat64) a, _ := randDense(size, rho, src)
d, _ := randDense(size, rho, rand.NormFloat64) d, _ := randDense(size, rho, src)
b.StartTimer() b.StartTimer()
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
var n Dense var n Dense
@@ -2117,9 +2119,10 @@ func BenchmarkPreMulDense1000Tenth(b *testing.B) { densePreMulBench(b, 1000
func BenchmarkPreMulDense1000Hundredth(b *testing.B) { densePreMulBench(b, 1000, 0.01) } func BenchmarkPreMulDense1000Hundredth(b *testing.B) { densePreMulBench(b, 1000, 0.01) }
func BenchmarkPreMulDense1000Thousandth(b *testing.B) { densePreMulBench(b, 1000, 0.001) } func BenchmarkPreMulDense1000Thousandth(b *testing.B) { densePreMulBench(b, 1000, 0.001) }
func densePreMulBench(b *testing.B, size int, rho float64) { func densePreMulBench(b *testing.B, size int, rho float64) {
src := rand.NewSource(1)
b.StopTimer() b.StopTimer()
a, _ := randDense(size, rho, rand.NormFloat64) a, _ := randDense(size, rho, src)
d, _ := randDense(size, rho, rand.NormFloat64) d, _ := randDense(size, rho, src)
wd = NewDense(size, size, nil) wd = NewDense(size, size, nil)
b.StartTimer() b.StartTimer()
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
@@ -2132,7 +2135,8 @@ func BenchmarkDenseRow100(b *testing.B) { rowDenseBench(b, 100) }
func BenchmarkDenseRow1000(b *testing.B) { rowDenseBench(b, 1000) } func BenchmarkDenseRow1000(b *testing.B) { rowDenseBench(b, 1000) }
func rowDenseBench(b *testing.B, size int) { func rowDenseBench(b *testing.B, size int) {
a, _ := randDense(size, 1, rand.NormFloat64) src := rand.NewSource(1)
a, _ := randDense(size, 1, src)
_, c := a.Dims() _, c := a.Dims()
dst := make([]float64, c) dst := make([]float64, c)
@@ -2147,7 +2151,8 @@ func BenchmarkDenseExp100(b *testing.B) { expDenseBench(b, 100) }
func BenchmarkDenseExp1000(b *testing.B) { expDenseBench(b, 1000) } func BenchmarkDenseExp1000(b *testing.B) { expDenseBench(b, 1000) }
func expDenseBench(b *testing.B, size int) { func expDenseBench(b *testing.B, size int) {
a, _ := randDense(size, 1, rand.NormFloat64) src := rand.NewSource(1)
a, _ := randDense(size, 1, src)
b.ResetTimer() b.ResetTimer()
var m Dense var m Dense
@@ -2179,7 +2184,8 @@ func BenchmarkDensePow100_9(b *testing.B) { powDenseBench(b, 100, 9) }
func BenchmarkDensePow1000_9(b *testing.B) { powDenseBench(b, 1000, 9) } func BenchmarkDensePow1000_9(b *testing.B) { powDenseBench(b, 1000, 9) }
func powDenseBench(b *testing.B, size, n int) { func powDenseBench(b *testing.B, size, n int) {
a, _ := randDense(size, 1, rand.NormFloat64) src := rand.NewSource(1)
a, _ := randDense(size, 1, src)
b.ResetTimer() b.ResetTimer()
var m Dense var m Dense
@@ -2195,9 +2201,10 @@ func BenchmarkDenseMulTransDense1000Tenth(b *testing.B) { denseMulTransBenc
func BenchmarkDenseMulTransDense1000Hundredth(b *testing.B) { denseMulTransBench(b, 1000, 0.01) } func BenchmarkDenseMulTransDense1000Hundredth(b *testing.B) { denseMulTransBench(b, 1000, 0.01) }
func BenchmarkDenseMulTransDense1000Thousandth(b *testing.B) { denseMulTransBench(b, 1000, 0.001) } func BenchmarkDenseMulTransDense1000Thousandth(b *testing.B) { denseMulTransBench(b, 1000, 0.001) }
func denseMulTransBench(b *testing.B, size int, rho float64) { func denseMulTransBench(b *testing.B, size int, rho float64) {
src := rand.NewSource(1)
b.StopTimer() b.StopTimer()
a, _ := randDense(size, rho, rand.NormFloat64) a, _ := randDense(size, rho, src)
d, _ := randDense(size, rho, rand.NormFloat64) d, _ := randDense(size, rho, src)
b.StartTimer() b.StartTimer()
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
var n Dense var n Dense
@@ -2215,8 +2222,9 @@ func BenchmarkDenseMulTransDenseSym1000Thousandth(b *testing.B) {
denseMulTransSymBench(b, 1000, 0.001) denseMulTransSymBench(b, 1000, 0.001)
} }
func denseMulTransSymBench(b *testing.B, size int, rho float64) { func denseMulTransSymBench(b *testing.B, size int, rho float64) {
src := rand.NewSource(1)
b.StopTimer() b.StopTimer()
a, _ := randDense(size, rho, rand.NormFloat64) a, _ := randDense(size, rho, src)
b.StartTimer() b.StartTimer()
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
var n Dense var n Dense
@@ -2230,7 +2238,8 @@ func BenchmarkDenseSum1000(b *testing.B) { denseSumBench(b, 1000) }
var denseSumForBench float64 var denseSumForBench float64
func denseSumBench(b *testing.B, size int) { func denseSumBench(b *testing.B, size int) {
a, _ := randDense(size, 1.0, rand.NormFloat64) src := rand.NewSource(1)
a, _ := randDense(size, 1.0, src)
b.ResetTimer() b.ResetTimer()
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
denseSumForBench = Sum(a) denseSumForBench = Sum(a)

View File

@@ -8,6 +8,8 @@ import (
"math" "math"
"testing" "testing"
"golang.org/x/exp/rand"
"gonum.org/v1/gonum/blas/blas64" "gonum.org/v1/gonum/blas/blas64"
"gonum.org/v1/gonum/blas/testblas" "gonum.org/v1/gonum/blas/testblas"
) )
@@ -153,12 +155,13 @@ func makeVecDenseInc(inc int, f []float64) *VecDense {
} }
func benchmarkInner(b *testing.B, m, n int) { func benchmarkInner(b *testing.B, m, n int) {
src := rand.NewSource(1)
x := NewVecDense(m, nil) x := NewVecDense(m, nil)
randomSlice(x.mat.Data) randomSlice(x.mat.Data, src)
y := NewVecDense(n, nil) y := NewVecDense(n, nil)
randomSlice(y.mat.Data) randomSlice(y.mat.Data, src)
data := make([]float64, m*n) data := make([]float64, m*n)
randomSlice(data) randomSlice(data, src)
mat := &Dense{mat: blas64.General{Rows: m, Cols: n, Stride: n, Data: data}, capRows: m, capCols: n} mat := &Dense{mat: blas64.General{Rows: m, Cols: n, Stride: n, Data: data}, capRows: m, capCols: n}
b.ResetTimer() b.ResetTimer()
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {

View File

@@ -342,13 +342,14 @@ func retranspose(a, m Matrix) Matrix {
} }
// makeRandOf returns a new randomly filled m×n matrix of the underlying matrix type. // makeRandOf returns a new randomly filled m×n matrix of the underlying matrix type.
func makeRandOf(a Matrix, m, n int) Matrix { func makeRandOf(a Matrix, m, n int, src rand.Source) Matrix {
rnd := rand.New(src)
var rMatrix Matrix var rMatrix Matrix
switch t := a.(type) { switch t := a.(type) {
default: default:
panic("unknown type for make rand of") panic("unknown type for make rand of")
case Untransposer: case Untransposer:
rMatrix = retranspose(a, makeRandOf(t.Untranspose(), n, m)) rMatrix = retranspose(a, makeRandOf(t.Untranspose(), n, m, src))
case *Dense, *basicMatrix: case *Dense, *basicMatrix:
var mat = &Dense{} var mat = &Dense{}
if m != 0 && n != 0 { if m != 0 && n != 0 {
@@ -356,7 +357,7 @@ func makeRandOf(a Matrix, m, n int) Matrix {
} }
for i := 0; i < m; i++ { for i := 0; i < m; i++ {
for j := 0; j < n; j++ { for j := 0; j < n; j++ {
mat.Set(i, j, rand.NormFloat64()) mat.Set(i, j, rnd.NormFloat64())
} }
} }
rMatrix = returnAs(mat, t) rMatrix = returnAs(mat, t)
@@ -380,7 +381,7 @@ func makeRandOf(a Matrix, m, n int) Matrix {
}, },
} }
for i := 0; i < length; i++ { for i := 0; i < length; i++ {
mat.SetVec(i, rand.NormFloat64()) mat.SetVec(i, rnd.NormFloat64())
} }
return mat return mat
case *basicVector: case *basicVector:
@@ -394,7 +395,7 @@ func makeRandOf(a Matrix, m, n int) Matrix {
m: make([]float64, m), m: make([]float64, m),
} }
for i := 0; i < m; i++ { for i := 0; i < m; i++ {
mat.m[i] = rand.NormFloat64() mat.m[i] = rnd.NormFloat64()
} }
return mat return mat
case *SymDense, *basicSymmetric: case *SymDense, *basicSymmetric:
@@ -407,7 +408,7 @@ func makeRandOf(a Matrix, m, n int) Matrix {
} }
for i := 0; i < m; i++ { for i := 0; i < m; i++ {
for j := i; j < n; j++ { for j := i; j < n; j++ {
mat.SetSym(i, j, rand.NormFloat64()) mat.SetSym(i, j, rnd.NormFloat64())
} }
} }
rMatrix = returnAs(mat, t) rMatrix = returnAs(mat, t)
@@ -439,13 +440,13 @@ func makeRandOf(a Matrix, m, n int) Matrix {
if triKind == Upper { if triKind == Upper {
for i := 0; i < m; i++ { for i := 0; i < m; i++ {
for j := i; j < n; j++ { for j := i; j < n; j++ {
mat.SetTri(i, j, rand.NormFloat64()) mat.SetTri(i, j, rnd.NormFloat64())
} }
} }
} else { } else {
for i := 0; i < m; i++ { for i := 0; i < m; i++ {
for j := 0; j <= i; j++ { for j := 0; j <= i; j++ {
mat.SetTri(i, j, rand.NormFloat64()) mat.SetTri(i, j, rnd.NormFloat64())
} }
} }
} }
@@ -464,7 +465,7 @@ func makeRandOf(a Matrix, m, n int) Matrix {
kl = min(kl, m-1) kl = min(kl, m-1)
data := make([]float64, min(m, n+kl)*(kl+ku+1)) data := make([]float64, min(m, n+kl)*(kl+ku+1))
for i := range data { for i := range data {
data[i] = rand.NormFloat64() data[i] = rnd.NormFloat64()
} }
mat := NewBandDense(m, n, kl, ku, data) mat := NewBandDense(m, n, kl, ku, data)
rMatrix = returnAs(mat, t) rMatrix = returnAs(mat, t)
@@ -482,7 +483,7 @@ func makeRandOf(a Matrix, m, n int) Matrix {
k = min(k, m-1) // Special case for small sizes. k = min(k, m-1) // Special case for small sizes.
data := make([]float64, m*(k+1)) data := make([]float64, m*(k+1))
for i := range data { for i := range data {
data[i] = rand.NormFloat64() data[i] = rnd.NormFloat64()
} }
mat := NewSymBandDense(n, k, data) mat := NewSymBandDense(n, k, data)
rMatrix = returnAs(mat, t) rMatrix = returnAs(mat, t)
@@ -503,7 +504,7 @@ func makeRandOf(a Matrix, m, n int) Matrix {
k = min(k, m-1) // Special case for small sizes. k = min(k, m-1) // Special case for small sizes.
data := make([]float64, m*(k+1)) data := make([]float64, m*(k+1))
for i := range data { for i := range data {
data[i] = rand.NormFloat64() data[i] = rnd.NormFloat64()
} }
mat := NewTriBandDense(n, k, triKind, data) mat := NewTriBandDense(n, k, triKind, data)
rMatrix = returnAs(mat, t) rMatrix = returnAs(mat, t)
@@ -529,7 +530,7 @@ func makeRandOf(a Matrix, m, n int) Matrix {
}, },
} }
for i := 0; i < n; i++ { for i := 0; i < n; i++ {
mat.SetDiag(i, rand.Float64()) mat.SetDiag(i, rnd.Float64())
} }
rMatrix = returnAs(mat, t) rMatrix = returnAs(mat, t)
} }
@@ -908,6 +909,7 @@ func testOneInputFunc(t *testing.T,
// legalSize returns true if the size is valid for the function. // legalSize returns true if the size is valid for the function.
legalSize func(r, c int) bool, legalSize func(r, c int) bool,
) { ) {
src := rand.NewSource(1)
for _, aMat := range testMatrices { for _, aMat := range testMatrices {
for _, test := range sizes { for _, test := range sizes {
// Skip the test if the argument would not be assignable to the // Skip the test if the argument would not be assignable to the
@@ -919,7 +921,7 @@ func testOneInputFunc(t *testing.T,
if !legalDims(aMat, test.ar, test.ac) { if !legalDims(aMat, test.ar, test.ac) {
continue continue
} }
a := makeRandOf(aMat, test.ar, test.ac) a := makeRandOf(aMat, test.ar, test.ac, src)
// Compute the true answer if the sizes are legal. // Compute the true answer if the sizes are legal.
dimsOK := legalSize(test.ar, test.ac) dimsOK := legalSize(test.ar, test.ac)
@@ -1072,6 +1074,7 @@ func testTwoInputFunc(t *testing.T,
// legalSize returns true if the sizes are valid for the function. // legalSize returns true if the sizes are valid for the function.
legalSize func(ar, ac, br, bc int) bool, legalSize func(ar, ac, br, bc int) bool,
) { ) {
src := rand.NewSource(1)
for _, aMat := range testMatrices { for _, aMat := range testMatrices {
for _, bMat := range testMatrices { for _, bMat := range testMatrices {
// Loop over all of the size combinations (bigger, smaller, etc.). // Loop over all of the size combinations (bigger, smaller, etc.).
@@ -1088,8 +1091,8 @@ func testTwoInputFunc(t *testing.T,
if !legalDims(bMat, test.br, test.bc) { if !legalDims(bMat, test.br, test.bc) {
continue continue
} }
a := makeRandOf(aMat, test.ar, test.ac) a := makeRandOf(aMat, test.ar, test.ac, src)
b := makeRandOf(bMat, test.br, test.bc) b := makeRandOf(bMat, test.br, test.bc, src)
// Compute the true answer if the sizes are legal. // Compute the true answer if the sizes are legal.
dimsOK := legalSize(test.ar, test.ac, test.br, test.bc) dimsOK := legalSize(test.ar, test.ac, test.br, test.bc)
@@ -1158,6 +1161,7 @@ func testOneInput(t *testing.T,
// tol is the tolerance for equality when comparing method results. // tol is the tolerance for equality when comparing method results.
tol float64, tol float64,
) { ) {
src := rand.NewSource(1)
for _, aMat := range testMatrices { for _, aMat := range testMatrices {
for _, test := range sizes { for _, test := range sizes {
// Skip the test if the argument would not be assignable to the // Skip the test if the argument would not be assignable to the
@@ -1169,7 +1173,7 @@ func testOneInput(t *testing.T,
if !legalDims(aMat, test.ar, test.ac) { if !legalDims(aMat, test.ar, test.ac) {
continue continue
} }
a := makeRandOf(aMat, test.ar, test.ac) a := makeRandOf(aMat, test.ar, test.ac, src)
// Compute the true answer if the sizes are legal. // Compute the true answer if the sizes are legal.
dimsOK := legalSize(test.ar, test.ac) dimsOK := legalSize(test.ar, test.ac)
@@ -1184,7 +1188,7 @@ func testOneInput(t *testing.T,
// Test the method for a zero-value of the receiver. // Test the method for a zero-value of the receiver.
aType, aTrans := untranspose(a) aType, aTrans := untranspose(a)
errStr := fmt.Sprintf("%T.%s(%T), size: %#v, atrans %v", receiver, name, aType, test, aTrans) errStr := fmt.Sprintf("%T.%s(%T), size: %#v, atrans %v", receiver, name, aType, test, aTrans)
zero := makeRandOf(receiver, 0, 0) zero := makeRandOf(receiver, 0, 0, src)
panicked, err := panics(func() { method(zero, a) }) panicked, err := panics(func() { method(zero, a) })
if !dimsOK && !panicked { if !dimsOK && !panicked {
t.Errorf("Did not panic with illegal size: %s", errStr) t.Errorf("Did not panic with illegal size: %s", errStr)
@@ -1209,7 +1213,7 @@ func testOneInput(t *testing.T,
// The receiver has been overwritten in place so use its size // The receiver has been overwritten in place so use its size
// to construct a new random matrix. // to construct a new random matrix.
rr, rc := zero.Dims() rr, rc := zero.Dims()
neverZero := makeRandOf(receiver, rr, rc) neverZero := makeRandOf(receiver, rr, rc, src)
panicked, _ = panics(func() { method(neverZero, a) }) panicked, _ = panics(func() { method(neverZero, a) })
if panicked { if panicked {
t.Errorf("Panicked with non-zero receiver: %s", errStr) t.Errorf("Panicked with non-zero receiver: %s", errStr)
@@ -1223,26 +1227,26 @@ func testOneInput(t *testing.T,
default: default:
panic("matrix type not coded for incorrect receiver size") panic("matrix type not coded for incorrect receiver size")
case *Dense: case *Dense:
wrongSize := makeRandOf(receiver, rr+1, rc) wrongSize := makeRandOf(receiver, rr+1, rc, src)
panicked, _ = panics(func() { method(wrongSize, a) }) panicked, _ = panics(func() { method(wrongSize, a) })
if !panicked { if !panicked {
t.Errorf("Did not panic with wrong number of rows: %s", errStr) t.Errorf("Did not panic with wrong number of rows: %s", errStr)
} }
wrongSize = makeRandOf(receiver, rr, rc+1) wrongSize = makeRandOf(receiver, rr, rc+1, src)
panicked, _ = panics(func() { method(wrongSize, a) }) panicked, _ = panics(func() { method(wrongSize, a) })
if !panicked { if !panicked {
t.Errorf("Did not panic with wrong number of columns: %s", errStr) t.Errorf("Did not panic with wrong number of columns: %s", errStr)
} }
case *TriDense, *SymDense: case *TriDense, *SymDense:
// Add to the square size. // Add to the square size.
wrongSize := makeRandOf(receiver, rr+1, rc+1) wrongSize := makeRandOf(receiver, rr+1, rc+1, src)
panicked, _ = panics(func() { method(wrongSize, a) }) panicked, _ = panics(func() { method(wrongSize, a) })
if !panicked { if !panicked {
t.Errorf("Did not panic with wrong size: %s", errStr) t.Errorf("Did not panic with wrong size: %s", errStr)
} }
case *VecDense: case *VecDense:
// Add to the column length. // Add to the column length.
wrongSize := makeRandOf(receiver, rr+1, rc) wrongSize := makeRandOf(receiver, rr+1, rc, src)
panicked, _ = panics(func() { method(wrongSize, a) }) panicked, _ = panics(func() { method(wrongSize, a) })
if !panicked { if !panicked {
t.Errorf("Did not panic with wrong number of rows: %s", errStr) t.Errorf("Did not panic with wrong number of rows: %s", errStr)
@@ -1304,6 +1308,7 @@ func testTwoInput(t *testing.T,
// tol is the tolerance for equality when comparing method results. // tol is the tolerance for equality when comparing method results.
tol float64, tol float64,
) { ) {
src := rand.NewSource(1)
for _, aMat := range testMatrices { for _, aMat := range testMatrices {
for _, bMat := range testMatrices { for _, bMat := range testMatrices {
// Loop over all of the size combinations (bigger, smaller, etc.). // Loop over all of the size combinations (bigger, smaller, etc.).
@@ -1320,8 +1325,8 @@ func testTwoInput(t *testing.T,
if !legalDims(bMat, test.br, test.bc) { if !legalDims(bMat, test.br, test.bc) {
continue continue
} }
a := makeRandOf(aMat, test.ar, test.ac) a := makeRandOf(aMat, test.ar, test.ac, src)
b := makeRandOf(bMat, test.br, test.bc) b := makeRandOf(bMat, test.br, test.bc, src)
// Compute the true answer if the sizes are legal. // Compute the true answer if the sizes are legal.
dimsOK := legalSize(test.ar, test.ac, test.br, test.bc) dimsOK := legalSize(test.ar, test.ac, test.br, test.bc)
@@ -1339,7 +1344,7 @@ func testTwoInput(t *testing.T,
aType, aTrans := untranspose(a) aType, aTrans := untranspose(a)
bType, bTrans := untranspose(b) bType, bTrans := untranspose(b)
errStr := fmt.Sprintf("%T.%s(%T, %T), sizes: %#v, atrans %v, btrans %v", receiver, name, aType, bType, test, aTrans, bTrans) errStr := fmt.Sprintf("%T.%s(%T, %T), sizes: %#v, atrans %v, btrans %v", receiver, name, aType, bType, test, aTrans, bTrans)
zero := makeRandOf(receiver, 0, 0) zero := makeRandOf(receiver, 0, 0, src)
panicked, err := panics(func() { method(zero, a, b) }) panicked, err := panics(func() { method(zero, a, b) })
if !dimsOK && !panicked { if !dimsOK && !panicked {
t.Errorf("Did not panic with illegal size: %s", errStr) t.Errorf("Did not panic with illegal size: %s", errStr)
@@ -1369,7 +1374,7 @@ func testTwoInput(t *testing.T,
// The receiver has been overwritten in place so use its size // The receiver has been overwritten in place so use its size
// to construct a new random matrix. // to construct a new random matrix.
rr, rc := wasZero.Dims() rr, rc := wasZero.Dims()
neverZero := makeRandOf(receiver, rr, rc) neverZero := makeRandOf(receiver, rr, rc, src)
panicked, message := panics(func() { method(neverZero, a, b) }) panicked, message := panics(func() { method(neverZero, a, b) })
if panicked { if panicked {
t.Errorf("Panicked with non-zero receiver: %s: %s", errStr, message) t.Errorf("Panicked with non-zero receiver: %s: %s", errStr, message)
@@ -1384,26 +1389,26 @@ func testTwoInput(t *testing.T,
default: default:
panic("matrix type not coded for incorrect receiver size") panic("matrix type not coded for incorrect receiver size")
case *Dense: case *Dense:
wrongSize := makeRandOf(receiver, rr+1, rc) wrongSize := makeRandOf(receiver, rr+1, rc, src)
panicked, _ = panics(func() { method(wrongSize, a, b) }) panicked, _ = panics(func() { method(wrongSize, a, b) })
if !panicked { if !panicked {
t.Errorf("Did not panic with wrong number of rows: %s", errStr) t.Errorf("Did not panic with wrong number of rows: %s", errStr)
} }
wrongSize = makeRandOf(receiver, rr, rc+1) wrongSize = makeRandOf(receiver, rr, rc+1, src)
panicked, _ = panics(func() { method(wrongSize, a, b) }) panicked, _ = panics(func() { method(wrongSize, a, b) })
if !panicked { if !panicked {
t.Errorf("Did not panic with wrong number of columns: %s", errStr) t.Errorf("Did not panic with wrong number of columns: %s", errStr)
} }
case *TriDense, *SymDense: case *TriDense, *SymDense:
// Add to the square size. // Add to the square size.
wrongSize := makeRandOf(receiver, rr+1, rc+1) wrongSize := makeRandOf(receiver, rr+1, rc+1, src)
panicked, _ = panics(func() { method(wrongSize, a, b) }) panicked, _ = panics(func() { method(wrongSize, a, b) })
if !panicked { if !panicked {
t.Errorf("Did not panic with wrong size: %s", errStr) t.Errorf("Did not panic with wrong size: %s", errStr)
} }
case *VecDense: case *VecDense:
// Add to the column length. // Add to the column length.
wrongSize := makeRandOf(receiver, rr+1, rc) wrongSize := makeRandOf(receiver, rr+1, rc, src)
panicked, _ = panics(func() { method(wrongSize, a, b) }) panicked, _ = panics(func() { method(wrongSize, a, b) })
if !panicked { if !panicked {
t.Errorf("Did not panic with wrong number of rows: %s", errStr) t.Errorf("Did not panic with wrong number of rows: %s", errStr)
@@ -1475,7 +1480,7 @@ func testTwoInput(t *testing.T,
// Compute the real answer for this case. It is different // Compute the real answer for this case. It is different
// from the initial answer since now a and b have the // from the initial answer since now a and b have the
// same data. // same data.
zero = makeRandOf(wasZero, 0, 0) zero = makeRandOf(wasZero, 0, 0, src)
method(zero, aSame, bSame) method(zero, aSame, bSame)
wasZero, zero = zero, nil // Nil-out zero so we detect illegal use. wasZero, zero = zero, nil // Nil-out zero so we detect illegal use.
preData := underlyingData(receiver) preData := underlyingData(receiver)

View File

@@ -12,6 +12,7 @@ import (
func TestLQ(t *testing.T) { func TestLQ(t *testing.T) {
t.Parallel() t.Parallel()
rnd := rand.New(rand.NewSource(1))
for _, test := range []struct { for _, test := range []struct {
m, n int m, n int
}{ }{
@@ -23,7 +24,7 @@ func TestLQ(t *testing.T) {
a := NewDense(m, n, nil) a := NewDense(m, n, nil)
for i := 0; i < m; i++ { for i := 0; i < m; i++ {
for j := 0; j < n; j++ { for j := 0; j < n; j++ {
a.Set(i, j, rand.NormFloat64()) a.Set(i, j, rnd.NormFloat64())
} }
} }
var want Dense var want Dense
@@ -50,6 +51,7 @@ func TestLQ(t *testing.T) {
func TestLQSolveTo(t *testing.T) { func TestLQSolveTo(t *testing.T) {
t.Parallel() t.Parallel()
rnd := rand.New(rand.NewSource(1))
for _, trans := range []bool{false, true} { for _, trans := range []bool{false, true} {
for _, test := range []struct { for _, test := range []struct {
m, n, bc int m, n, bc int
@@ -65,7 +67,7 @@ func TestLQSolveTo(t *testing.T) {
a := NewDense(m, n, nil) a := NewDense(m, n, nil)
for i := 0; i < m; i++ { for i := 0; i < m; i++ {
for j := 0; j < n; j++ { for j := 0; j < n; j++ {
a.Set(i, j, rand.Float64()) a.Set(i, j, rnd.Float64())
} }
} }
br := m br := m
@@ -75,7 +77,7 @@ func TestLQSolveTo(t *testing.T) {
b := NewDense(br, bc, nil) b := NewDense(br, bc, nil)
for i := 0; i < br; i++ { for i := 0; i < br; i++ {
for j := 0; j < bc; j++ { for j := 0; j < bc; j++ {
b.Set(i, j, rand.Float64()) b.Set(i, j, rnd.Float64())
} }
} }
var x Dense var x Dense
@@ -112,6 +114,7 @@ func TestLQSolveTo(t *testing.T) {
func TestLQSolveToVec(t *testing.T) { func TestLQSolveToVec(t *testing.T) {
t.Parallel() t.Parallel()
rnd := rand.New(rand.NewSource(1))
for _, trans := range []bool{false, true} { for _, trans := range []bool{false, true} {
for _, test := range []struct { for _, test := range []struct {
m, n int m, n int
@@ -124,7 +127,7 @@ func TestLQSolveToVec(t *testing.T) {
a := NewDense(m, n, nil) a := NewDense(m, n, nil)
for i := 0; i < m; i++ { for i := 0; i < m; i++ {
for j := 0; j < n; j++ { for j := 0; j < n; j++ {
a.Set(i, j, rand.Float64()) a.Set(i, j, rnd.Float64())
} }
} }
br := m br := m
@@ -133,7 +136,7 @@ func TestLQSolveToVec(t *testing.T) {
} }
b := NewVecDense(br, nil) b := NewVecDense(br, nil)
for i := 0; i < br; i++ { for i := 0; i < br; i++ {
b.SetVec(i, rand.Float64()) b.SetVec(i, rnd.Float64())
} }
var x VecDense var x VecDense
lq := &LQ{} lq := &LQ{}

View File

@@ -12,11 +12,12 @@ import (
func TestLUD(t *testing.T) { func TestLUD(t *testing.T) {
t.Parallel() t.Parallel()
rnd := rand.New(rand.NewSource(1))
for _, n := range []int{1, 5, 10, 11, 50} { for _, n := range []int{1, 5, 10, 11, 50} {
a := NewDense(n, n, nil) a := NewDense(n, n, nil)
for i := 0; i < n; i++ { for i := 0; i < n; i++ {
for j := 0; j < n; j++ { for j := 0; j < n; j++ {
a.Set(i, j, rand.NormFloat64()) a.Set(i, j, rnd.NormFloat64())
} }
} }
var want Dense var want Dense
@@ -41,6 +42,7 @@ func TestLUD(t *testing.T) {
func TestLURankOne(t *testing.T) { func TestLURankOne(t *testing.T) {
t.Parallel() t.Parallel()
rnd := rand.New(rand.NewSource(1))
for _, pivoting := range []bool{true} { for _, pivoting := range []bool{true} {
for _, n := range []int{3, 10, 50} { for _, n := range []int{3, 10, 50} {
// Construct a random LU factorization // Construct a random LU factorization
@@ -48,7 +50,7 @@ func TestLURankOne(t *testing.T) {
lu.lu = NewDense(n, n, nil) lu.lu = NewDense(n, n, nil)
for i := 0; i < n; i++ { for i := 0; i < n; i++ {
for j := 0; j < n; j++ { for j := 0; j < n; j++ {
lu.lu.Set(i, j, rand.Float64()) lu.lu.Set(i, j, rnd.Float64())
} }
} }
lu.pivot = make([]int, n) lu.pivot = make([]int, n)
@@ -59,18 +61,18 @@ func TestLURankOne(t *testing.T) {
// For each row, randomly swap with itself or a row after (like is done) // For each row, randomly swap with itself or a row after (like is done)
// in the actual LU factorization. // in the actual LU factorization.
for i := range lu.pivot { for i := range lu.pivot {
idx := i + rand.Intn(n-i) idx := i + rnd.Intn(n-i)
lu.pivot[i], lu.pivot[idx] = lu.pivot[idx], lu.pivot[i] lu.pivot[i], lu.pivot[idx] = lu.pivot[idx], lu.pivot[i]
} }
} }
// Apply a rank one update. Ensure the update magnitude is larger than // Apply a rank one update. Ensure the update magnitude is larger than
// the equal tolerance. // the equal tolerance.
alpha := rand.Float64() + 1 alpha := rnd.Float64() + 1
x := NewVecDense(n, nil) x := NewVecDense(n, nil)
y := NewVecDense(n, nil) y := NewVecDense(n, nil)
for i := 0; i < n; i++ { for i := 0; i < n; i++ {
x.setVec(i, rand.Float64()+1) x.setVec(i, rnd.Float64()+1)
y.setVec(i, rand.Float64()+1) y.setVec(i, rnd.Float64()+1)
} }
a := luReconstruct(lu) a := luReconstruct(lu)
a.RankOne(a, alpha, x, y) a.RankOne(a, alpha, x, y)
@@ -109,6 +111,7 @@ func luReconstruct(lu *LU) *Dense {
func TestLUSolveTo(t *testing.T) { func TestLUSolveTo(t *testing.T) {
t.Parallel() t.Parallel()
rnd := rand.New(rand.NewSource(1))
for _, test := range []struct { for _, test := range []struct {
n, bc int n, bc int
}{ }{
@@ -121,13 +124,13 @@ func TestLUSolveTo(t *testing.T) {
a := NewDense(n, n, nil) a := NewDense(n, n, nil)
for i := 0; i < n; i++ { for i := 0; i < n; i++ {
for j := 0; j < n; j++ { for j := 0; j < n; j++ {
a.Set(i, j, rand.NormFloat64()) a.Set(i, j, rnd.NormFloat64())
} }
} }
b := NewDense(n, bc, nil) b := NewDense(n, bc, nil)
for i := 0; i < n; i++ { for i := 0; i < n; i++ {
for j := 0; j < bc; j++ { for j := 0; j < bc; j++ {
b.Set(i, j, rand.NormFloat64()) b.Set(i, j, rnd.NormFloat64())
} }
} }
var lu LU var lu LU
@@ -169,16 +172,17 @@ func TestLUSolveToCond(t *testing.T) {
func TestLUSolveVecTo(t *testing.T) { func TestLUSolveVecTo(t *testing.T) {
t.Parallel() t.Parallel()
rnd := rand.New(rand.NewSource(1))
for _, n := range []int{5, 10} { for _, n := range []int{5, 10} {
a := NewDense(n, n, nil) a := NewDense(n, n, nil)
for i := 0; i < n; i++ { for i := 0; i < n; i++ {
for j := 0; j < n; j++ { for j := 0; j < n; j++ {
a.Set(i, j, rand.NormFloat64()) a.Set(i, j, rnd.NormFloat64())
} }
} }
b := NewVecDense(n, nil) b := NewVecDense(n, nil)
for i := 0; i < n; i++ { for i := 0; i < n; i++ {
b.SetVec(i, rand.NormFloat64()) b.SetVec(i, rnd.NormFloat64())
} }
var lu LU var lu LU
lu.Factorize(a) lu.Factorize(a)

View File

@@ -17,6 +17,7 @@ import (
// TODO: Need to add tests where one is overwritten. // TODO: Need to add tests where one is overwritten.
func TestMulTypes(t *testing.T) { func TestMulTypes(t *testing.T) {
t.Parallel() t.Parallel()
src := rand.NewSource(1)
for _, test := range []struct { for _, test := range []struct {
ar int ar int
ac int ac int
@@ -88,11 +89,11 @@ func TestMulTypes(t *testing.T) {
// Generate random matrices // Generate random matrices
avec := make([]float64, ar*ac) avec := make([]float64, ar*ac)
randomSlice(avec) randomSlice(avec, src)
a := NewDense(ar, ac, avec) a := NewDense(ar, ac, avec)
bvec := make([]float64, br*bc) bvec := make([]float64, br*bc)
randomSlice(bvec) randomSlice(bvec, src)
b := NewDense(br, bc, bvec) b := NewDense(br, bc, bvec)
@@ -132,7 +133,7 @@ func TestMulTypes(t *testing.T) {
// Normal multiply with existing receiver // Normal multiply with existing receiver
c := NewDense(ar, bc, cvec) c := NewDense(ar, bc, cvec)
randomSlice(cvec) randomSlice(cvec, src)
testMul(t, a, b, c, acomp, bcomp, ccomp, false, "existing receiver") testMul(t, a, b, c, acomp, bcomp, ccomp, false, "existing receiver")
// Cast a as a basic matrix // Cast a as a basic matrix
@@ -144,18 +145,19 @@ func TestMulTypes(t *testing.T) {
testMul(t, a, bm, d, acomp, bcomp, ccomp, true, "b is basic, receiver is empty") testMul(t, a, bm, d, acomp, bcomp, ccomp, true, "b is basic, receiver is empty")
d.Reset() d.Reset()
testMul(t, am, bm, d, acomp, bcomp, ccomp, true, "both basic, receiver is empty") testMul(t, am, bm, d, acomp, bcomp, ccomp, true, "both basic, receiver is empty")
randomSlice(cvec) randomSlice(cvec, src)
testMul(t, am, b, d, acomp, bcomp, ccomp, true, "a is basic, receiver is full") testMul(t, am, b, d, acomp, bcomp, ccomp, true, "a is basic, receiver is full")
randomSlice(cvec) randomSlice(cvec, src)
testMul(t, a, bm, d, acomp, bcomp, ccomp, true, "b is basic, receiver is full") testMul(t, a, bm, d, acomp, bcomp, ccomp, true, "b is basic, receiver is full")
randomSlice(cvec) randomSlice(cvec, src)
testMul(t, am, bm, d, acomp, bcomp, ccomp, true, "both basic, receiver is full") testMul(t, am, bm, d, acomp, bcomp, ccomp, true, "both basic, receiver is full")
} }
} }
func randomSlice(s []float64) { func randomSlice(s []float64, src rand.Source) {
rnd := rand.New(src)
for i := range s { for i := range s {
s[i] = rand.NormFloat64() s[i] = rnd.NormFloat64()
} }
} }

View File

@@ -73,9 +73,10 @@ func BenchmarkMulWorkspaceDense1000Tenth(b *testing.B) { denseMulWorkspaceB
func BenchmarkMulWorkspaceDense1000Hundredth(b *testing.B) { denseMulWorkspaceBench(b, 1000, 0.01) } func BenchmarkMulWorkspaceDense1000Hundredth(b *testing.B) { denseMulWorkspaceBench(b, 1000, 0.01) }
func BenchmarkMulWorkspaceDense1000Thousandth(b *testing.B) { denseMulWorkspaceBench(b, 1000, 0.001) } func BenchmarkMulWorkspaceDense1000Thousandth(b *testing.B) { denseMulWorkspaceBench(b, 1000, 0.001) }
func denseMulWorkspaceBench(b *testing.B, size int, rho float64) { func denseMulWorkspaceBench(b *testing.B, size int, rho float64) {
src := rand.NewSource(1)
b.StopTimer() b.StopTimer()
a, _ := randDense(size, rho, rand.NormFloat64) a, _ := randDense(size, rho, src)
d, _ := randDense(size, rho, rand.NormFloat64) d, _ := randDense(size, rho, src)
b.StartTimer() b.StartTimer()
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
a.Mul(a, d) a.Mul(a, d)

View File

@@ -92,6 +92,7 @@ var productTests = []struct {
func TestProduct(t *testing.T) { func TestProduct(t *testing.T) {
t.Parallel() t.Parallel()
rnd := rand.New(rand.NewSource(1))
for _, test := range productTests { for _, test := range productTests {
dimensions := test.factors dimensions := test.factors
if dimensions == nil && test.n > 0 { if dimensions == nil && test.n > 0 {
@@ -100,7 +101,7 @@ func TestProduct(t *testing.T) {
if i != 0 { if i != 0 {
dimensions[i].r = dimensions[i-1].c dimensions[i].r = dimensions[i-1].c
} }
dimensions[i].c = rand.Intn(50) + 1 dimensions[i].c = rnd.Intn(50) + 1
} }
dimensions[0].r = test.product.r dimensions[0].r = test.product.r
dimensions[test.n-1].c = test.product.c dimensions[test.n-1].c = test.product.c
@@ -109,7 +110,7 @@ func TestProduct(t *testing.T) {
for i, d := range dimensions { for i, d := range dimensions {
data := make([]float64, d.r*d.c) data := make([]float64, d.r*d.c)
for i := range data { for i := range data {
data[i] = rand.Float64() data[i] = rnd.Float64()
} }
factors[i] = NewDense(d.r, d.c, data) factors[i] = NewDense(d.r, d.c, data)
} }

View File

@@ -15,6 +15,7 @@ import (
func TestQR(t *testing.T) { func TestQR(t *testing.T) {
t.Parallel() t.Parallel()
rnd := rand.New(rand.NewSource(1))
for _, test := range []struct { for _, test := range []struct {
m, n int m, n int
}{ }{
@@ -26,7 +27,7 @@ func TestQR(t *testing.T) {
a := NewDense(m, n, nil) a := NewDense(m, n, nil)
for i := 0; i < m; i++ { for i := 0; i < m; i++ {
for j := 0; j < n; j++ { for j := 0; j < n; j++ {
a.Set(i, j, rand.NormFloat64()) a.Set(i, j, rnd.NormFloat64())
} }
} }
var want Dense var want Dense
@@ -74,6 +75,7 @@ func isOrthonormal(q *Dense, tol float64) bool {
func TestQRSolveTo(t *testing.T) { func TestQRSolveTo(t *testing.T) {
t.Parallel() t.Parallel()
rnd := rand.New(rand.NewSource(1))
for _, trans := range []bool{false, true} { for _, trans := range []bool{false, true} {
for _, test := range []struct { for _, test := range []struct {
m, n, bc int m, n, bc int
@@ -89,7 +91,7 @@ func TestQRSolveTo(t *testing.T) {
a := NewDense(m, n, nil) a := NewDense(m, n, nil)
for i := 0; i < m; i++ { for i := 0; i < m; i++ {
for j := 0; j < n; j++ { for j := 0; j < n; j++ {
a.Set(i, j, rand.Float64()) a.Set(i, j, rnd.Float64())
} }
} }
br := m br := m
@@ -99,7 +101,7 @@ func TestQRSolveTo(t *testing.T) {
b := NewDense(br, bc, nil) b := NewDense(br, bc, nil)
for i := 0; i < br; i++ { for i := 0; i < br; i++ {
for j := 0; j < bc; j++ { for j := 0; j < bc; j++ {
b.Set(i, j, rand.Float64()) b.Set(i, j, rnd.Float64())
} }
} }
var x Dense var x Dense
@@ -136,6 +138,7 @@ func TestQRSolveTo(t *testing.T) {
func TestQRSolveVecTo(t *testing.T) { func TestQRSolveVecTo(t *testing.T) {
t.Parallel() t.Parallel()
rnd := rand.New(rand.NewSource(1))
for _, trans := range []bool{false, true} { for _, trans := range []bool{false, true} {
for _, test := range []struct { for _, test := range []struct {
m, n int m, n int
@@ -148,7 +151,7 @@ func TestQRSolveVecTo(t *testing.T) {
a := NewDense(m, n, nil) a := NewDense(m, n, nil)
for i := 0; i < m; i++ { for i := 0; i < m; i++ {
for j := 0; j < n; j++ { for j := 0; j < n; j++ {
a.Set(i, j, rand.Float64()) a.Set(i, j, rnd.Float64())
} }
} }
br := m br := m
@@ -157,7 +160,7 @@ func TestQRSolveVecTo(t *testing.T) {
} }
b := NewVecDense(br, nil) b := NewVecDense(br, nil)
for i := 0; i < br; i++ { for i := 0; i < br; i++ {
b.SetVec(i, rand.Float64()) b.SetVec(i, rnd.Float64())
} }
var x VecDense var x VecDense
var qr QR var qr QR

View File

@@ -12,6 +12,7 @@ import (
func TestSolve(t *testing.T) { func TestSolve(t *testing.T) {
t.Parallel() t.Parallel()
rnd := rand.New(rand.NewSource(1))
// Hand-coded cases. // Hand-coded cases.
for _, test := range []struct { for _, test := range []struct {
a [][]float64 a [][]float64
@@ -204,14 +205,14 @@ func TestSolve(t *testing.T) {
a := NewDense(m, n, nil) a := NewDense(m, n, nil)
for i := 0; i < m; i++ { for i := 0; i < m; i++ {
for j := 0; j < n; j++ { for j := 0; j < n; j++ {
a.Set(i, j, rand.Float64()) a.Set(i, j, rnd.Float64())
} }
} }
br := m br := m
b := NewDense(br, bc, nil) b := NewDense(br, bc, nil)
for i := 0; i < br; i++ { for i := 0; i < br; i++ {
for j := 0; j < bc; j++ { for j := 0; j < bc; j++ {
b.Set(i, j, rand.Float64()) b.Set(i, j, rnd.Float64())
} }
} }
var x Dense var x Dense
@@ -247,6 +248,7 @@ func TestSolve(t *testing.T) {
func TestSolveVec(t *testing.T) { func TestSolveVec(t *testing.T) {
t.Parallel() t.Parallel()
rnd := rand.New(rand.NewSource(1))
for _, test := range []struct { for _, test := range []struct {
m, n int m, n int
}{ }{
@@ -265,13 +267,13 @@ func TestSolveVec(t *testing.T) {
a := NewDense(m, n, nil) a := NewDense(m, n, nil)
for i := 0; i < m; i++ { for i := 0; i < m; i++ {
for j := 0; j < n; j++ { for j := 0; j < n; j++ {
a.Set(i, j, rand.Float64()) a.Set(i, j, rnd.Float64())
} }
} }
br := m br := m
b := NewVecDense(br, nil) b := NewVecDense(br, nil)
for i := 0; i < br; i++ { for i := 0; i < br; i++ {
b.SetVec(i, rand.Float64()) b.SetVec(i, rnd.Float64())
} }
var x VecDense var x VecDense
err := x.SolveVec(a, b) err := x.SolveVec(a, b)

View File

@@ -14,6 +14,7 @@ import (
func TestSVD(t *testing.T) { func TestSVD(t *testing.T) {
t.Parallel() t.Parallel()
rnd := rand.New(rand.NewSource(1))
// Hand coded tests // Hand coded tests
for _, test := range []struct { for _, test := range []struct {
a *Dense a *Dense
@@ -106,7 +107,7 @@ func TestSVD(t *testing.T) {
for trial := 0; trial < 10; trial++ { for trial := 0; trial < 10; trial++ {
a := NewDense(m, n, nil) a := NewDense(m, n, nil)
for i := range a.mat.Data { for i := range a.mat.Data {
a.mat.Data[i] = rand.NormFloat64() a.mat.Data[i] = rnd.NormFloat64()
} }
aCopy := DenseCopyOf(a) aCopy := DenseCopyOf(a)

View File

@@ -177,6 +177,7 @@ func TestSymDiagView(t *testing.T) {
func TestSymAdd(t *testing.T) { func TestSymAdd(t *testing.T) {
t.Parallel() t.Parallel()
rnd := rand.New(rand.NewSource(1))
for _, test := range []struct { for _, test := range []struct {
n int n int
}{ }{
@@ -190,11 +191,11 @@ func TestSymAdd(t *testing.T) {
n := test.n n := test.n
a := NewSymDense(n, nil) a := NewSymDense(n, nil)
for i := range a.mat.Data { for i := range a.mat.Data {
a.mat.Data[i] = rand.Float64() a.mat.Data[i] = rnd.Float64()
} }
b := NewSymDense(n, nil) b := NewSymDense(n, nil)
for i := range a.mat.Data { for i := range a.mat.Data {
b.mat.Data[i] = rand.Float64() b.mat.Data[i] = rnd.Float64()
} }
var m Dense var m Dense
m.Add(a, b) m.Add(a, b)
@@ -239,6 +240,7 @@ func TestSymAdd(t *testing.T) {
func TestCopy(t *testing.T) { func TestCopy(t *testing.T) {
t.Parallel() t.Parallel()
rnd := rand.New(rand.NewSource(1))
for _, test := range []struct { for _, test := range []struct {
n int n int
}{ }{
@@ -252,7 +254,7 @@ func TestCopy(t *testing.T) {
n := test.n n := test.n
a := NewSymDense(n, nil) a := NewSymDense(n, nil)
for i := range a.mat.Data { for i := range a.mat.Data {
a.mat.Data[i] = rand.Float64() a.mat.Data[i] = rnd.Float64()
} }
s := NewSymDense(n, nil) s := NewSymDense(n, nil)
s.CopySym(a) s.CopySym(a)
@@ -287,6 +289,7 @@ func TestSymCopyPanic(t *testing.T) {
func TestSymRankOne(t *testing.T) { func TestSymRankOne(t *testing.T) {
t.Parallel() t.Parallel()
rnd := rand.New(rand.NewSource(1))
const tol = 1e-15 const tol = 1e-15
for _, test := range []struct { for _, test := range []struct {
@@ -303,11 +306,11 @@ func TestSymRankOne(t *testing.T) {
alpha := 2.0 alpha := 2.0
a := NewSymDense(n, nil) a := NewSymDense(n, nil)
for i := range a.mat.Data { for i := range a.mat.Data {
a.mat.Data[i] = rand.Float64() a.mat.Data[i] = rnd.Float64()
} }
x := make([]float64, n) x := make([]float64, n)
for i := range x { for i := range x {
x[i] = rand.Float64() x[i] = rnd.Float64()
} }
xMat := NewDense(n, 1, x) xMat := NewDense(n, 1, x)
@@ -386,6 +389,7 @@ func TestIssue250SymRankOne(t *testing.T) {
func TestRankTwo(t *testing.T) { func TestRankTwo(t *testing.T) {
t.Parallel() t.Parallel()
rnd := rand.New(rand.NewSource(1))
for _, test := range []struct { for _, test := range []struct {
n int n int
}{ }{
@@ -400,13 +404,13 @@ func TestRankTwo(t *testing.T) {
alpha := 2.0 alpha := 2.0
a := NewSymDense(n, nil) a := NewSymDense(n, nil)
for i := range a.mat.Data { for i := range a.mat.Data {
a.mat.Data[i] = rand.Float64() a.mat.Data[i] = rnd.Float64()
} }
x := make([]float64, n) x := make([]float64, n)
y := make([]float64, n) y := make([]float64, n)
for i := range x { for i := range x {
x[i] = rand.Float64() x[i] = rnd.Float64()
y[i] = rand.Float64() y[i] = rnd.Float64()
} }
xMat := NewDense(n, 1, x) xMat := NewDense(n, 1, x)
@@ -763,19 +767,21 @@ func BenchmarkSymSum1000(b *testing.B) { symSumBench(b, 1000) }
var symSumForBench float64 var symSumForBench float64
func symSumBench(b *testing.B, size int) { func symSumBench(b *testing.B, size int) {
a := randSymDense(size) src := rand.NewSource(1)
a := randSymDense(size, src)
b.ResetTimer() b.ResetTimer()
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
symSumForBench = Sum(a) symSumForBench = Sum(a)
} }
} }
func randSymDense(size int) *SymDense { func randSymDense(size int, src rand.Source) *SymDense {
rnd := rand.New(src)
backData := make([]float64, size*size) backData := make([]float64, size*size)
for i := 0; i < size; i++ { for i := 0; i < size; i++ {
backData[i*size+i] = rand.Float64() backData[i*size+i] = rnd.Float64()
for j := i + 1; j < size; j++ { for j := i + 1; j < size; j++ {
v := rand.Float64() v := rnd.Float64()
backData[i*size+j] = v backData[i*size+j] = v
backData[j*size+i] = v backData[j*size+i] = v
} }

View File

@@ -204,9 +204,11 @@ func TestTriDiagView(t *testing.T) {
func TestTriDenseCopy(t *testing.T) { func TestTriDenseCopy(t *testing.T) {
t.Parallel() t.Parallel()
src := rand.NewSource(1)
rnd := rand.New(src)
for i := 0; i < 100; i++ { for i := 0; i < 100; i++ {
size := rand.Intn(100) size := rnd.Intn(100)
r, err := randDense(size, 0.9, rand.NormFloat64) r, err := randDense(size, 0.9, src)
if size == 0 { if size == 0 {
if err != ErrZeroLength { if err != ErrZeroLength {
t.Fatalf("expected error %v: got: %v", ErrZeroLength, err) t.Fatalf("expected error %v: got: %v", ErrZeroLength, err)
@@ -255,9 +257,11 @@ func TestTriDenseCopy(t *testing.T) {
func TestTriTriDenseCopy(t *testing.T) { func TestTriTriDenseCopy(t *testing.T) {
t.Parallel() t.Parallel()
src := rand.NewSource(1)
rnd := rand.New(src)
for i := 0; i < 100; i++ { for i := 0; i < 100; i++ {
size := rand.Intn(100) size := rnd.Intn(100)
r, err := randDense(size, 1, rand.NormFloat64) r, err := randDense(size, 1, src)
if size == 0 { if size == 0 {
if err != ErrZeroLength { if err != ErrZeroLength {
t.Fatalf("expected error %v: got: %v", ErrZeroLength, err) t.Fatalf("expected error %v: got: %v", ErrZeroLength, err)
@@ -308,11 +312,12 @@ func TestTriTriDenseCopy(t *testing.T) {
func TestTriInverse(t *testing.T) { func TestTriInverse(t *testing.T) {
t.Parallel() t.Parallel()
rnd := rand.New(rand.NewSource(1))
for _, kind := range []TriKind{Upper, Lower} { for _, kind := range []TriKind{Upper, Lower} {
for _, n := range []int{1, 3, 5, 9} { for _, n := range []int{1, 3, 5, 9} {
data := make([]float64, n*n) data := make([]float64, n*n)
for i := range data { for i := range data {
data[i] = rand.NormFloat64() data[i] = rnd.NormFloat64()
} }
a := NewTriDense(n, kind, data) a := NewTriDense(n, kind, data)
var tr TriDense var tr TriDense

View File

@@ -498,8 +498,9 @@ func BenchmarkAddScaledVec1000Inc20(b *testing.B) { addScaledVecBench(b, 1000,
func BenchmarkAddScaledVec10000Inc20(b *testing.B) { addScaledVecBench(b, 10000, 20) } func BenchmarkAddScaledVec10000Inc20(b *testing.B) { addScaledVecBench(b, 10000, 20) }
func BenchmarkAddScaledVec100000Inc20(b *testing.B) { addScaledVecBench(b, 100000, 20) } func BenchmarkAddScaledVec100000Inc20(b *testing.B) { addScaledVecBench(b, 100000, 20) }
func addScaledVecBench(b *testing.B, size, inc int) { func addScaledVecBench(b *testing.B, size, inc int) {
x := randVecDense(size, inc, 1, rand.NormFloat64) src := rand.NewSource(1)
y := randVecDense(size, inc, 1, rand.NormFloat64) x := randVecDense(size, inc, 1, src)
y := randVecDense(size, inc, 1, src)
b.ResetTimer() b.ResetTimer()
var v VecDense var v VecDense
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
@@ -523,7 +524,8 @@ func BenchmarkScaleVec1000Inc20(b *testing.B) { scaleVecBench(b, 1000, 20) }
func BenchmarkScaleVec10000Inc20(b *testing.B) { scaleVecBench(b, 10000, 20) } func BenchmarkScaleVec10000Inc20(b *testing.B) { scaleVecBench(b, 10000, 20) }
func BenchmarkScaleVec100000Inc20(b *testing.B) { scaleVecBench(b, 100000, 20) } func BenchmarkScaleVec100000Inc20(b *testing.B) { scaleVecBench(b, 100000, 20) }
func scaleVecBench(b *testing.B, size, inc int) { func scaleVecBench(b *testing.B, size, inc int) {
x := randVecDense(size, inc, 1, rand.NormFloat64) src := rand.NewSource(1)
x := randVecDense(size, inc, 1, src)
b.ResetTimer() b.ResetTimer()
var v VecDense var v VecDense
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
@@ -547,8 +549,9 @@ func BenchmarkAddVec1000Inc20(b *testing.B) { addVecBench(b, 1000, 20) }
func BenchmarkAddVec10000Inc20(b *testing.B) { addVecBench(b, 10000, 20) } func BenchmarkAddVec10000Inc20(b *testing.B) { addVecBench(b, 10000, 20) }
func BenchmarkAddVec100000Inc20(b *testing.B) { addVecBench(b, 100000, 20) } func BenchmarkAddVec100000Inc20(b *testing.B) { addVecBench(b, 100000, 20) }
func addVecBench(b *testing.B, size, inc int) { func addVecBench(b *testing.B, size, inc int) {
x := randVecDense(size, inc, 1, rand.NormFloat64) src := rand.NewSource(1)
y := randVecDense(size, inc, 1, rand.NormFloat64) x := randVecDense(size, inc, 1, src)
y := randVecDense(size, inc, 1, src)
b.ResetTimer() b.ResetTimer()
var v VecDense var v VecDense
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
@@ -572,8 +575,9 @@ func BenchmarkSubVec1000Inc20(b *testing.B) { subVecBench(b, 1000, 20) }
func BenchmarkSubVec10000Inc20(b *testing.B) { subVecBench(b, 10000, 20) } func BenchmarkSubVec10000Inc20(b *testing.B) { subVecBench(b, 10000, 20) }
func BenchmarkSubVec100000Inc20(b *testing.B) { subVecBench(b, 100000, 20) } func BenchmarkSubVec100000Inc20(b *testing.B) { subVecBench(b, 100000, 20) }
func subVecBench(b *testing.B, size, inc int) { func subVecBench(b *testing.B, size, inc int) {
x := randVecDense(size, inc, 1, rand.NormFloat64) src := rand.NewSource(1)
y := randVecDense(size, inc, 1, rand.NormFloat64) x := randVecDense(size, inc, 1, src)
y := randVecDense(size, inc, 1, src)
b.ResetTimer() b.ResetTimer()
var v VecDense var v VecDense
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
@@ -581,14 +585,15 @@ func subVecBench(b *testing.B, size, inc int) {
} }
} }
func randVecDense(size, inc int, rho float64, rnd func() float64) *VecDense { func randVecDense(size, inc int, rho float64, src rand.Source) *VecDense {
if size <= 0 { if size <= 0 {
panic("bad vector size") panic("bad vector size")
} }
rnd := rand.New(src)
data := make([]float64, size*inc) data := make([]float64, size*inc)
for i := range data { for i := range data {
if rand.Float64() < rho { if rnd.Float64() < rho {
data[i] = rnd() data[i] = rnd.NormFloat64()
} }
} }
return &VecDense{ return &VecDense{
@@ -605,7 +610,8 @@ func BenchmarkVectorSum100000(b *testing.B) { vectorSumBench(b, 100000) }
var vectorSumForBench float64 var vectorSumForBench float64
func vectorSumBench(b *testing.B, size int) { func vectorSumBench(b *testing.B, size int) {
a := randVecDense(size, 1, 1.0, rand.NormFloat64) src := rand.NewSource(1)
a := randVecDense(size, 1, 1.0, src)
b.ResetTimer() b.ResetTimer()
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
vectorSumForBench = Sum(a) vectorSumForBench = Sum(a)