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.
10 "golang.org/x/exp/rand"
12 "gonum.org/v1/gonum/floats"
15 func TestEigen(t *testing.T) {
16 for i, test := range []struct {
24 a: NewDense(3, 3, []float64{
29 values: []complex128{1, 1, 1},
30 left: NewDense(3, 3, []float64{
35 right: NewDense(3, 3, []float64{
42 var e1, e2, e3, e4 Eigen
43 ok := e1.Factorize(test.a, true, true)
45 panic("bad factorization")
47 e2.Factorize(test.a, false, true)
48 e3.Factorize(test.a, true, false)
49 e4.Factorize(test.a, false, false)
52 if !cmplxEqual(v1, test.values) {
53 t.Errorf("eigenvector mismatch. Case %v", i)
55 if !Equal(e1.LeftVectors(), test.left) {
56 t.Errorf("left eigenvector mismatch. Case %v", i)
58 if !Equal(e1.Vectors(), test.right) {
59 t.Errorf("right eigenvector mismatch. Case %v", i)
62 // Check that the eigenvectors and values are the same in all combinations.
63 if !cmplxEqual(v1, e2.Values(nil)) {
64 t.Errorf("eigenvector mismatch. Case %v", i)
66 if !cmplxEqual(v1, e3.Values(nil)) {
67 t.Errorf("eigenvector mismatch. Case %v", i)
69 if !cmplxEqual(v1, e4.Values(nil)) {
70 t.Errorf("eigenvector mismatch. Case %v", i)
72 if !Equal(e1.Vectors(), e2.Vectors()) {
73 t.Errorf("right eigenvector mismatch. Case %v", i)
75 if !Equal(e1.LeftVectors(), e3.LeftVectors()) {
76 t.Errorf("right eigenvector mismatch. Case %v", i)
79 // TODO(btracey): Also add in a test for correctness when #308 is
80 // resolved and we have a CMat.Mul().
84 func cmplxEqual(v1, v2 []complex128) bool {
85 for i, v := range v1 {
93 func TestSymEigen(t *testing.T) {
94 // Hand coded tests with results from lapack.
95 for _, test := range []struct {
102 mat: NewSymDense(3, []float64{8, 2, 4, 2, 6, 10, 4, 10, 5}),
103 values: []float64{-4.707679201365891, 6.294580208480216, 17.413098992885672},
104 vectors: NewDense(3, 3, []float64{
105 -0.127343483135656, -0.902414161226903, -0.411621572466779,
106 -0.664177720955769, 0.385801900032553, -0.640331827193739,
107 0.736648893495999, 0.191847792659746, -0.648492738712395,
112 ok := es.Factorize(test.mat, true)
114 t.Errorf("bad factorization")
116 if !floats.EqualApprox(test.values, es.values, 1e-14) {
117 t.Errorf("Eigenvalue mismatch")
119 if !EqualApprox(test.vectors, es.vectors, 1e-14) {
120 t.Errorf("Eigenvector mismatch")
124 es2.Factorize(test.mat, false)
125 if !floats.EqualApprox(es2.values, es.values, 1e-14) {
126 t.Errorf("Eigenvalue mismatch when no vectors computed")
131 rnd := rand.New(rand.NewSource(1))
132 for _, n := range []int{3, 5, 10, 70} {
133 for cas := 0; cas < 10; cas++ {
134 a := make([]float64, n*n)
136 a[i] = rnd.NormFloat64()
138 s := NewSymDense(n, a)
140 ok := es.Factorize(s, true)
145 // Check that the eigenvectors are orthonormal.
146 if !isOrthonormal(es.vectors, 1e-8) {
147 t.Errorf("Eigenvectors not orthonormal")
150 // Check that the eigenvalues are actually eigenvalues.
151 for i := 0; i < n; i++ {
152 v := NewVecDense(n, Col(nil, i, es.vectors))
157 scal.ScaleVec(es.values[i], v)
159 if !EqualApprox(&m, &scal, 1e-8) {
160 t.Errorf("Eigenvalue does not match")