mat: change factorization inputs to use bit types
* mat: change factorization inputs to use bit types
Fixes and
MODIFY
mat/eigen.go
mat/eigen.go
@@ -104,12 +104,25 @@ func (m *Dense) EigenvectorsSym(e *EigenSym) {
m.Copy(e.vectors)
}
+// EigenKind specifies the computation of eigenvectors during factorization.
+type EigenKind int
+
+const (
+ // EigenNone specifies to not compute any eigenvectors.
+ EigenNone EigenKind = 0
+ // EigenLeft specifies to compute the left eigenvectors.
+ EigenLeft EigenKind = 1 << iota
+ // EigenRight specifies to compute the right eigenvectors.
+ EigenRight
+ // EigenBoth is a convenience value for computing both eigenvectors.
+ EigenBoth EigenKind = EigenLeft | EigenRight
+)
+
// Eigen is a type for creating and using the eigenvalue decomposition of a dense matrix.
type Eigen struct {
n int // The size of the factorized matrix.
- right bool // have the right eigenvectors been computed
- left bool // have the left eigenvectors been computed
+ kind EigenKind
values []complex128
rVectors *CDense
@@ -118,7 +131,7 @@ type Eigen struct {
// succFact returns whether the receiver contains a successful factorization.
func (e *Eigen) succFact() bool {
- return len(e.values) != 0
+ return e.n != 0
}
// Factorize computes the eigenvalues of the square matrix a, and optionally
@@ -135,13 +148,17 @@ func (e *Eigen) succFact() bool {
//
// Typically eigenvectors refer to right eigenvectors.
//
-// In all cases, Factorize computes the eigenvalues of the matrix. If right and left
-// are true, then the right and left eigenvectors will be computed, respectively.
+// In all cases, Factorize computes the eigenvalues of the matrix. kind
+// specifies which of the eigenvectors, if any, to compute. See the EigenKind
+// documentation for more information.
// Eigen panics if the input matrix is not square.
//
// Factorize returns whether the decomposition succeeded. If the decomposition
// failed, methods that require a successful factorization will panic.
-func (e *Eigen) Factorize(a Matrix, left, right bool) (ok bool) {
+func (e *Eigen) Factorize(a Matrix, kind EigenKind) (ok bool) {
+ // kill previous factorization.
+ e.n = 0
+ e.kind = 0
// Copy a because it is modified during the Lapack call.
r, c := a.Dims()
if r != c {
@@ -150,6 +167,9 @@ func (e *Eigen) Factorize(a Matrix, left, right bool) (ok bool) {
var sd Dense
sd.Clone(a)
+ left := kind&EigenLeft != 0
+ right := kind&EigenRight != 0
+
var vl, vr Dense
jobvl := lapack.LeftEVNone
jobvr := lapack.RightEVNone
@@ -183,8 +203,7 @@ func (e *Eigen) Factorize(a Matrix, left, right bool) (ok bool) {
return false
}
e.n = r
- e.right = right
- e.left = left
+ e.kind = kind
// Construct complex eigenvalues from float64 data.
values := make([]complex128, r)
@@ -212,6 +231,15 @@ func (e *Eigen) Factorize(a Matrix, left, right bool) (ok bool) {
return true
}
+// Kind returns the EigenKind of the decomposition. If no decomposition has been
+// computed, Kind returns -1.
+func (e *Eigen) Kind() EigenKind {
+ if !e.succFact() {
+ return -1
+ }
+ return e.kind
+}
+
// Values extracts the eigenvalues of the factorized matrix. If dst is
// non-nil, the values are stored in-place into dst. In this case
// dst must have length n, otherwise Values will panic. If dst is
@@ -281,7 +309,7 @@ func (e *Eigen) VectorsTo(dst *CDense) *CDense {
if !e.succFact() {
panic(badFact)
}
- if !e.right {
+ if e.kind&EigenRight == 0 {
panic(badNoVect)
}
if dst == nil {
@@ -303,7 +331,7 @@ func (e *Eigen) LeftVectorsTo(dst *CDense) *CDense {
if !e.succFact() {
panic(badFact)
}
- if !e.left {
+ if e.kind&EigenLeft == 0 {
panic(badNoVect)
}
if dst == nil {

MODIFY
mat/eigen_example_test.go
mat/eigen_example_test.go
@@ -50,7 +50,7 @@ func ExampleEigen() {
fmt.Printf("A = %v\n\n", mat.Formatted(a, mat.Prefix(" ")))
var eig mat.Eigen
- ok := eig.Factorize(a, true, false)
+ ok := eig.Factorize(a, mat.EigenLeft)
if !ok {
log.Fatal("Eigendecomposition failed")
}

MODIFY
mat/eigen_test.go
mat/eigen_test.go
@@ -63,13 +63,13 @@ func TestEigen(t *testing.T) {
},
} {
var e1, e2, e3, e4 Eigen
- ok := e1.Factorize(test.a, true, true)
+ ok := e1.Factorize(test.a, EigenBoth)
if !ok {
panic("bad factorization")
}
- e2.Factorize(test.a, false, true)
- e3.Factorize(test.a, true, false)
- e4.Factorize(test.a, false, false)
+ e2.Factorize(test.a, EigenRight)
+ e3.Factorize(test.a, EigenLeft)
+ e4.Factorize(test.a, EigenNone)
v1 := e1.Values(nil)
if !cmplxEqualTol(v1, test.values, 1e-14) {

mat: change factorization inputs to use bit types (#872)

* mat: change factorization inputs to use bit types

Fixes #756 and #748.