1 #ifndef OMEGA_H_SVD_HPP
2 #define OMEGA_H_SVD_HPP
4 #include <Omega_h_eigen.hpp>
20 Givens givens(Real
const a, Real
const b) noexcept {
24 if (std::abs(b) > std::abs(a)) {
25 auto const t = -a / b;
26 s = 1.0 / std::sqrt(1.0 + t * t);
29 auto const t = -b / a;
30 c = 1.0 / std::sqrt(1.0 + t * t);
53 SVD<2> svd_bidiagonal(Real f, Real
const g, Real h) noexcept {
54 auto fa = std::abs(f);
55 auto ga = std::abs(g);
56 auto ha = std::abs(h);
63 auto const swap_diag = (ha > fa);
64 if (swap_diag ==
true) {
72 }
else if (ga > fa && fa / ga < DBL_EPSILON) {
75 s1 = ha > 1.0 ? Real(fa / (ga / ha)) : Real((fa / ga) * ha);
82 auto const d = fa - ha;
83 auto const l = d / fa;
85 auto const t = 2.0 - l;
86 auto const mm = m * m;
87 auto const tt = t * t;
88 auto const s = std::sqrt(tt + mm);
89 auto const r = ((l != 0.0) ? (std::sqrt(l * l + mm))
91 auto const a = 0.5 * (s + r);
97 tau = (m / (s + t) + m / (r + l)) * (1.0 + a);
100 tau = (l == 0.0) ? (std::copysign(2.0, f) * std::copysign(1.0, g))
101 : (g / std::copysign(d, f) + m / t);
104 std::sqrt(tau * tau + 4.0);
107 cu = (cv + sv * m) / a;
108 su = (h / f) * sv / a;
111 s0 = std::copysign(s0, f);
112 s1 = std::copysign(s1, h);
113 if (swap_diag ==
true) {
117 auto const U = matrix_2x2(cu, -su, su, cu);
118 auto const S = matrix_2x2(s0, 0.0, 0.0, s1);
119 auto const V = matrix_2x2(cv, -sv, sv, cv);
124 SVD<2> svd_2x2(Matrix<2, 2>
const A) OMEGA_H_NOEXCEPT {
126 auto const cs = givens(A(0, 0), A(1, 0));
129 auto const R = matrix_2x2(c, -s, s, c);
130 auto const B = R * A;
132 auto const XSV = svd_bidiagonal(B(0, 0), B(0, 1), B(1, 1));
133 auto const X = XSV.U;
134 auto const S = XSV.S;
135 auto const V = XSV.V;
137 auto const U = transpose(R) * X;
147 OMEGA_H_INLINE SVD<dim> decompose_svd(
148 Matrix<dim, dim>
const A) OMEGA_H_NOEXCEPT {
150 auto const norm_a = norm(A);
151 auto const scale = norm_a > 0.0 ? norm_a : Real(1.0);
153 auto U = identity_matrix<dim, dim>();
154 auto V = identity_matrix<dim, dim>();
155 auto off = norm_off_diag(S);
156 auto const tol = DBL_EPSILON;
157 Int
const max_iter = 2048;
159 while (off > tol && num_iter < max_iter) {
161 auto const pq = arg_max_off_diag(S);
164 if (p > q) swap2(p, q);
166 auto const Spq = matrix_2x2(S(p, p), S(p, q), S(q, p), S(q, q));
167 auto const LDR = svd_2x2(Spq);
168 auto const L = LDR.U;
169 auto const R = LDR.V;
170 auto const cl = L(0, 0);
171 auto const sl = L(0, 1);
172 auto const cr = R(0, 0);
173 auto const sr = (sign(R(0, 1)) == sign(R(1, 0))) ? (-R(0, 1)) : (R(0, 1));
176 S = givens_left(cl, sl, p, q, S);
177 S = givens_right(cr, sr, p, q, S);
178 U = givens_right(cl, sl, p, q, U);
179 V = givens_left(cr, sr, p, q, V);
180 off = norm_off_diag(S);
185 for (Int i = 0; i < dim; ++i) {
188 for (Int j = 0; j < dim; ++j) {
Definition: amr_mpi_test.cpp:6
Definition: Omega_h_svd.hpp:14
Definition: Omega_h_svd.hpp:38