1#ifndef LAMBDA_LANCZOS_TRIDIAGONAL_IMPL_H_
2#define LAMBDA_LANCZOS_TRIDIAGONAL_IMPL_H_
23 const std::vector<T>& alpha,
24 const std::vector<T>& beta) {
27 size_t m = alpha.size();
33 for(
size_t i = 1; i < m; ++i){
34 q_i = alpha[i] - c - beta[i-1]*beta[i-1]/q_i;
39 q_i = std::numeric_limits<T>::epsilon();
56 const std::vector<T>& beta) {
69 const std::vector<T>& beta,
72 T pmid = std::numeric_limits<T>::max();
77 while(upper-lower > std::min(std::abs(lower), std::abs(upper))*std::numeric_limits<T>::epsilon()) {
78 mid = (lower+upper)*T(0.5);
102 const std::vector<T>& beta,
107 const auto m = alpha.size();
108 std::vector<T> cv(m);
113 cv[m-2] = (ev - alpha[m-1]) * cv[m-1] / beta[m-2];
114 for (
size_t k = m-2; k-- > 0;) {
115 cv[k] = ((ev - alpha[k + 1]) * cv[k + 1] - beta[k + 1] * cv[k + 2]) / beta[k];
130 const std::vector<T>& beta,
131 std::vector<T>& eigenvalues,
132 std::vector<std::vector<T>>& eigenvectors) {
133 const size_t n = alpha.size();
134 eigenvalues.resize(n);
135 eigenvectors.resize(n);
137 for(
size_t j = 0; j < n; ++j) {
162 return std::make_pair(1.0, 0.0);
166 return std::make_pair(0.0, 1.0);
169 T x = std::sqrt(a*a + b*b);
173 return std::make_pair(c, s);
192 std::vector<T>& beta,
193 std::vector<std::vector<T>>& q,
196 bool rotate_matrix) {
205 T d = (alpha[offset+nsub-2] - alpha[offset+nsub-1]) / (2 * beta[offset+nsub-2]);
206 T mu = alpha[offset+nsub-1] - beta[offset+nsub-2] / (d + sgn(d) * sqrt(d*d + T(1)));
207 T x = alpha[offset+0] - mu;
213 for(
size_t k = 0; k < nsub - 1; ++k) {
214 T z = s*beta[offset+k];
215 T beta_prev = c*beta[offset+k];
222 beta[offset+k-1] = sqrt(x*x + z*z);
224 T u = ((alpha[offset+k+1] - alpha[offset+k] + p)*s + T(2)*c*beta_prev);
225 alpha[offset+k] = alpha[offset+k] - p + s*u;
233 for(
size_t j = 0; j < alpha.size(); ++j) {
234 auto v0 = q[offset+k][j];
235 auto v1 = q[offset+k+1][j];
237 q[offset+k][j] = c*v0 + s*v1;
238 q[offset+k+1][j] = -s*v0 + c*v1;
243 alpha[offset+nsub-1] = alpha[offset+nsub-1] - p;
244 beta[offset+nsub-2] = x;
264 std::vector<T>& beta,
265 size_t& submatrix_first,
266 size_t& submatrix_last) {
267 const T eps = std::numeric_limits<T>::epsilon() * 0.5;
268 const T safe_min = std::numeric_limits<T>::min();
269 const size_t n = alpha.size();
272 for(
size_t i = 0; i < n-1; ++i) {
273 if(std::abs(beta[i]) < std::sqrt(std::abs(alpha[i]) * std::abs(alpha[i+1]))*eps + safe_min) {
279 while(submatrix_last > 0 && beta[submatrix_last-1] == 0) {
282 submatrix_first = submatrix_last;
283 while(submatrix_first > 0 && beta[submatrix_first-1] != 0) {
303 const std::vector<T>& beta,
304 std::vector<T>& eigenvalues,
305 std::vector<std::vector<T>>& eigenvectors,
306 bool compute_eigenvector =
true) {
307 const size_t n = alpha.size();
309 auto alpha_work = alpha;
310 auto beta_work = beta;
313 if(compute_eigenvector) {
317 size_t unconverged_count = 0;
318 size_t submatrix_last_prev = n - 1;
320 size_t loop_count = 1;
322 size_t submatrix_last = submatrix_last_prev;
323 size_t submatrix_first;
324 find_subspace(alpha_work, beta_work, submatrix_first, submatrix_last);
326 const size_t nsub = submatrix_last - submatrix_first + 1;
327 const size_t max_loop_count = nsub * 50;
329 if(submatrix_last > 0) {
335 compute_eigenvector);
340 if(submatrix_last == submatrix_last_prev) {
341 if(loop_count > max_loop_count) {
342 submatrix_last_prev = submatrix_first;
350 submatrix_last_prev = submatrix_last;
354 eigenvalues = alpha_work;
358 return unconverged_count;
374 const std::vector<T>& beta,
375 std::vector<T>& eigenvalues) {
376 std::vector<std::vector<T>> dummy_eigenvectors;
size_t num_of_eigs_smaller_than(T c, const std::vector< T > &alpha, const std::vector< T > &beta)
Finds the number of eigenvalues of given tridiagonal matrix smaller than c.
Definition: lambda_lanczos_tridiagonal_impl.hpp:22
size_t tridiagonal_eigenvalues(const std::vector< T > &alpha, const std::vector< T > &beta, std::vector< T > &eigenvalues)
Computes all eigenvalues for given tri-diagonal matrix using the Implicitly Shifted QR algorithm.
Definition: lambda_lanczos_tridiagonal_impl.hpp:373
T find_mth_eigenvalue(const std::vector< T > &alpha, const std::vector< T > &beta, const size_t m)
Finds the mth smaller eigenvalue of given tridiagonal matrix.
Definition: lambda_lanczos_tridiagonal_impl.hpp:68
void find_subspace(const std::vector< T > &alpha, std::vector< T > &beta, size_t &submatrix_first, size_t &submatrix_last)
Find sub-tridiagonal matrix that remains non-diagonal.
Definition: lambda_lanczos_tridiagonal_impl.hpp:263
void tridiagonal_eigenpairs_bisection(const std::vector< T > &alpha, const std::vector< T > &beta, std::vector< T > &eigenvalues, std::vector< std::vector< T > > &eigenvectors)
Computes all eigenpairs (eigenvalues and eigenvectors) for given tri-diagonal matrix.
Definition: lambda_lanczos_tridiagonal_impl.hpp:129
std::vector< T > compute_tridiagonal_eigenvector_from_eigenvalue(const std::vector< T > &alpha, const std::vector< T > &beta, const size_t index, const T ev)
Computes an eigenvector corresponding to given eigenvalue for given tri-diagonal matrix.
Definition: lambda_lanczos_tridiagonal_impl.hpp:101
T tridiagonal_eigen_limit(const std::vector< T > &alpha, const std::vector< T > &beta)
Computes the upper bound of the absolute value of eigenvalues by Gerschgorin theorem.
Definition: lambda_lanczos_tridiagonal_impl.hpp:55
void isqr_step(std::vector< T > &alpha, std::vector< T > &beta, std::vector< std::vector< T > > &q, size_t offset, size_t nsub, bool rotate_matrix)
Performs an implicit shift QR step A = Z^T A Z on given sub tridiagonal matrix A.
Definition: lambda_lanczos_tridiagonal_impl.hpp:191
size_t tridiagonal_eigenpairs(const std::vector< T > &alpha, const std::vector< T > &beta, std::vector< T > &eigenvalues, std::vector< std::vector< T > > &eigenvectors, bool compute_eigenvector=true)
Computes all eigenpairs (eigenvalues and eigenvectors) for given tri-diagonal matrix using the Implic...
Definition: lambda_lanczos_tridiagonal_impl.hpp:302
std::pair< T, T > calc_givens_cs(T a, T b)
Calculates the cosine and sine of Givens rotation that eliminates a specific element (see detail).
Definition: lambda_lanczos_tridiagonal_impl.hpp:160
void normalize(std::vector< T > &vec)
Normalizes given vector.
Definition: lambda_lanczos_util.hpp:180
void sort_eigenpairs(std::vector< real_t< T > > &eigenvalues, std::vector< std::vector< T > > &eigenvectors, bool sort_eigenvector, const std::function< bool(real_t< T >, real_t< T >)> predicate=std::less< real_t< T > >())
Sorts eigenvalues and eigenvectors with respect to given predicate.
Definition: lambda_lanczos_util.hpp:242
T sgn(T val)
Return the sign of given value.
Definition: lambda_lanczos_util.hpp:300
void initAsIdentity(std::vector< std::vector< T > > &a, size_t n)
Initializes the given matrix a to an n by n identity matrix.
Definition: lambda_lanczos_util.hpp:226
real_t< T > l1_norm(const std::vector< T > &vec)
Returns 1-norm of given vector.
Definition: lambda_lanczos_util.hpp:189
Definition: eigenpair_manager.hpp:10