118 const params& prm = params(),
119 const backend_params& bprm = backend_params(),
120 const InnerProduct& inner_product = InnerProduct())
121 : SolverBase(context)
124 , H(prm.M + 1, prm.M)
128 , r(Backend::create_vector(n, bprm))
129 , inner_product(inner_product)
131 v.reserve(prm.M + 1);
132 for (
unsigned i = 0; i <= prm.M; ++i)
133 v.push_back(Backend::create_vector(n, bprm));
136 for (
unsigned i = 0; i < prm.M; ++i)
137 z.push_back(Backend::create_vector(n, bprm));
160 scalar_type norm_rhs = norm(rhs);
161 if (norm_rhs < Alina::detail::eps<scalar_type>(1)) {
163 norm_rhs = math::identity<scalar_type>();
171 scalar_type eps = std::max(prm.tol * norm_rhs, prm.abstol);
172 scalar_type norm_r = math::zero<scalar_type>();
176 backend::residual(rhs, A, x, *v[0]);
179 if ((norm_r = norm(*v[0])) < eps || iter >= prm.maxiter)
183 std::fill(s.begin(), s.end(), 0);
186 backend::axpby(math::inverse(norm_r), *v[0], math::zero<scalar_type>(), *v[0]);
195 vector& v_new = *v[j + 1];
197 P.apply(*v[j], *z[j]);
198 backend::spmv(math::identity<scalar_type>(), A, *z[j],
199 math::zero<scalar_type>(), v_new);
201 for (
unsigned k = 0; k <= j; ++k) {
202 H(k, j) = inner_product(v_new, *v[k]);
203 backend::axpby(-H(k, j), *v[k], math::identity<scalar_type>(), v_new);
205 H(j + 1, j) = norm(v_new);
207 backend::axpby(math::inverse(H(j + 1, j)), v_new, math::zero<scalar_type>(), v_new);
209 for (
unsigned k = 0; k < j; ++k)
210 detail::apply_plane_rotation(H(k, j), H(k + 1, j), cs[k], sn[k]);
212 detail::generate_plane_rotation(H(j, j), H(j + 1, j), cs[j], sn[j]);
213 detail::apply_plane_rotation(H(j, j), H(j + 1, j), cs[j], sn[j]);
214 detail::apply_plane_rotation(s[j], s[j + 1], cs[j], sn[j]);
216 scalar_type inner_res = std::abs(s[j + 1]);
218 if (prm.verbose && iter % 5 == 0)
219 std::cout << iter <<
"\t" << std::scientific << inner_res / norm_rhs << std::endl;
223 if (iter >= prm.maxiter || j >= prm.M || inner_res <= eps)
228 for (
unsigned i = j; i-- > 0;) {
230 for (
unsigned k = 0; k < i; ++k)
231 s[k] -= H(k, i) * s[i];
234 backend::lin_comb(j, s, z, math::identity<scalar_type>(), x);