Repository: gonum/gonum (language: go)

Issue:
proposal: mat: rename Symmetric method to avoid name conflict when embedding mat.Symmetric
Trying to embed mat.Symmetric in another struct
```
type SymmetricLinOp struct {
    mat.Symmetric
}
```
 and get a `SymmetricLinOp.Symmetric is a field, not a method` error during compilation. I suppose this is why the "-er" suffix rule is often used, to avoid this kind of issue. Obviously, I can just make a named field and write wrappers for all the relevant methods, but that's a bit of a waste. 


Discussion / hints:
Can you paste a reproducer just so we can see the impact.

The obvious work-around for this is to define a local renaming of `mat.Symmetric`, say `type symmetric = mat.Symmetric` and then `type SymmetricLinOp struct { symmetric }`. This is not ideal, but workable. The fix would be to rename the `Symmetric` method, but that's a big change in terms of API breakage, so it needs to be considered carefully (if we were to do this, I would suggest something like `SymDim() int`)
```
package main

import "gonum.org/v1/gonum/mat"

type SymLinOp interface {
	mat.Symmetric
	MulVecTo(dst *mat.VecDense, _ bool, x mat.Vector)
}

type SymmetricWrapper struct {
	mat.Symmetric
}

func (m *SymmetricWrapper) MulVecTo(dst *mat.VecDense, _ bool, x mat.Vector) {
	dst.MulVec(m.Symmetric, x)
}

func takesSymLinOp(s SymLinOp) {}

func main(){
	s := mat.NewSymDense(3, []float64{2, 1, 1, 0, 2, 1, 0, 0, 2})
	w := &SymmetricWrapper{s}
	takesSymLinOp(w)
}
```
Yes. As mentioned above this can be fixed with a type alias.

```
package main

import "gonum.org/v1/gonum/mat"

type SymLinOp interface {
	mat.Symmetric
	MulVecTo(dst *mat.VecDense, _ bool, x mat.Vector)
}

type symmetric = mat.Symmetric

type SymmetricWrapper struct {
	symmetric
}

func (m *SymmetricWrapper) MulVecTo(dst *mat.VecDense, _ bool, x mat.Vector) {
	dst.MulVec(m, x)
}

func takesSymLinOp(s SymLinOp) {}

func main() {
	s := mat.NewSymDense(3, []float64{2, 1, 1, 0, 2, 1, 0, 0, 2})
	w := &SymmetricWrapper{s}
	takesSymLinOp(w)
}
```

This is clearly not ideal since it would need to be explained somewhere since it's probably not obvious to many people.

