Tatooine
eigenvalues.h
Go to the documentation of this file.
1#ifndef TATOOINE_TENSOR_OPERATIONS_EIGENVALUES_H
2#define TATOOINE_TENSOR_OPERATIONS_EIGENVALUES_H
3//==============================================================================
4#include <tatooine/tensor.h>
8//==============================================================================
9namespace tatooine {
10//==============================================================================
11// template <typename Tensor, typename Real>
12// constexpr auto eigenvectors_sym(base_tensor<Tensor, Real, 2, 2> const& A) {
13// decltype(auto) b = A(1, 0);
14// if (b == 0) {
15// return std::pair{mat<Real, 2, 2>::eye(), vec<Real, 2>{A(0, 0), A(1, 1)}};
16// }
17//
18// decltype(auto) a = A(0, 0);
19// decltype(auto) d = A(1, 1);
20// auto const e_sqr = d * d - 2 * a * d + 4 * b * b + a * a;
21// auto const e = std::sqrt(e_sqr);
22// constexpr auto half = 1 / Real(2);
23// auto const b2inv = 1 / (2 * b);
24// std::pair out{mat<Real, 2, 2>{{Real(1), Real(1)},
25// {-(e - d + a) * b2inv, (e + d - a) * b2inv}},
26// vec<Real, 2>{-(e - d - a) * half, (e + d + a) * half}};
27// if (out.second(0) > out.second(1)) {
28// std::swap(out.first(1, 0), out.first(1, 1));
29// std::swap(out.second(0), out.second(1));
30// }
31// if (out.first(1, 0) < 0) {
32// out.first.col(0) *= -1;
33// }
34// if (out.first(1, 1) < 0) {
35// out.first.col(1) *= -1;
36// }
37// out.first.col(0) /= std::sqrt(1 + out.first(1, 0) * out.first(1, 0));
38// out.first.col(1) /= std::sqrt(1 + out.first(1, 1) * out.first(1, 1));
39// return out;
40//}
41//------------------------------------------------------------------------------
42#if TATOOINE_BLAS_AND_LAPACK_AVAILABLE
43template <static_quadratic_mat Mat>
45 static constexpr auto N = tensor_dimension<Mat, 0>;
46
47 auto W = std::pair{mat<tatooine::value_type<Mat>, N, N>{std::forward<Mat>(A)},
50 return W;
51}
52#endif
53//==============================================================================
54template <fixed_size_quadratic_mat<2> Mat>
55constexpr auto eigenvalues_sym(Mat&& A) {
56 decltype(auto) b = A(1, 0);
57 if (std::abs(b) <= 1e-11) {
58 return vec<tatooine::value_type<Mat>, 2>{A(0, 0), A(1, 1)};
59 }
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);
64 constexpr auto half = 1 / tatooine::value_type<Mat>(2);
65 auto lambda = vec<tatooine::value_type<Mat>, 2>{-e + d + a, e + d + a} * half;
66 if (lambda(0) > lambda(1)) {
67 std::swap(lambda(0), lambda(1));
68 }
69 return lambda;
70}
71//------------------------------------------------------------------------------
72#if TATOOINE_BLAS_AND_LAPACK_AVAILABLE
73template <static_quadratic_mat Mat>
74constexpr auto eigenvalues_sym(Mat&& A) {
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)};
79 return W;
80}
81#endif
82//------------------------------------------------------------------------------
83#if TATOOINE_BLAS_AND_LAPACK_AVAILABLE
84template <static_quadratic_mat Mat>
85constexpr auto eigenvalues(Mat&& A) {
86 using Real = tatooine::value_type<Mat>;
87 auto constexpr N = tensor_dimensions<Mat>[0];
88 auto A2 = tensor<Real, N, N>{std::forward<Mat>(A)};
89 auto eig = complex_vec<Real, N>{};
90 [[maybe_unused]] auto const info = lapack::geev(A2, eig);
91 return eig;
92}
93#endif
94// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
95template <fixed_size_quadratic_mat<2> Mat>
96constexpr auto eigenvalues(Mat&& A)
97 -> complex_vec<tatooine::value_type<Mat>, 2> {
98 using value_t = tatooine::value_type<Mat>;
99 decltype(auto) b = A(1, 0);
100 decltype(auto) c = A(0, 1);
101 // if (std::abs(b - c) < 1e-10) {
102 // return eigenvalues_22_sym(A);
103 //}
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;
107
108 auto s = ComplexVec2<value_t>{};
109 if (sqr >= 0) {
110 s(0).real(-(std::sqrt(sqr) - d - a) / 2);
111 s(1).real((std::sqrt(sqr) + d + a) / 2);
112 } else {
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());
117 }
118 return s;
119}
120//------------------------------------------------------------------------------
121#if TATOOINE_BLAS_AND_LAPACK_AVAILABLE
122template <static_quadratic_mat Mat>
123auto eigenvectors(Mat&& B) {
124 auto constexpr N = tensor_dimensions<Mat>[0];
125 using Real = tatooine::value_type<Mat>;
126 auto A = tensor<Real, N, N>{B};
127 auto eig = std::pair{complex_mat<Real, N, N>{}, complex_vec<Real, N>{}};
128 auto& V = eig.first;
129 auto& W = eig.second;
130 auto VR = mat<Real, N, N>{};
131 [[maybe_unused]] auto const info = lapack::geev_right(A, W, VR);
132
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};
137 } else {
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]};
140 if (i == N - 1) {
141 ++j;
142 }
143 }
144 }
145 }
146
147 return eig;
148}
149#endif
150//==============================================================================
151} // namespace tatooine
152//==============================================================================
153#endif
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
Definition: mat.h:14
Definition: tensor.h:17
Definition: vec.h:12