15 throw std::invalid_argument(
"eig_sym: matrix must be square");
17 constexpr real rotation_tol = 1
e-15;
21 for (
idx i = 0; i < n; ++i)
25 bool converged =
false;
27 for (
idx sweep = 0; sweep < max_sweeps; ++sweep) {
29 for (
idx p = 0; p < n; ++p)
30 for (
idx q = p + 1; q < n; ++q)
31 off += A(p, q) * A(p, q);
33 if (std::sqrt(2.0 * off) < tol) {
38 for (
idx p = 0; p < n - 1; ++p) {
39 for (
idx q = p + 1; q < n; ++q) {
41 if (std::abs(apq) < rotation_tol)
44 real app = A(p, p), aqq = A(q, q);
45 real tau = (aqq - app) / (2.0 * apq);
46 real t = std::copysign(1.0, tau)
47 / (std::abs(tau) + std::sqrt(1.0 + tau * tau));
48 real c = 1.0 / std::sqrt(1.0 + t * t);
51 A(p, p) = c * c * app - 2.0 * c * s * apq + s * s * aqq;
52 A(q, q) = s * s * app + 2.0 * c * s * apq + c * c * aqq;
53 A(p, q) = A(q, p) = 0.0;
55 for (
idx r = 0; r < n; ++r) {
58 real arp = A(r, p), arq = A(r, q);
59 A(r, p) = A(p, r) = c * arp - s * arq;
60 A(r, q) = A(q, r) = s * arp + c * arq;
63 for (
idx r = 0; r < n; ++r) {
64 real vrp = V(r, p), vrq = V(r, q);
65 V(r, p) = c * vrp - s * vrq;
66 V(r, q) = s * vrp + c * vrq;
74 for (
idx i = 0; i < n; ++i)
77 for (
idx i = 0; i < n - 1; ++i) {
79 for (
idx j = i + 1; j < n; ++j)
80 if (values[j] < values[min_j])
83 std::swap(values[i], values[min_j]);
84 for (
idx r = 0; r < n; ++r)
85 std::swap(V(r, i), V(r, min_j));
89 return {values, V, sweeps, converged};