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.
10 "gonum.org/v1/gonum/blas"
11 "gonum.org/v1/gonum/blas/blas64"
12 "gonum.org/v1/gonum/lapack"
15 // Dsyev computes all eigenvalues and, optionally, the eigenvectors of a real
16 // symmetric matrix A.
18 // w contains the eigenvalues in ascending order upon return. w must have length
19 // at least n, and Dsyev will panic otherwise.
21 // On entry, a contains the elements of the symmetric matrix A in the triangular
22 // portion specified by uplo. If jobz == lapack.ComputeEV a contains the
23 // orthonormal eigenvectors of A on exit, otherwise on exit the specified
24 // triangular region is overwritten.
26 // work is temporary storage, and lwork specifies the usable memory length. At minimum,
27 // lwork >= 3*n-1, and Dsyev will panic otherwise. The amount of blocking is
28 // limited by the usable length. If lwork == -1, instead of computing Dsyev the
29 // optimal work length is stored into work[0].
30 func (impl Implementation) Dsyev(jobz lapack.EVJob, uplo blas.Uplo, n int, a []float64, lda int, w, work []float64, lwork int) (ok bool) {
31 checkMatrix(n, n, a, lda)
32 upper := uplo == blas.Upper
33 wantz := jobz == lapack.ComputeEV
40 nb := impl.Ilaenv(1, "DSYTRD", opts, n, -1, -1, -1)
41 lworkopt := max(1, (nb+2)*n)
42 work[0] = float64(lworkopt)
46 if len(work) < lwork {
65 smlnum := safmin / eps
67 rmin := math.Sqrt(smlnum)
68 rmax := math.Sqrt(bignum)
70 // Scale matrix to allowable range, if necessary.
71 anrm := impl.Dlansy(lapack.MaxAbs, uplo, n, a, lda, work)
74 if anrm > 0 && anrm < rmin {
77 } else if anrm > rmax {
82 kind := lapack.LowerTri
84 kind = lapack.UpperTri
86 impl.Dlascl(kind, 0, 0, 1, sigma, n, n, a, lda)
91 llwork := lwork - indwork
92 impl.Dsytrd(uplo, n, a, lda, w, work[inde:], work[indtau:], work[indwork:], llwork)
94 // For eigenvalues only, call Dsterf. For eigenvectors, first call Dorgtr
95 // to generate the orthogonal matrix, then call Dsteqr.
97 ok = impl.Dsterf(n, w, work[inde:])
99 impl.Dorgtr(uplo, n, a, lda, work[indtau:], work[indwork:], llwork)
100 ok = impl.Dsteqr(lapack.EVComp(jobz), n, w, work[inde:], a, lda, work[indtau:])
106 // If the matrix was scaled, then rescale eigenvalues appropriately.
108 bi := blas64.Implementation()
109 bi.Dscal(n, 1/sigma, w, 1)
111 work[0] = float64(lworkopt)