12 constexpr real tiny = 1
e-300;
14 idx r = std::min(m, n);
19 for (
idx i = 0; i < n; ++i)
23 bool converged =
false;
25 for (
idx sweep = 0; sweep < max_sweeps; ++sweep) {
27 for (
idx p = 0; p < r - 1; ++p) {
28 for (
idx q = p + 1; q < r; ++q) {
30 for (
idx i = 0; i < m; ++i) {
31 alpha += A(i, p) * A(i, p);
32 beta += A(i, q) * A(i, q);
33 gamma += A(i, p) * A(i, q);
35 if (alpha < tiny ||
beta < tiny)
38 real cos_pq = std::abs(gamma) / std::sqrt(alpha *
beta);
39 max_cos = std::max(max_cos, cos_pq);
47 real c = 1.0 / std::sqrt(1.0 + t * t);
50 for (
idx i = 0; i < m; ++i) {
51 real aip = A(i, p), aiq = A(i, q);
52 A(i, p) = c * aip - s * aiq;
53 A(i, q) = s * aip + c * aiq;
56 for (
idx i = 0; i < n; ++i) {
57 real vip = V(i, p), viq = V(i, q);
58 V(i, p) = c * vip - s * viq;
59 V(i, q) = s * vip + c * viq;
73 for (
idx j = 0; j < r; ++j) {
75 for (
idx i = 0; i < m; ++i)
76 nrm += A(i, j) * A(i, j);
77 S[j] = std::sqrt(nrm);
79 for (
idx i = 0; i < m; ++i)
80 U(i, j) = A(i, j) / S[j];
83 for (
idx i = 0; i < r - 1; ++i) {
85 for (
idx j = i + 1; j < r; ++j)
90 std::swap(S[i], S[max_j]);
91 for (
idx k = 0; k < m; ++k)
92 std::swap(U(k, i), U(k, max_j));
93 for (
idx k = 0; k < n; ++k)
94 std::swap(V(k, i), V(k, max_j));
99 for (
idx i = 0; i < r; ++i)
100 for (
idx j = 0; j < n; ++j)
103 return {U, S, Vt, sweeps, converged};