inline void gen_mult(const VectorIn& v, const Matrix& A, VectorOut& w, Assign, tag::flat<tag::row_vector>, tag::flat<tag::matrix>, tag::flat<tag::row_vector>) { vampir_trace<4011> tracer; // Vector must be column vector // If vector is row vector then matrix must have one column and the operation is a outer product // -> result should be a matrix too // Check if element types are compatible (in contrast to tag dispatching, nesting is considered here) BOOST_STATIC_ASSERT((boost::is_same< typename ashape::mult_op<typename ashape::ashape<VectorIn>::type, typename ashape::ashape<Matrix>::type >::type, ::mtl::ashape::rvec_mat_mult >::value)); #if 1 MTL_DEBUG_THROW_IF((void*)&v == (void*)&w, argument_result_conflict()); #else if ((void*)&v == (void*)&w) { VectorOut tmp(size(w)); mult(A, b, tmp); swap(w, tmp); return; } #endif // w.checked_change_dim(num_cols(A)); w.checked_change_resource(v); MTL_DEBUG_THROW_IF(num_cols(v) != num_rows(A), incompatible_size()); // same dispatching criterion as mat_cvec_mult (until now) rvec_mat_mult(v, A, w, Assign(), typename mtl::traits::mat_cvec_flatcat<Matrix>::type()); }
void adjoint_solve(const VectorIn& x, VectorOut& y) const { using mtl::conj; y.checked_change_resource(x); MTL_THROW_IF(size(x) != size(inv_diag), mtl::incompatible_size()); for (size_type i= 0; i < size(inv_diag); ++i) y[i]= conj(inv_diag[i]) * x[i]; }
void solve(const VectorIn& x, VectorOut& y) const { mtl::vampir_trace<5051> tracer; y.checked_change_resource(x); MTL_THROW_IF(size(x) != size(inv_diag), mtl::incompatible_size()); for (size_type i= 0; i < size(inv_diag); ++i) y[i]= inv_diag[i] * x[i]; }
void adjoint_solve(const VectorIn& x, VectorOut& y) const { mtl::vampir_trace<5059> tracer; y.checked_change_resource(x); pc1.adjoint_solve(x, y); VectorOut &r= create_r(y), &d= create_d(y); r= x; r-= adjoint(A) * y; pc2.adjoint_solve(r, d); y+= d; }
void mult(const VectorIn& v, VectorOut& w, Assign) const { MTL_DEBUG_THROW_IF(std::size_t(size(v)) != n, incompatible_size()); MTL_DEBUG_THROW_IF(size(w) != 0 && std::size_t(size(w)) != m, incompatible_size()); if (size(w) == 0) w.change_dim(m); if (m == n) Assign::first_update(w, v); else if (m < n) Assign::first_update(w, v[irange(m)]); else { VectorOut w1(w[irange(n)]), w2(w[irange(n, imax)]); Assign::first_update(w1, v); Assign::init(w2); } }