Reputation: 193
This is a question about setting proper tolerance ("abstol") for convergence of eigenvalue calculation with LAPACKE_zheevx() function in C++.
When LAPACKE_zheev() fails to converge when calculating eigenvalues/eigenvectors with the default value of "abstol" (i.e. abstol=-1), the LAPACK manual says to set abstol=2*DLAMCH('S'). However, DLAMCH is Fortran function and I use C++ which does not recognize it as a valid C++ function. Could anyone please help me how to properly set "abstol=2*DLAMCH('S')" when using LAPACK with C++ (i.e. when using LAPACKE)?
Thanks very much in advance!!
Background: LAPACKE is C++ interface for LAPACK (Fortran library for numerical algebra). LAPACKE_zheevx() is LAPACKE's C++ interface for LAPACK's ZHEEVX() function.
Keywords: LAPACK, LAPACKE, C++, ABSTOL, DLAMCH, CONVERGENCE, EIGENVALUES, EIGENVECTORS
Upvotes: 1
Views: 283
Reputation: 15508
In addition to the answer of Jon Purdy (which is practically the way to go):
Here is the definition of dlamch.f
in Fortran. Going through that function, and getting the Lapack-intrinsic functions from here, one sees that for the input 's'
the function translated to C++ becomes:
auto dlamch_s()
{
auto one = 1.0;
auto rnd = one;
auto eps = (one == rnd ? 0.5 : 1.0) * std::numeric_limits<double>::epsilon();
auto sfmin = std::numeric_limits<double>::min();
auto small = one / std::numeric_limits<double>::max();
if(small>=sfmin)
{
sfmin = small*(one + eps);
}
return sfmin;
}
Don't ask me, however, why the one == rnd
step is needed.
Upvotes: 2
Reputation: 55059
I don’t know anything about these libraries, but a bit of Googling reveals there is a corresponding LAPACKE_dlamch()
function:
double LAPACKE_dlamch(char cmach)
So you should be able to just pass LAPACKE_dlamch('S')
as the abstol
(12th) parameter of LAPACKE_zheevx()
:
lapack_int LAPACKE_zheevx (
int matrix_layout,
char jobz,
char range,
char uplo,
lapack_int n,
lapack_complex_double *a,
lapack_int lda,
double vl,
double vu,
lapack_int il,
lapack_int iu,
double abstol,
// ^^^^^^^^^^^^^
lapack_int *m,
double *w,
lapack_complex_double *z,
lapack_int ldz,
lapack_int *ifail
)
Upvotes: 2