The alternative is similarly unpleasant in that is breaks the API (we already do this in the current phase of development, but this is — without hard data to back up the claim — probably likely to break more people than other breakages we've done recently). Despite that, I think that the pain of breakage once is likely to be less than the ongoing pain of explaining this in the future. Having said that, it does need to be discussed. Not least to figure out what a good name for the method would be (I suggested `SymDim` above, but that clashes with the naming convention of `Triangle` and `Bandwidth` for the triangular and banded matrix types both of which I think are good names). Some options:

- `SymDim`
- `SymmetricDim`
- `Size`
- `SymmetricSize`

None of these stand out as an obvious winner (_maybe_ `SymmetricDim`?)

/cc @vladimir-ch @btracey @sbinet 
`Symmetric` as a method that returns dimensions is confusing, I'm glad you are considering changing it! `SymDim` looks good to me, retains the sweet and short sound of `Dims()`. 
Is there a decision here? v0.10.0 is coming soon.
Sorry, I forgot about this one. `SymmetricDim` or `SymDim` both seem ok. In addition to those, how about `Symmetry`? By not having the `Dim` suffix it matches with `Triangle` or `Bandwidth`.
I like `Symmetry`. I'll send a PR.
Actually. Having second thoughts. Symmetry brings to mind the group theory context.
Sure, no problem, it was just an idea. `SymmetricDim` is good.
Do we want to do `Triangle`=>`TriangleDim` at the same time?

Fix patch:
diff --git a/diff/fd/hessian.go b/diff/fd/hessian.go
index 684b12803..80616b2b8 100644
--- a/diff/fd/hessian.go
+++ b/diff/fd/hessian.go
@@ -25,7 +25,7 @@ func Hessian(dst *mat.SymDense, f func(x []float64) float64, x []float64, settin
 	n := len(x)
 	if dst.IsEmpty() {
 		*dst = *(dst.GrowSym(n).(*mat.SymDense))
-	} else if dst.Symmetric() != n {
+	} else if dst.SymmetricDim() != n {
 		panic("hessian: dst size mismatch")
 	}
 	dst.Zero()
@@ -111,7 +111,7 @@ func hessianSerial(dst *mat.SymDense, f func(x []float64) float64, x []float64,
 }
 
 func hessianConcurrent(dst *mat.SymDense, nWorkers, evals int, f func(x []float64) float64, x []float64, stencil []Point, step float64, originKnown bool, originValue float64) {
-	n := dst.Symmetric()
+	n := dst.SymmetricDim()
 	type run struct {
 		i, j       int
 		iIdx, jIdx int
diff --git a/graph/simple/dense_undirected_matrix.go b/graph/simple/dense_undirected_matrix.go
index f51debb4f..209e2a1c9 100644
--- a/graph/simple/dense_undirected_matrix.go
+++ b/graph/simple/dense_undirected_matrix.go
@@ -107,7 +107,7 @@ func (g *UndirectedMatrix) From(id int64) graph.Nodes {
 		return graph.Empty
 	}
 	var nodes []graph.Node
-	r := g.mat.Symmetric()
+	r := g.mat.SymmetricDim()
 	for i := 0; i < r; i++ {
 		if int64(i) == id {
 			continue
@@ -161,7 +161,7 @@ func (g *UndirectedMatrix) Nodes() graph.Nodes {
 		copy(nodes, g.nodes)
 		return iterator.NewOrderedNodes(nodes)
 	}
-	r := g.mat.Symmetric()
+	r := g.mat.SymmetricDim()
 	// Matrix graphs must have at least one node.
 	return iterator.NewImplicitNodes(0, r, newSimpleNode)
 }
@@ -263,6 +263,6 @@ func (g *UndirectedMatrix) WeightedEdges() graph.WeightedEdges {
 }
 
 func (g *UndirectedMatrix) has(id int64) bool {
-	r := g.mat.Symmetric()
+	r := g.mat.SymmetricDim()
 	return 0 <= id && id < int64(r)
 }
diff --git a/mat/cholesky.go b/mat/cholesky.go
index 6f65d425e..92b42f568 100644
--- a/mat/cholesky.go
+++ b/mat/cholesky.go
@@ -90,7 +90,7 @@ func (c *Cholesky) At(i, j int) float64 {
 	if !c.valid() {
 		panic(badCholesky)
 	}
-	n := c.Symmetric()
+	n := c.SymmetricDim()
 	if uint(i) >= uint(n) {
 		panic(ErrRowAccess)
 	}
@@ -110,9 +110,9 @@ func (c *Cholesky) T() Matrix {
 	return c
 }
 
-// Symmetric implements the Symmetric interface and returns the number of rows
+// SymmetricDim implements the Symmetric interface and returns the number of rows
 // in the matrix (this is also the number of columns).
-func (c *Cholesky) Symmetric() int {
+func (c *Cholesky) SymmetricDim() int {
 	r, _ := c.chol.Dims()
 	return r
 }
@@ -129,7 +129,7 @@ func (c *Cholesky) Cond() float64 {
 // whether the matrix is positive definite. If Factorize returns false, the
 // factorization must not be used.
 func (c *Cholesky) Factorize(a Symmetric) (ok bool) {
-	n := a.Symmetric()
+	n := a.SymmetricDim()
 	if c.chol == nil {
 		c.chol = NewTriDense(n, Upper, nil)
 	} else {
@@ -193,7 +193,7 @@ func (c *Cholesky) Clone(chol *Cholesky) {
 	if !chol.valid() {
 		panic(badCholesky)
 	}
-	n := chol.Symmetric()
+	n := chol.SymmetricDim()
 	if c.chol == nil {
 		c.chol = NewTriDense(n, Upper, nil)
 	} else {
@@ -377,7 +377,7 @@ func (c *Cholesky) ToSym(dst *SymDense) {
 	if dst.IsEmpty() {
 		dst.ReuseAsSym(n)
 	} else {
-		n2 := dst.Symmetric()
+		n2 := dst.SymmetricDim()
 		if n != n2 {
 			panic(ErrShape)
 		}
@@ -458,7 +458,7 @@ func (c *Cholesky) Scale(f float64, orig *Cholesky) {
 	if f <= 0 {
 		panic("cholesky: scaling by a non-positive constant")
 	}
-	n := orig.Symmetric()
+	n := orig.SymmetricDim()
 	if c.chol == nil {
 		c.chol = NewTriDense(n, Upper, nil)
 	} else if c.chol.mat.N != n {
@@ -480,7 +480,7 @@ func (c *Cholesky) Scale(f float64, orig *Cholesky) {
 // ExtendVecSym will panic if v.Len() != a.Symmetric()+1 or if a does not contain
 // a valid decomposition.
 func (c *Cholesky) ExtendVecSym(a *Cholesky, v Vector) (ok bool) {
-	n := a.Symmetric()
+	n := a.SymmetricDim()
 
 	if v.Len() != n+1 {
 		panic(badSliceLength)
@@ -549,7 +549,7 @@ func (c *Cholesky) SymRankOne(orig *Cholesky, alpha float64, x Vector) (ok bool)
 	if !orig.valid() {
 		panic(badCholesky)
 	}
-	n := orig.Symmetric()
+	n := orig.SymmetricDim()
 	if r, c := x.Dims(); r != n || c != 1 {
 		panic(ErrShape)
 	}
@@ -872,9 +872,9 @@ func (ch *BandCholesky) TBand() Banded {
 	return ch
 }
 
-// Symmetric implements the Symmetric interface and returns the number of rows
+// SymmetricDim implements the Symmetric interface and returns the number of rows
 // in the matrix (this is also the number of columns).
-func (ch *BandCholesky) Symmetric() int {
+func (ch *BandCholesky) SymmetricDim() int {
 	n, _ := ch.chol.Triangle()
 	return n
 }
diff --git a/mat/diagonal.go b/mat/diagonal.go
index 7383d4390..0bcb7a109 100644
--- a/mat/diagonal.go
+++ b/mat/diagonal.go
@@ -54,10 +54,10 @@ type Diagonal interface {
 	Triangle() (int, TriKind)
 	TTri() Triangular
 
-	// Symmetric and SymBand are included in the Diagonal interface
+	// SymmetricDim and SymBand are included in the Diagonal interface
 	// to allow the use of Diagonal types in symmetric and banded symmetric
 	// functions respectively.
-	Symmetric() int
+	SymmetricDim() int
 	SymBand() (n, k int)
 
 	// TriBand and TTriBand are included in the Diagonal interface
@@ -137,8 +137,8 @@ func (d *DiagDense) Bandwidth() (kl, ku int) {
 	return 0, 0
 }
 
-// Symmetric implements the Symmetric interface.
-func (d *DiagDense) Symmetric() int {
+// SymmetricDim implements the Symmetric interface.
+func (d *DiagDense) SymmetricDim() int {
 	return d.mat.N
 }
 
diff --git a/mat/eigen.go b/mat/eigen.go
index a0485398a..85c56fc53 100644
--- a/mat/eigen.go
+++ b/mat/eigen.go
@@ -38,7 +38,7 @@ func (e *EigenSym) Factorize(a Symmetric, vectors bool) (ok bool) {
 	e.vectorsComputed = false
 	e.values = e.values[:]
 
-	n := a.Symmetric()
+	n := a.SymmetricDim()
 	sd := NewSymDense(n, nil)
 	sd.CopySym(a)
 
diff --git a/mat/symband.go b/mat/symband.go
index 30dc14432..6d7b00be1 100644
--- a/mat/symband.go
+++ b/mat/symband.go
@@ -36,8 +36,8 @@ type SymBandDense struct {
 type SymBanded interface {
 	Banded
 
-	// Symmetric returns the number of rows/columns in the matrix.
-	Symmetric() int
+	// SymmetricDim returns the number of rows/columns in the matrix.
+	SymmetricDim() int
 
 	// SymBand returns the number of rows/columns in the matrix, and the size of
 	// the bandwidth.
@@ -115,8 +115,8 @@ func (s *SymBandDense) Dims() (r, c int) {
 	return s.mat.N, s.mat.N
 }
 
-// Symmetric returns the size of the receiver.
-func (s *SymBandDense) Symmetric() int {
+// SymmetricDim returns the size of the receiver.
+func (s *SymBandDense) SymmetricDim() int {
 	return s.mat.N
 }
 
diff --git a/mat/symmetric.go b/mat/symmetric.go
index ec67af31a..ec9b75cf7 100644
--- a/mat/symmetric.go
+++ b/mat/symmetric.go
@@ -37,8 +37,8 @@ type SymDense struct {
 // the element at {j, i}). Symmetric matrices are always square.
 type Symmetric interface {
 	Matrix
-	// Symmetric returns the number of rows/columns in the matrix.
-	Symmetric() int
+	// SymmetricDim returns the number of rows/columns in the matrix.
+	SymmetricDim() int
 }
 
 // A RawSymmetricer can return a view of itself as a BLAS Symmetric matrix.
@@ -100,9 +100,9 @@ func (s *SymDense) T() Matrix {
 	return s
 }
 
-// Symmetric implements the Symmetric interface and returns the number of rows
+// SymmetricDim implements the Symmetric interface and returns the number of rows
 // and columns in the matrix.
-func (s *SymDense) Symmetric() int {
+func (s *SymDense) SymmetricDim() int {
 	return s.mat.N
 }
 
@@ -234,7 +234,7 @@ func (s *SymDense) reuseAsZeroed(n int) {
 }
 
 func (s *SymDense) isolatedWorkspace(a Symmetric) (w *SymDense, restore func()) {
-	n := a.Symmetric()
+	n := a.SymmetricDim()
 	if n == 0 {
 		panic(ErrZeroLength)
 	}
@@ -258,8 +258,8 @@ func (s *SymDense) DiagView() Diagonal {
 }
 
 func (s *SymDense) AddSym(a, b Symmetric) {
-	n := a.Symmetric()
-	if n != b.Symmetric() {
+	n := a.SymmetricDim()
+	if n != b.SymmetricDim() {
 		panic(ErrShape)
 	}
 	s.reuseAsNonZeroed(n)
@@ -295,7 +295,7 @@ func (s *SymDense) AddSym(a, b Symmetric) {
 }
 
 func (s *SymDense) CopySym(a Symmetric) int {
-	n := a.Symmetric()
+	n := a.SymmetricDim()
 	n = min(n, s.mat.N)
 	if n == 0 {
 		return 0
@@ -325,7 +325,7 @@ func (s *SymDense) CopySym(a Symmetric) int {
 //  s = a + alpha * x * xᵀ
 func (s *SymDense) SymRankOne(a Symmetric, alpha float64, x Vector) {
 	n := x.Len()
-	if a.Symmetric() != n {
+	if a.SymmetricDim() != n {
 		panic(ErrShape)
 	}
 	s.reuseAsNonZeroed(n)
@@ -357,7 +357,7 @@ func (s *SymDense) SymRankOne(a Symmetric, alpha float64, x Vector) {
 // result into the receiver. If a is zero, see SymOuterK.
 //  s = a + alpha * x * x'
 func (s *SymDense) SymRankK(a Symmetric, alpha float64, x Matrix) {
-	n := a.Symmetric()
+	n := a.SymmetricDim()
 	r, _ := x.Dims()
 	if r != n {
 		panic(ErrShape)
@@ -495,7 +495,7 @@ func (s *SymDense) RankTwo(a Symmetric, alpha float64, x, y Vector) {
 
 // ScaleSym multiplies the elements of a by f, placing the result in the receiver.
 func (s *SymDense) ScaleSym(f float64, a Symmetric) {
-	n := a.Symmetric()
+	n := a.SymmetricDim()
 	s.reuseAsNonZeroed(n)
 	if a, ok := a.(RawSymmetricer); ok {
 		amat := a.RawSymmetric()
@@ -523,7 +523,7 @@ func (s *SymDense) ScaleSym(f float64, a Symmetric) {
 // have to be a strict subset, dimension repeats are allowed.
 func (s *SymDense) SubsetSym(a Symmetric, set []int) {
 	n := len(set)
-	na := a.Symmetric()
+	na := a.SymmetricDim()
 	s.reuseAsNonZeroed(n)
 	var restore func()
 	if a == s {
@@ -663,7 +663,7 @@ func (s *SymDense) GrowSym(n int) Symmetric {
 // PowPSD returns an error if the matrix is not positive symmetric definite
 // or the Eigen decomposition is not successful.
 func (s *SymDense) PowPSD(a Symmetric, pow float64) error {
-	dim := a.Symmetric()
+	dim := a.SymmetricDim()
 	s.reuseAsNonZeroed(dim)
 
 	var eigen EigenSym
diff --git a/mat/triangular.go b/mat/triangular.go
index 39db932aa..581b5d8de 100644
--- a/mat/triangular.go
+++ b/mat/triangular.go
@@ -659,7 +659,7 @@ func (t *TriDense) Trace() float64 {
 // copySymIntoTriangle copies a symmetric matrix into a TriDense
 func copySymIntoTriangle(t *TriDense, s Symmetric) {
 	n, upper := t.Triangle()
-	ns := s.Symmetric()
+	ns := s.SymmetricDim()
 	if n != ns {
 		panic("mat: triangle size mismatch")
 	}
diff --git a/optimize/cmaes.go b/optimize/cmaes.go
index ce0b86cdf..9c51211d1 100644
--- a/optimize/cmaes.go
+++ b/optimize/cmaes.go
@@ -206,7 +206,7 @@ func (cma *CmaEsChol) Init(dim, tasks int) int {
 	cma.mean = resize(cma.mean, dim) // mean location initialized at the start of Run
 
 	if cma.InitCholesky != nil {
-		if cma.InitCholesky.Symmetric() != dim {
+		if cma.InitCholesky.SymmetricDim() != dim {
 			panic("cma-es-chol: incorrect InitCholesky size")
 		}
 		cma.chol.Clone(cma.InitCholesky)
diff --git a/optimize/functions/functions.go b/optimize/functions/functions.go
index 84c5e8fe8..9a32c74a7 100644
--- a/optimize/functions/functions.go
+++ b/optimize/functions/functions.go
@@ -60,7 +60,7 @@ func (Beale) Hess(dst *mat.SymDense, x []float64) {
 	if len(x) != 2 {
 		panic("dimension of the problem must be 2")
 	}
-	if len(x) != dst.Symmetric() {
+	if len(x) != dst.SymmetricDim() {
 		panic("incorrect size of the Hessian")
 	}
 
@@ -562,7 +562,7 @@ func (BrownBadlyScaled) Hess(dst *mat.SymDense, x []float64) {
 	if len(x) != 2 {
 		panic("dimension of the problem must be 2")
 	}
-	if len(x) != dst.Symmetric() {
+	if len(x) != dst.SymmetricDim() {
 		panic("incorrect size of the Hessian")
 	}
 
@@ -639,7 +639,7 @@ func (BrownAndDennis) Hess(dst *mat.SymDense, x []float64) {
 	if len(x) != 4 {
 		panic("dimension of the problem must be 4")
 	}
-	if len(x) != dst.Symmetric() {
+	if len(x) != dst.SymmetricDim() {
 		panic("incorrect size of the Hessian")
 	}
 
@@ -1274,7 +1274,7 @@ func (PowellBadlyScaled) Hess(dst *mat.SymDense, x []float64) {
 	if len(x) != 2 {
 		panic("dimension of the problem must be 2")
 	}
-	if len(x) != dst.Symmetric() {
+	if len(x) != dst.SymmetricDim() {
 		panic("incorrect size of the Hessian")
 	}
 
@@ -1522,7 +1522,7 @@ func (Watson) Grad(grad, x []float64) {
 
 func (Watson) Hess(dst *mat.SymDense, x []float64) {
 	dim := len(x)
-	if len(x) != dst.Symmetric() {
+	if len(x) != dst.SymmetricDim() {
 		panic("incorrect size of the Hessian")
 	}
 
@@ -1644,7 +1644,7 @@ func (Wood) Hess(dst *mat.SymDense, x []float64) {
 	if len(x) != 4 {
 		panic("dimension of the problem must be 4")
 	}
-	if len(x) != dst.Symmetric() {
+	if len(x) != dst.SymmetricDim() {
 		panic("incorrect size of the Hessian")
 	}
 
diff --git a/optimize/minimize.go b/optimize/minimize.go
index 60594fc9e..7c1f3ff37 100644
--- a/optimize/minimize.go
+++ b/optimize/minimize.go
@@ -447,7 +447,7 @@ func getInitLocation(dim int, initX []float64, initValues *Location) (Operation,
 		op |= GradEvaluation
 	}
 	if initValues.Hessian != nil {
-		if initValues.Hessian.Symmetric() != dim {
+		if initValues.Hessian.SymmetricDim() != dim {
 			panic("optimize: initial Hessian does not match problem dimension")
 		}
 		loc.Hessian = initValues.Hessian
diff --git a/stat/distmat/wishart.go b/stat/distmat/wishart.go
index e498d9444..d89d3ef95 100644
--- a/stat/distmat/wishart.go
+++ b/stat/distmat/wishart.go
@@ -44,7 +44,7 @@ type Wishart struct {
 //
 // NewWishart panics if nu <= d - 1 where d is the order of v.
 func NewWishart(v mat.Symmetric, nu float64, src rand.Source) (*Wishart, bool) {
-	dim := v.Symmetric()
+	dim := v.SymmetricDim()
 	if nu <= float64(dim-1) {
 		panic("wishart: nu must be greater than dim-1")
 	}
@@ -75,7 +75,7 @@ func NewWishart(v mat.Symmetric, nu float64, src rand.Source) (*Wishart, bool) {
 func (w *Wishart) MeanSymTo(dst *mat.SymDense) {
 	if dst.IsEmpty() {
 		dst.ReuseAsSym(w.dim)
-	} else if dst.Symmetric() != w.dim {
+	} else if dst.SymmetricDim() != w.dim {
 		panic(badDim)
 	}
 	w.setV()
@@ -94,7 +94,7 @@ func (w *Wishart) ProbSym(x mat.Symmetric) float64 {
 // LogProbSym returns -∞ if the input matrix is not positive definite (the Cholesky
 // decomposition fails).
 func (w *Wishart) LogProbSym(x mat.Symmetric) float64 {
-	dim := x.Symmetric()
+	dim := x.SymmetricDim()
 	if dim != w.dim {
 		panic(badDim)
 	}
@@ -109,7 +109,7 @@ func (w *Wishart) LogProbSym(x mat.Symmetric) float64 {
 // LogProbSymChol returns the log of the probability of the input symmetric matrix
 // given its Cholesky decomposition.
 func (w *Wishart) LogProbSymChol(cholX *mat.Cholesky) float64 {
-	dim := cholX.Symmetric()
+	dim := cholX.SymmetricDim()
 	if dim != w.dim {
 		panic(badDim)
 	}
diff --git a/stat/distmv/dirichlet.go b/stat/distmv/dirichlet.go
index f6663438c..e4b01537b 100644
--- a/stat/distmv/dirichlet.go
+++ b/stat/distmv/dirichlet.go
@@ -66,7 +66,7 @@ func NewDirichlet(alpha []float64, src rand.Source) *Dirichlet {
 func (d *Dirichlet) CovarianceMatrix(dst *mat.SymDense) {
 	if dst.IsEmpty() {
 		*dst = *(dst.GrowSym(d.dim).(*mat.SymDense))
-	} else if dst.Symmetric() != d.dim {
+	} else if dst.SymmetricDim() != d.dim {
 		panic("dirichelet: input matrix size mismatch")
 	}
 	scale := 1 / (d.sumAlpha * d.sumAlpha * (d.sumAlpha + 1))
diff --git a/stat/distmv/normal.go b/stat/distmv/normal.go
index aad27dad0..58c2ea3fb 100644
--- a/stat/distmv/normal.go
+++ b/stat/distmv/normal.go
@@ -43,7 +43,7 @@ func NewNormal(mu []float64, sigma mat.Symmetric, src rand.Source) (*Normal, boo
 	if len(mu) == 0 {
 		panic(badZeroDimension)
 	}
-	dim := sigma.Symmetric()
+	dim := sigma.SymmetricDim()
 	if dim != len(mu) {
 		panic(badSizeMismatch)
 	}
@@ -69,7 +69,7 @@ func NewNormal(mu []float64, sigma mat.Symmetric, src rand.Source) (*Normal, boo
 // panics if len(mu) is not equal to chol.Size().
 func NewNormalChol(mu []float64, chol *mat.Cholesky, src rand.Source) *Normal {
 	dim := len(mu)
-	if dim != chol.Symmetric() {
+	if dim != chol.SymmetricDim() {
 		panic(badSizeMismatch)
 	}
 	n := &Normal{
@@ -93,7 +93,7 @@ func NewNormalPrecision(mu []float64, prec *mat.SymDense, src rand.Source) (norm
 	if len(mu) == 0 {
 		panic(badZeroDimension)
 	}
-	dim := prec.Symmetric()
+	dim := prec.SymmetricDim()
 	if dim != len(mu) {
 		panic(badSizeMismatch)
 	}
@@ -161,7 +161,7 @@ func (n *Normal) ConditionNormal(observed []int, values []float64, src rand.Sour
 func (n *Normal) CovarianceMatrix(dst *mat.SymDense) {
 	if dst.IsEmpty() {
 		*dst = *(dst.GrowSym(n.dim).(*mat.SymDense))
-	} else if dst.Symmetric() != n.dim {
+	} else if dst.SymmetricDim() != n.dim {
 		panic("normal: input matrix size mismatch")
 	}
 	dst.CopySym(&n.sigma)
@@ -197,7 +197,7 @@ func NormalLogProb(x, mu []float64, chol *mat.Cholesky) float64 {
 	if len(x) != dim {
 		panic(badSizeMismatch)
 	}
-	if chol.Symmetric() != dim {
+	if chol.SymmetricDim() != dim {
 		panic(badSizeMismatch)
 	}
 	logSqrtDet := 0.5 * chol.LogDet()
@@ -301,7 +301,7 @@ func (n *Normal) Rand(x []float64) []float64 {
 // available. Otherwise, the NewNormal function should be used.
 func NormalRand(x, mean []float64, chol *mat.Cholesky, src rand.Source) []float64 {
 	x = reuseAs(x, len(mean))
-	if len(mean) != chol.Symmetric() {
+	if len(mean) != chol.SymmetricDim() {
 		panic(badInputLength)
 	}
 	if src == nil {
diff --git a/stat/distmv/studentst.go b/stat/distmv/studentst.go
index 24410352f..a381cb6fa 100644
--- a/stat/distmv/studentst.go
+++ b/stat/distmv/studentst.go
@@ -55,7 +55,7 @@ func NewStudentsT(mu []float64, sigma mat.Symmetric, nu float64, src rand.Source
 	if len(mu) == 0 {
 		panic(badZeroDimension)
 	}
-	dim := sigma.Symmetric()
+	dim := sigma.SymmetricDim()
 	if dim != len(mu) {
 		panic(badSizeMismatch)
 	}
@@ -231,7 +231,7 @@ func findUnob(observed []int, dim int) (unobserved []int) {
 func (st *StudentsT) CovarianceMatrix(dst *mat.SymDense) {
 	if dst.IsEmpty() {
 		*dst = *(dst.GrowSym(st.dim).(*mat.SymDense))
-	} else if dst.Symmetric() != st.dim {
+	} else if dst.SymmetricDim() != st.dim {
 		panic("studentst: input matrix size mismatch")
 	}
 	dst.CopySym(&st.sigma)
diff --git a/stat/mds/mds.go b/stat/mds/mds.go
index 2faa3d1d1..c8ecefeec 100644
--- a/stat/mds/mds.go
+++ b/stat/mds/mds.go
@@ -24,7 +24,7 @@ import (
 func TorgersonScaling(dst *mat.Dense, eigdst []float64, dis mat.Symmetric) (k int, eig []float64) {
 	// https://doi.org/10.1007/0-387-28981-X_12
 
-	n := dis.Symmetric()
+	n := dis.SymmetricDim()
 	if dst.IsEmpty() {
 		dst.ReuseAs(n, n)
 	} else {
diff --git a/stat/samplemv/metropolishastings.go b/stat/samplemv/metropolishastings.go
index ad09fa380..00a4f212f 100644
--- a/stat/samplemv/metropolishastings.go
+++ b/stat/samplemv/metropolishastings.go
@@ -173,7 +173,7 @@ type ProposalNormal struct {
 //
 // NewProposalNormal returns {nil, false} if the covariance matrix is not positive-definite.
 func NewProposalNormal(sigma *mat.SymDense, src rand.Source) (*ProposalNormal, bool) {
-	mu := make([]float64, sigma.Symmetric())
+	mu := make([]float64, sigma.SymmetricDim())
 	normal, ok := distmv.NewNormal(mu, sigma, src)
 	if !ok {
 		return nil, false
diff --git a/stat/statmat.go b/stat/statmat.go
index 3dbcd1d2a..06fcd93de 100644
--- a/stat/statmat.go
+++ b/stat/statmat.go
@@ -29,7 +29,7 @@ func CovarianceMatrix(dst *mat.SymDense, x mat.Matrix, weights []float64) {
 
 	if dst.IsEmpty() {
 		*dst = *(dst.GrowSym(c).(*mat.SymDense))
-	} else if n := dst.Symmetric(); n != c {
+	} else if n := dst.SymmetricDim(); n != c {
 		panic(mat.ErrShape)
 	}
 
@@ -86,7 +86,7 @@ func CorrelationMatrix(dst *mat.SymDense, x mat.Matrix, weights []float64) {
 
 // covToCorr converts a covariance matrix to a correlation matrix.
 func covToCorr(c *mat.SymDense) {
-	r := c.Symmetric()
+	r := c.SymmetricDim()
 
 	s := make([]float64, r)
 	for i := 0; i < r; i++ {


Test patch:
diff --git a/diff/fd/watson_test.go b/diff/fd/watson_test.go
index 243a450b6..b115528c7 100644
--- a/diff/fd/watson_test.go
+++ b/diff/fd/watson_test.go
@@ -86,7 +86,7 @@ func (Watson) Grad(grad, x []float64) {
 
 func (Watson) Hess(hess mat.MutableSymmetric, x []float64) {
 	dim := len(x)
-	if dim != hess.Symmetric() {
+	if dim != hess.SymmetricDim() {
 		panic("incorrect size of the Hessian")
 	}
 
diff --git a/mat/basictypes_test.go b/mat/basictypes_test.go
index 22970e6ac..1dfd75415 100644
--- a/mat/basictypes_test.go
+++ b/mat/basictypes_test.go
@@ -56,7 +56,7 @@ var _ Symmetric = &basicSymmetric{}
 func (m *basicSymmetric) At(r, c int) float64 { return (*SymDense)(m).At(r, c) }
 func (m *basicSymmetric) Dims() (r, c int)    { return (*SymDense)(m).Dims() }
 func (m *basicSymmetric) T() Matrix           { return m }
-func (m *basicSymmetric) Symmetric() int      { return (*SymDense)(m).Symmetric() }
+func (m *basicSymmetric) SymmetricDim() int   { return (*SymDense)(m).SymmetricDim() }
 
 type basicTriangular TriDense
 
@@ -87,7 +87,7 @@ func (m *basicSymBanded) Dims() (r, c int)        { return (*SymBandDense)(m).Di
 func (m *basicSymBanded) T() Matrix               { return m }
 func (m *basicSymBanded) Bandwidth() (kl, ku int) { return (*SymBandDense)(m).Bandwidth() }
 func (m *basicSymBanded) TBand() Banded           { return m }
-func (m *basicSymBanded) Symmetric() int          { return (*SymBandDense)(m).Symmetric() }
+func (m *basicSymBanded) SymmetricDim() int       { return (*SymBandDense)(m).SymmetricDim() }
 func (m *basicSymBanded) SymBand() (n, k int)     { return (*SymBandDense)(m).SymBand() }
 
 type basicTriBanded TriBandDense
@@ -112,7 +112,7 @@ func (m *basicDiagonal) At(r, c int) float64               { return (*DiagDense)
 func (m *basicDiagonal) Dims() (r, c int)                  { return (*DiagDense)(m).Dims() }
 func (m *basicDiagonal) T() Matrix                         { return Transpose{m} }
 func (m *basicDiagonal) Diag() int                         { return (*DiagDense)(m).Diag() }
-func (m *basicDiagonal) Symmetric() int                    { return (*DiagDense)(m).Symmetric() }
+func (m *basicDiagonal) SymmetricDim() int                 { return (*DiagDense)(m).SymmetricDim() }
 func (m *basicDiagonal) SymBand() (n, k int)               { return (*DiagDense)(m).SymBand() }
 func (m *basicDiagonal) Bandwidth() (kl, ku int)           { return (*DiagDense)(m).Bandwidth() }
 func (m *basicDiagonal) TBand() Banded                     { return TransposeBand{m} }
diff --git a/mat/cholesky_test.go b/mat/cholesky_test.go
index c5a87b792..d535d5e85 100644
--- a/mat/cholesky_test.go
+++ b/mat/cholesky_test.go
@@ -89,8 +89,8 @@ func TestCholeskyAt(t *testing.T) {
 		if !ok {
 			t.Fatalf("Matrix not positive definite")
 		}
-		n := test.Symmetric()
-		cn := chol.Symmetric()
+		n := test.SymmetricDim()
+		cn := chol.SymmetricDim()
 		if cn != n {
 			t.Errorf("Cholesky size does not match. Got %d, want %d", cn, n)
 		}
@@ -516,7 +516,7 @@ func TestCholeskyExtendVecSym(t *testing.T) {
 			}),
 		},
 	} {
-		n := test.a.Symmetric()
+		n := test.a.SymmetricDim()
 		as := test.a.sliceSym(0, n-1)
 
 		// Compute the full factorization to use later (do the full factorization
diff --git a/mat/list_test.go b/mat/list_test.go
index c821bc54d..ba813ebdf 100644
--- a/mat/list_test.go
+++ b/mat/list_test.go
@@ -765,7 +765,7 @@ func makeCopyOf(a Matrix) Matrix {
 		m.CloneFrom(a)
 		return returnAs(&m, t)
 	case *SymDense, *basicSymmetric:
-		n := t.(Symmetric).Symmetric()
+		n := t.(Symmetric).SymmetricDim()
 		m := NewSymDense(n, nil)
 		m.CopySym(t.(Symmetric))
 		return returnAs(m, t)
diff --git a/mat/symmetric_test.go b/mat/symmetric_test.go
index 3c9d4cb80..af95d7635 100644
--- a/mat/symmetric_test.go
+++ b/mat/symmetric_test.go
@@ -659,7 +659,7 @@ func TestViewGrowSquare(t *testing.T) {
 
 		// Grow the matrix back to the original view
 		gn := n - start1 - start2
-		g := v2.GrowSym(gn - v2.Symmetric()).(*SymDense)
+		g := v2.GrowSym(gn - v2.SymmetricDim()).(*SymDense)
 		g.SetSym(1, 1, 2.2)
 
 		for i := 0; i < gn; i++ {
diff --git a/stat/distmat/wishart_test.go b/stat/distmat/wishart_test.go
index a604f8181..cc7e686cd 100644
--- a/stat/distmat/wishart_test.go
+++ b/stat/distmat/wishart_test.go
@@ -111,7 +111,7 @@ func TestWishartRand(t *testing.T) {
 		},
 	} {
 		rnd := rand.New(rand.NewSource(1))
-		dim := test.v.Symmetric()
+		dim := test.v.SymmetricDim()
 		w, ok := NewWishart(test.v, test.nu, rnd)
 		if !ok {
 			panic("bad test")
diff --git a/stat/distmv/general_test.go b/stat/distmv/general_test.go
index 8d75fc502..4f7c5c100 100644
--- a/stat/distmv/general_test.go
+++ b/stat/distmv/general_test.go
@@ -77,7 +77,7 @@ type Cover interface {
 func checkCov(t *testing.T, cas int, x *mat.Dense, c Cover, tol float64) {
 	var cov mat.SymDense
 	c.CovarianceMatrix(&cov)
-	n := cov.Symmetric()
+	n := cov.SymmetricDim()
 	cov2 := mat.NewSymDense(n, nil)
 	c.CovarianceMatrix(cov2)
 	if !mat.Equal(&cov, cov2) {
diff --git a/stat/distmv/normal_test.go b/stat/distmv/normal_test.go
index 6a676501c..7302cdc4e 100644
--- a/stat/distmv/normal_test.go
+++ b/stat/distmv/normal_test.go
@@ -399,7 +399,7 @@ func TestCovarianceMatrix(t *testing.T) {
 		if !mat.EqualApprox(&cov, test.sigma, 1e-14) {
 			t.Errorf("Covariance mismatch with nil input")
 		}
-		dim := test.sigma.Symmetric()
+		dim := test.sigma.SymmetricDim()
 		cov = *mat.NewSymDense(dim, nil)
 		normal.CovarianceMatrix(&cov)
 		if !mat.EqualApprox(&cov, test.sigma, 1e-14) {
diff --git a/stat/statmat_test.go b/stat/statmat_test.go
index aa92ef224..e70ed6f2e 100644
--- a/stat/statmat_test.go
+++ b/stat/statmat_test.go
@@ -244,7 +244,7 @@ func TestCorrCov(t *testing.T) {
 		CorrelationMatrix(&corr, test.data, test.weights)
 		CovarianceMatrix(&cov, test.data, test.weights)
 
-		r := cov.Symmetric()
+		r := cov.SymmetricDim()
 
 		// Get the diagonal elements from cov to determine the sigmas.
 		sigmas := make([]float64, r)
@@ -252,11 +252,11 @@ func TestCorrCov(t *testing.T) {
 			sigmas[i] = math.Sqrt(cov.At(i, i))
 		}
 
-		covFromCorr := mat.NewSymDense(corr.Symmetric(), nil)
+		covFromCorr := mat.NewSymDense(corr.SymmetricDim(), nil)
 		covFromCorr.CopySym(&corr)
 		corrToCov(covFromCorr, sigmas)
 
-		corrFromCov := mat.NewSymDense(cov.Symmetric(), nil)
+		corrFromCov := mat.NewSymDense(cov.SymmetricDim(), nil)
 		corrFromCov.CopySym(&cov)
 		covToCorr(corrFromCov)
 
@@ -450,7 +450,7 @@ func BenchmarkCovToCorr(b *testing.B) {
 	m := randMat(small, small)
 	var cov mat.SymDense
 	CovarianceMatrix(&cov, m, nil)
-	cc := mat.NewSymDense(cov.Symmetric(), nil)
+	cc := mat.NewSymDense(cov.SymmetricDim(), nil)
 	b.ResetTimer()
 	for i := 0; i < b.N; i++ {
 		b.StopTimer()
@@ -465,7 +465,7 @@ func BenchmarkCorrToCov(b *testing.B) {
 	m := randMat(small, small)
 	var corr mat.SymDense
 	CorrelationMatrix(&corr, m, nil)
-	cc := mat.NewSymDense(corr.Symmetric(), nil)
+	cc := mat.NewSymDense(corr.SymmetricDim(), nil)
 	sigma := make([]float64, small)
 	for i := range sigma {
 		sigma[i] = 2