1#ifndef TATOOINE_TENSOR_OPERATIONS_EIGENVALUES_H
2#define TATOOINE_TENSOR_OPERATIONS_EIGENVALUES_H
42#if TATOOINE_BLAS_AND_LAPACK_AVAILABLE
43template <static_quadratic_mat Mat>
45 static constexpr auto N = tensor_dimension<Mat, 0>;
54template <fixed_size_quadratic_mat<2> Mat>
56 decltype(
auto) b = A(1, 0);
57 if (std::abs(b) <= 1e-11) {
60 decltype(
auto) a = A(0, 0);
61 decltype(
auto) d = A(1, 1);
62 auto const e_sqr = d * d - 2 * a * d + 4 * b * b + a * a;
63 auto const e = std::sqrt(e_sqr);
66 if (lambda(0) > lambda(1)) {
67 std::swap(lambda(0), lambda(1));
72#if TATOOINE_BLAS_AND_LAPACK_AVAILABLE
73template <static_quadratic_mat Mat>
75 auto constexpr N = tensor_dimensions<Mat>[0];
76 auto W = vec<tatooine::value_type<Mat>, N>{};
77 auto A2 = mat<tatooine::value_type<Mat>, N, N>{std::forward<Mat>(A)};
83#if TATOOINE_BLAS_AND_LAPACK_AVAILABLE
84template <static_quadratic_mat Mat>
87 auto constexpr N = tensor_dimensions<Mat>[0];
90 [[maybe_unused]]
auto const info =
lapack::geev(A2, eig);
95template <fixed_size_quadratic_mat<2> Mat>
97 -> complex_vec<tatooine::value_type<Mat>, 2> {
99 decltype(
auto) b = A(1, 0);
100 decltype(
auto) c = A(0, 1);
104 decltype(
auto) a = A(0, 0);
105 decltype(
auto) d = A(1, 1);
106 auto const sqr = d * d - 2 * a * d + 4 * b * c + a * a;
108 auto s = ComplexVec2<value_t>{};
110 s(0).real(-(std::sqrt(sqr) - d - a) / 2);
111 s(1).real((std::sqrt(sqr) + d + a) / 2);
113 s(0).real((d + a) / 2);
114 s(1).real(s(0).
real());
115 s(0).imag(std::sqrt(std::abs(sqr)) / 2);
116 s(1).imag(-s(0).
imag());
121#if TATOOINE_BLAS_AND_LAPACK_AVAILABLE
122template <static_quadratic_mat Mat>
124 auto constexpr N = tensor_dimensions<Mat>[0];
129 auto& W = eig.second;
133 for (std::size_t j = 0; j < N; ++j) {
134 for (std::size_t i = 0; i < N; ++i) {
135 if (W[j].
imag() == 0) {
136 V(i, j) = {VR[i + j * N], 0};
138 V(i, j) = {VR[i + j * N], VR[i + (j + 1) * N]};
139 V(i, j + 1) = {VR[i + j * N], -VR[i + (j + 1) * N]};
auto geev(job JOBVL, job JOBVR, int N, Float *A, int LDA, Float *WR, Float *WI, Float *VL, int LDVL, Float *VR, int LDVR, Float *WORK, int LWORK) -> int
Definition: geev.h:44
auto geev_right(tensor< Float, N, N > &A, tensor< std::complex< Float >, N > &W, tensor< Float, N, N > &VR)
Definition: geev.h:121
auto syev(job j, uplo u, int N, Float *A, int LDA, Float *W, Float *WORK, int LWORK) -> int
Definition: syev.h:17
Definition: algorithm.h:6
typename value_type_impl< T >::type value_type
Definition: type_traits.h:280
auto real(base_tensor< Tensor, std::complex< T >, Dims... > const &t)
Definition: complex_tensor_views.h:173
auto eigenvectors_sym(Mat &&A)
Definition: eigenvalues.h:44
constexpr auto eigenvalues(Mat &&A)
Definition: eigenvalues.h:85
auto imag(base_tensor< Tensor, std::complex< T >, Dims... > const &tensor)
Definition: complex_tensor_views.h:86
constexpr auto eigenvalues_sym(Mat &&A)
Definition: eigenvalues.h:55
mat< real_number, M, N > Mat
Definition: mat_typedefs.h:10
auto eigenvectors(Mat &&B)
Definition: eigenvalues.h:123