mat: Add Diagonal interface and DiagDense type
mat: Add Diagonal interface and DiagDense type
Fixes 592.
MODIFY
AUTHORS
AUTHORS
@@ -19,6 +19,7 @@ Dan Kortschak <dan.kortschak@adelaide.edu.au> <dan@kortschak.io>
Daniel Fireman <danielfireman@gmail.com>
David Samborski <bloggingarrow@gmail.com>
Davor Kapsa <davor.kapsa@gmail.com>
+DeepMind Technologies
Egon Elbre <egonelbre@gmail.com>
Ekaterina Efimova <katerina.efimova@gmail.com>
Ethan Burns <burns.ethan@gmail.com>

MODIFY
mat/errors.go
mat/errors.go
@@ -130,6 +130,7 @@ var (
ErrTriangle = Error{"matrix: triangular storage mismatch"}
ErrTriangleSet = Error{"matrix: triangular set out of bounds"}
ErrBandSet = Error{"matrix: band set out of bounds"}
+ ErrDiagSet = Error{"matrix: diagonal set out of bounds"}
ErrSliceLengthMismatch = Error{"matrix: input slice length mismatch"}
ErrNotPSD = Error{"matrix: input not positive symmetric definite"}
ErrFailedEigen = Error{"matrix: eigendecomposition not successful"}

MODIFY
mat/index_bound_checks.go
mat/index_bound_checks.go
@@ -231,3 +231,34 @@ func (s *SymBandDense) set(i, j int, v float64) {
}
s.mat.Data[i*s.mat.Stride+pj] = v
}
+
+// At returns the element at row i, column j.
+func (d *DiagDense) At(i, j int) float64 {
+ return d.at(i, j)
+}
+
+func (d *DiagDense) at(i, j int) float64 {
+ if uint(i) >= uint(len(d.data)) {
+ panic(ErrRowAccess)
+ }
+ if uint(j) >= uint(len(d.data)) {
+ panic(ErrColAccess)
+ }
+ if i != j {
+ return 0
+ }
+ return d.data[i]
+}
+
+// SetDiag sets the element at row i, column i to the value v.
+// It panics if the location is outside the appropriate region of the matrix.
+func (d *DiagDense) SetDiag(i int, v float64) {
+ d.setDiag(i, v)
+}
+
+func (d *DiagDense) setDiag(i int, v float64) {
+ if uint(i) >= uint(len(d.data)) {
+ panic(ErrRowAccess)
+ }
+ d.data[i] = v
+}

MODIFY
mat/index_no_bound_checks.go
mat/index_no_bound_checks.go
@@ -235,3 +235,34 @@ func (s *SymBandDense) set(i, j int, v float64) {
}
s.mat.Data[i*s.mat.Stride+pj] = v
}
+
+// At returns the element at row i, column j.
+func (d *DiagDense) At(i, j int) float64 {
+ if uint(i) >= uint(len(d.data)) {
+ panic(ErrRowAccess)
+ }
+ if uint(j) >= uint(len(d.data)) {
+ panic(ErrColAccess)
+ }
+ return d.at(i, j)
+}
+
+func (d *DiagDense) at(i, j int) float64 {
+ if i != j {
+ return 0
+ }
+ return d.data[i]
+}
+
+// SetDiag sets the element at row i, column i to the value v.
+// It panics if the location is outside the appropriate region of the matrix.
+func (d *DiagDense) SetDiag(i int, v float64) {
+ if uint(i) >= uint(len(d.data)) {
+ panic(ErrRowAccess)
+ }
+ d.setDiag(i, v)
+}
+
+func (d *DiagDense) setDiag(i int, v float64) {
+ d.data[i] = v
+}

MODIFY
mat/symband.go
mat/symband.go
@@ -91,13 +91,6 @@ func NewSymBandDense(n, k int, data []float64) *SymBandDense {
}
}
-// NewDiagonal is a convenience function that returns a diagonal matrix represented by a
-// SymBandDense. The length of data must be n or data must be nil, otherwise NewDiagonal
-// will panic.
-func NewDiagonal(n int, data []float64) *SymBandDense {
- return NewSymBandDense(n, 0, data)
-}
-
// Dims returns the number of rows and columns in the matrix.
func (s *SymBandDense) Dims() (r, c int) {
return s.mat.N, s.mat.N

MODIFY
mat/symband_test.go
mat/symband_test.go
@@ -78,55 +78,6 @@ func TestNewSymBand(t *testing.T) {
}
}
-func TestNewDiagonal(t *testing.T) {
- for i, test := range []struct {
- data []float64
- n int
- mat *SymBandDense
- dense *Dense
- }{
- {
- data: []float64{1, 2, 3, 4, 5, 6},
- n: 6,
- mat: &SymBandDense{
- mat: blas64.SymmetricBand{
- N: 6,
- Stride: 1,
- Uplo: blas.Upper,
- Data: []float64{1, 2, 3, 4, 5, 6},
- },
- },
- dense: NewDense(6, 6, []float64{
- 1, 0, 0, 0, 0, 0,
- 0, 2, 0, 0, 0, 0,
- 0, 0, 3, 0, 0, 0,
- 0, 0, 0, 4, 0, 0,
- 0, 0, 0, 0, 5, 0,
- 0, 0, 0, 0, 0, 6,
- }),
- },
- } {
- band := NewDiagonal(test.n, test.data)
- rows, cols := band.Dims()
-
- if rows != test.n {
- t.Errorf("unexpected number of rows for test %d: got: %d want: %d", i, rows, test.n)
- }
- if cols != test.n {
- t.Errorf("unexpected number of cols for test %d: got: %d want: %d", i, cols, test.n)
- }
- if !reflect.DeepEqual(band, test.mat) {
- t.Errorf("unexpected value via reflect for test %d: got: %v want: %v", i, band, test.mat)
- }
- if !Equal(band, test.mat) {
- t.Errorf("unexpected value via mat.Equal for test %d: got: %v want: %v", i, band, test.mat)
- }
- if !Equal(band, test.dense) {
- t.Errorf("unexpected value via mat.Equal(band, dense) for test %d:\ngot:\n% v\nwant:\n% v", i, Formatted(band), Formatted(test.dense))
- }
- }
-}
-
func TestSymBandAtSet(t *testing.T) {
// 1 2 3 0 0 0
// 2 4 5 6 0 0

MODIFY
optimize/cmaes.go
optimize/cmaes.go
@@ -212,7 +212,7 @@ func (cma *CmaEsChol) Init(dim, tasks int) int {
// Set the initial Cholesky to I.
b := mat.NewDiagonal(dim, nil)
for i := 0; i < dim; i++ {
- b.SetSymBand(i, i, 1)
+ b.SetDiag(i, 1)
}
var chol mat.Cholesky
ok := chol.Factorize(b)

MODIFY
stat/pca_test.go
stat/pca_test.go
@@ -185,7 +185,7 @@ tests:
// orthonormal by comparing V^T*V to the identity matrix.
I := mat.NewDiagonal(c, nil)
for k := 0; k < c; k++ {
- I.SetSymBand(k, k, 1)
+ I.SetDiag(k, 1)
}
var vv mat.Dense
vv.Mul(vecs.T(), vecs)

mat: Add Diagonal interface and DiagDense type (#594)

mat: Add Diagonal interface and DiagDense type

Fixes 592.