Closed
Description
Naively, I'd expect that computed eigenvalues are exactly same whether eigenvectors are computed or not. However, for the symmetric dsyevr
solver, this does not seem to be the case. The difference is "small", however it is very visible for e.g. when an eigenvalue is zero is exact arithmetics. Consider the following matrix
1 -1 0
-1 2 -1
0 -1 1
with the exact eigenvalues 0, 1, and 3.
Using dsyevr
(the driver is below the fold) produces
jobz = "V" info = 0
w = 2.6645352591003757E-015 1.0000000000000018 3.0000000000000000
jobz = "N" info = 0
w = 3.9250536344271737E-017 0.99999999999999978 3.0000000000000000
Note the difference in the "zero" eigenvalue.
The questions is whether my expectation (jobz='N' is exactly equivalent to "run with jobz='V', discard eigenvectors") is too strong, or if it is a potentially fixable defect?
The origin of this question is scipy/scipy#12515
$ cat syevr.f90
implicit none
integer, parameter :: n = 3
integer, parameter :: lda = n
real*8 :: a(lda, n)
real*8 :: abstol
real*8 :: vl, vu
integer :: il, iu
character*1 :: jobz
! outputs
integer :: m
integer :: ldz = n
real*8 :: w(1:n)
real*8 :: z(n, n)
integer :: isuppz(1:2*n)
integer :: lwork = 100
real*8 :: work(1:100)
integer :: liwork = 100
integer :: iwork(1:100)
integer :: info
external :: dsyevr
a(1, :) = (/ 1., -1., 0. /)
a(2, :) = (/ -1, 2, -1 /)
a(3, :) = (/ 0, -1, 1 /)
! not referenced when range='A'
vl = 0.d0
vu = 3.d0
il = 1
iu = n
abstol = 0.0d0
jobz = 'V'
call dsyevr(jobz, 'A', 'U', n, a, lda, vl, vu, il, iu, abstol, m, w, z, ldz, isuppz, work, lwork, iwork, liwork, info)
print*, "jobz = ", jobz, "info = ", info
print*, "w = ", w
jobz = 'N'
call dsyevr(jobz, 'A', 'U', n, a, lda, vl, vu, il, iu, abstol, m, w, z, ldz, isuppz, work, lwork, iwork, liwork, info)
print*, "jobz = ", jobz, "info = ", info
print*, "w = ", w
end
$ gfortran syevr.f90 -lblas -llapack
$ ./a.out
jobz = Vinfo = 0
w = 2.6645352591003757E-015 1.0000000000000018 3.0000000000000000
jobz = Ninfo = 0
w = 3.9250536344271737E-017 0.99999999999999978 3.0000000000000000
with
$ gfortran --version
GNU Fortran (conda-forge gcc 12.3.0-5) 12.3.0
Copyright (C) 2022 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
and
$ mamba list |grep lapack
lapack 3.9.0 netlib conda-forge
liblapack 3.9.0 5_h92ddd45_netlib conda-forge
liblapacke 3.9.0 5_h92ddd45_netlib conda-forge