35 throw std::invalid_argument(
"eig_sym: matrix must be square");
40 for (
idx i = 0;
i < n; ++
i) V(
i,
i) = 1.0;
43 bool converged =
false;
48 for (
idx p = 0; p < n; ++p)
49 for (
idx q = p+1; q < n; ++q)
50 off +=
A(p,q) *
A(p,q);
52 if (std::sqrt(2.0 *
off) <
tol) {
58 for (
idx p = 0; p < n-1; ++p) {
59 for (
idx q = p+1; q < n; ++q) {
61 if (std::abs(
apq) < 1
e-15)
continue;
67 real t = std::copysign(1.0,
tau)
68 / (std::abs(
tau) + std::sqrt(1.0 +
tau*
tau));
69 real c = 1.0 / std::sqrt(1.0 + t*t);
75 A(p,q) =
A(q,p) = 0.0;
78 for (
idx r = 0;
r < n; ++
r) {
79 if (
r == p ||
r == q)
continue;
87 for (
idx r = 0;
r < n; ++
r) {
99 for (
idx i = 0;
i < n; ++
i) values[
i] =
A(
i,
i);
102 for (
idx i = 0;
i < n-1; ++
i) {
108 std::swap(values[
i], values[
min_j]);
109 for (
idx r = 0;
r < n; ++
r)
114 return {values, V, sweeps, converged};
Dense row-major matrix with optional GPU storage.
Full symmetric eigendecomposition via cyclic Jacobi sweeps.
constexpr T ipow(T x) noexcept
Compute x^N at compile time via repeated squaring.
EigenResult eig_sym(const Matrix &A, real tol=1e-12, idx max_sweeps=100, Backend backend=Backend::seq)
Full eigendecomposition of a real symmetric matrix.
Full eigendecomposition result: A = V * diag(values) * V^T.