1 // Copyright ©2016 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.
12 "golang.org/x/exp/rand"
14 "gonum.org/v1/gonum/floats"
17 type Dsterfer interface {
19 Dsterf(n int, d, e []float64) (ok bool)
22 func DsterfTest(t *testing.T, impl Dsterfer) {
24 for cas, test := range []struct {
31 // Computed from Fortran code.
33 d: []float64{1, 3, 4, 6},
34 e: []float64{2, 4, 5},
36 ans: []float64{11.046227528488854, 4.795922173417400, -2.546379458290125, 0.704229756383872},
40 d := make([]float64, len(test.d))
42 e := make([]float64, len(test.e))
44 ok := impl.Dsterf(n, d, e)
46 t.Errorf("Case %d, Eigenvalue decomposition failed", cas)
49 ans := make([]float64, len(test.ans))
52 if !floats.EqualApprox(ans, d, 1e-10) {
53 t.Errorf("eigenvalue mismatch")
57 rnd := rand.New(rand.NewSource(1))
58 // Probabilistic tests.
59 for _, n := range []int{4, 6, 10} {
60 for cas := 0; cas < 10; cas++ {
61 d := make([]float64, n)
63 d[i] = rnd.NormFloat64()
65 dCopy := make([]float64, len(d))
67 e := make([]float64, n-1)
69 e[i] = rnd.NormFloat64()
71 eCopy := make([]float64, len(e))
74 ok := impl.Dsterf(n, d, e)
76 t.Errorf("Eigenvalue decomposition failed")
80 // Test that the eigenvalues are sorted.
81 if !sort.Float64sAreSorted(d) {
82 t.Errorf("Values are not sorted")
85 // Construct original tridagional matrix.
87 a := make([]float64, n*lda)
88 for i := 0; i < n; i++ {
91 a[i*lda+i+1] = eCopy[i]
92 a[(i+1)*lda+i] = eCopy[i]
96 asub := make([]float64, len(a))
97 ipiv := make([]int, n)
99 // Test that they are actually eigenvalues by computing the
100 // determinant of A - λI.
101 // TODO(btracey): Replace this test with a more numerically stable
103 for _, lambda := range d {
105 for i := 0; i < n; i++ {
106 asub[i*lda+i] -= lambda
110 ok := impl.Dgetrf(n, n, asub, lda, ipiv)
112 // Definitely singular.
115 // Compute determinant.
117 for i := 0; i < n; i++ {
119 logdet += math.Log(math.Abs(v))
121 if math.Exp(logdet) > 2 {
122 t.Errorf("Incorrect singular value. n = %d, cas = %d, det = %v", n, cas, math.Exp(logdet))