21 throw std::invalid_argument(
"eig_sym: matrix must be square");
23 constexpr real rotation_tol = 1
e-15;
27 for (
idx i = 0; i < n; ++i)
31 bool converged =
false;
33 for (
idx sweep = 0; sweep < max_sweeps; ++sweep) {
35 for (
idx p = 0; p < n; ++p)
36 for (
idx q = p + 1; q < n; ++q)
37 off += A(p, q) * A(p, q);
39 if (std::sqrt(2.0 * off) < tol) {
44 for (
idx p = 0; p < n - 1; ++p) {
45 for (
idx q = p + 1; q < n; ++q) {
47 if (std::abs(apq) < rotation_tol)
50 real app = A(p, p), aqq = A(q, q);
51 real tau = (aqq - app) / (2.0 * apq);
52 real t = std::copysign(1.0, tau)
53 / (std::abs(tau) + std::sqrt(1.0 + tau * tau));
54 real c = 1.0 / std::sqrt(1.0 + t * t);
57 A(p, p) = c * c * app - 2.0 * c * s * apq + s * s * aqq;
58 A(q, q) = s * s * app + 2.0 * c * s * apq + c * c * aqq;
59 A(p, q) = A(q, p) = 0.0;
61 for (
idx r = 0; r < n; ++r) {
64 real arp = A(r, p), arq = A(r, q);
65 A(r, p) = A(p, r) = c * arp - s * arq;
66 A(r, q) = A(q, r) = s * arp + c * arq;
69 for (
idx r = 0; r < n; ++r) {
70 real vrp = V(r, p), vrq = V(r, q);
71 V(r, p) = c * vrp - s * vrq;
72 V(r, q) = s * vrp + c * vrq;
80 for (
idx i = 0; i < n; ++i)
83 for (
idx i = 0; i < n - 1; ++i) {
85 for (
idx j = i + 1; j < n; ++j)
86 if (values[j] < values[min_j])
89 std::swap(values[i], values[min_j]);
90 for (
idx r = 0; r < n; ++r)
91 std::swap(V(r, i), V(r, min_j));
95 return {values, V, sweeps, converged};