159 static const scalar_type zero = math::zero<scalar_type>();
160 static const scalar_type one = math::identity<scalar_type>();
164 scalar_type norm_rhs = norm(rhs);
165 if (norm_rhs < Alina::detail::eps<scalar_type>(1)) {
167 norm_rhs = math::identity<scalar_type>();
175 scalar_type eps = std::max(prm.tol * norm_rhs, prm.abstol);
176 scalar_type norm_r = zero;
180 if (prm.pside == ePreconditionerSideType::left) {
181 backend::residual(rhs, A, x, *v[0]);
185 backend::residual(rhs, A, x, *r);
190 if (norm_r < eps || iter >= prm.maxiter)
194 backend::axpby(math::inverse(norm_r), *r, zero, *v[0]);
196 std::fill(s.begin(), s.end(), 0);
205 vector& v_new = *v[j + 1];
207 preconditioner_spmv(prm.pside, P, A, *v[j], v_new, *r);
209 for (
unsigned k = 0; k <= j; ++k) {
210 H(k, j) = inner_product(v_new, *v[k]);
211 backend::axpby(-H(k, j), *v[k], one, v_new);
213 H(j + 1, j) = norm(v_new);
215 backend::axpby(math::inverse(H(j + 1, j)), v_new, zero, v_new);
217 for (
unsigned k = 0; k < j; ++k)
218 detail::apply_plane_rotation(H(k, j), H(k + 1, j), cs[k], sn[k]);
220 detail::generate_plane_rotation(H(j, j), H(j + 1, j), cs[j], sn[j]);
221 detail::apply_plane_rotation(H(j, j), H(j + 1, j), cs[j], sn[j]);
222 detail::apply_plane_rotation(s[j], s[j + 1], cs[j], sn[j]);
224 scalar_type inner_res = std::abs(s[j + 1]);
226 if (prm.verbose && iter % 5 == 0)
227 std::cout << iter <<
"\t" << std::scientific << inner_res / norm_rhs << std::endl;
231 if (iter >= prm.maxiter || j >= prm.M || inner_res <= eps)
236 for (
unsigned i = j; i-- > 0;) {
238 for (
unsigned k = 0; k < i; ++k)
239 s[k] -= H(k, i) * s[i];
244 backend::lin_comb(j, s, v, zero, dx);
246 if (prm.pside == ePreconditionerSideType::left) {
247 backend::axpby(one, dx, one, x);
252 backend::axpby(one, tmp, one, x);
256 return std::make_tuple(iter, norm_r / norm_rhs);