inline void gen_matrix_copy(const MatrixSrc& src, MatrixDest& dest, bool with_reset) { MTL_THROW_IF(num_rows(src) != num_rows(dest) || num_cols(src) != num_cols(dest), incompatible_size()); if (with_reset) detail::zero_with_sparse_src(dest, typename traits::category<MatrixSrc>::type()); typename traits::row<MatrixSrc>::type row(src); typename traits::col<MatrixSrc>::type col(src); typename traits::const_value<MatrixSrc>::type value(src); typedef typename traits::range_generator<tag::major, MatrixSrc>::type cursor_type; //std::cout << "Slot size is " << detail::copy_inserter_size<Updater>::apply(src, dest) << "\n"; matrix::inserter<MatrixDest, Updater> ins(dest, detail::copy_inserter_size<Updater>::apply(src, dest)); for (cursor_type cursor = begin<tag::major>(src), cend = end<tag::major>(src); cursor != cend; ++cursor) { // std::cout << dest << '\n'; typedef typename traits::range_generator<tag::nz, cursor_type>::type icursor_type; for (icursor_type icursor = begin<tag::nz>(cursor), icend = end<tag::nz>(cursor); icursor != icend; ++icursor) { //std::cout << "in " << row(*icursor) << ", " << col(*icursor) << " insert " << value(*icursor) << '\n'; ins(row(*icursor), col(*icursor)) << value(*icursor); } } }
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); } }
void mult(const VectorIn& v, VectorOut& w, Assign) const { MTL_DEBUG_THROW_IF(int(size(v)) != s, incompatible_size()); MTL_DEBUG_THROW_IF(size(v) != size(w), incompatible_size()); const int nb = n < 3 ? 1 : (n - 2) / 4 * 4 + 1; // Inner domain for (int i= 1; i < m-1; i++) { int kmax= i * n + nb; for (int k= i * n + 1; k < kmax; k+= 4) { typename Collection<VectorIn>::value_type const v0= v[k], v1= v[k+1], v2= v[k+2], v3= v[k+3]; Assign::apply(w[k], 4 * v0 - v[k-n] - v[k+n] - v[k-1] - v1); Assign::apply(w[k+1], 4 * v1 - v[k-n+1] - v[k+n+1] - v0 - v2); Assign::apply(w[k+2], 4 * v2 - v[k-n+2] - v[k+n+2] - v1 - v3); Assign::apply(w[k+3], 4 * v3 - v[k-n+3] - v[k+n+3] - v2 - v[k+4]); } for (int j= nb, k= i * n + j; j < n-1; j++, k++) Assign::apply(w[k], 4 * v[k] - v[k-n] - v[k+n] - v[k-1] - v[k+1]); } // Upper border for (int j= 1; j < n-1; j++) Assign::apply(w[j], 4 * v[j] - v[j+n] - v[j-1] - v[j+1]); // Lower border for (int j= 1, k= (m-1) * n + j; j < n-1; j++, k++) Assign::apply(w[k], 4 * v[k] - v[k-n] - v[k-1] - v[k+1]); // Left border for (int i= 1, k= n; i < m-1; i++, k+= n) Assign::apply(w[k], 4 * v[k] - v[k-n] - v[k+n] - v[k+1]); // Right border for (int i= 1, k= n+n-1; i < m-1; i++, k+= n) Assign::apply(w[k], 4 * v[k] - v[k-n] - v[k+n] - v[k-1]); // Corners Assign::apply(w[0], 4 * v[0] - v[1] - v[n]); Assign::apply(w[n-1], 4 * v[n-1] - v[n-2] - v[2*n - 1]); Assign::apply(w[(m-1)*n], 4 * v[(m-1)*n] - v[(m-2)*n] - v[(m-1)*n+1]); Assign::apply(w[m*n-1], 4 * v[m*n-1] - v[m*n-2] - v[m*n-n-1]); }
inline void merge_complex_vector(const VectorReal& r, const VectorImaginary& i, VectorComplex& c) { vampir_trace<2014> tracer; typedef typename Collection<VectorComplex>::value_type value_type; MTL_THROW_IF(size(r) != size(i), incompatible_size()); c.checked_change_dim(size(r)); for (std::size_t j= 0; j < size(r); ++j) c[j]= value_type(r[j], i[j]); }
void forward_eval_loop(const TT& const_first_eval, const UU& const_second_eval, boost::mpl::false_) { vampir_trace<6001> tracer; // hope there is a more elegant way; copying the arguments causes errors due to double destructor evaluation TT& first_eval= const_cast<TT&>(const_first_eval); UU& second_eval= const_cast<UU&>(const_second_eval); MTL_DEBUG_THROW_IF(mtl::size(first_eval) != mtl::size(second_eval), incompatible_size()); for (std::size_t i= 0, s= size(first_eval); i < s; i++) { first_eval(i); second_eval(i); } }
inline typename make_sparse_trait<SizeVector1, ValueVector>::type make_sparse(const SizeVector1& rows, const SizeVector2& cols, const ValueVector& values, std::size_t m, std::size_t n) { MTL_THROW_IF(size(rows) != size(cols), incompatible_size()); MTL_THROW_IF(size(rows) != size(values), incompatible_size()); typedef make_sparse_trait<SizeVector1, ValueVector> traits; typedef typename traits::type matrix_type; typedef typename traits::value_type value_type; typedef typename traits::size_type size_type; size_type ms(m), ns(n); // shouldn't be needed :-! matrix_type A(ms, ns); matrix::inserter<matrix_type, update_plus<value_type> > ins(A, size_type(size(rows) / m + 1)); for (std::size_t i= 0; i < size(rows); i++) if (values[i] != value_type(0)) ins[rows[i]][cols[i]] << values[i]; return A; }
void backward_eval_loop(const TT& const_first_eval, const UU& const_second_eval, boost::mpl::false_) { vampir_trace<6003> tracer; // hope there is a more elegant way; copying the arguments causes errors due to double destructor evaluation TT& first_eval= const_cast<TT&>(const_first_eval); UU& second_eval= const_cast<UU&>(const_second_eval); MTL_DEBUG_THROW_IF(mtl::vector::size(first_eval) != mtl::vector::size(second_eval), incompatible_size()); for (std::size_t i= size(first_eval); i-- > 0; ) { // std::cout << "i is " << i << "\n"; first_eval(i); second_eval(i); } }
inline void matrix_copy_ele_times(const MatrixSrc& src, MatrixDest& dest) { MTL_THROW_IF(num_rows(src) != num_rows(dest) || num_cols(src) != num_cols(dest), incompatible_size()); typename traits::row<MatrixDest>::type row(dest); typename traits::col<MatrixDest>::type col(dest); typename traits::value<MatrixDest>::type value(dest); typedef typename traits::range_generator<tag::major, MatrixDest>::type cursor_type; typedef typename traits::range_generator<tag::nz, cursor_type>::type icursor_type; for (cursor_type cursor = begin<tag::major>(dest), cend = end<tag::major>(dest); cursor != cend; ++cursor) for (icursor_type icursor = begin<tag::nz>(cursor), icend = end<tag::nz>(cursor); icursor != icend; ++icursor) value(*icursor, value(*icursor) * src[row(*icursor)][col(*icursor)]); #if 0 // copy would result in a*0 = a and 0*b = b!!!! gen_matrix_copy< operations::update_times<typename MatrixDest::value_type> >(src, dest, false); #endif crop(dest); }
void forward_eval_loop(const TT& const_first_eval, const UU& const_second_eval, boost::mpl::true_) { vampir_trace<6002> tracer; // hope there is a more elegant way; copying the arguments causes errors due to double destructor evaluation TT& first_eval= const_cast<TT&>(const_first_eval); UU& second_eval= const_cast<UU&>(const_second_eval); MTL_DEBUG_THROW_IF(mtl::vec::size(first_eval) != mtl::vec::size(second_eval), incompatible_size()); const std::size_t s= size(first_eval), sb= s >> 2 << 2; for (std::size_t i= 0; i < sb; i+= 4) { first_eval.template at<0>(i); second_eval.template at<0>(i); first_eval.template at<1>(i); second_eval.template at<1>(i); first_eval.template at<2>(i); second_eval.template at<2>(i); first_eval.template at<3>(i); second_eval.template at<3>(i); } for (std::size_t i= sb; i < s; i++) { first_eval(i); second_eval(i); } }
void backward_eval_loop(const TT& const_first_eval, const UU& const_second_eval, boost::mpl::true_) { vampir_trace<6004> tracer; // hope there is a more elegant way; copying the arguments causes errors due to double destructor evaluation TT& first_eval= const_cast<TT&>(const_first_eval); UU& second_eval= const_cast<UU&>(const_second_eval); MTL_DEBUG_THROW_IF(mtl::size(first_eval) != mtl::size(second_eval), incompatible_size()); std::size_t s= size(first_eval), i= s-1, m= s % 4; for (; m; m--) { // std::cout << "i is " << i << "\n"; first_eval(i); second_eval(i--); } for(long j= i - 3; j >= 0; j-= 4) { // std::cout << "i is " << j+3 << ".." << j << "\n"; first_eval.template at<3>(j); second_eval.template at<3>(j); first_eval.template at<2>(j); second_eval.template at<2>(j); first_eval.template at<1>(j); second_eval.template at<1>(j); first_eval.template at<0>(j); second_eval.template at<0>(j); } }
inline void gen_vector_copy(const VectorSrc& src, VectorDest& dest, bool with_reset) { // Works only with dense vectors as dest !!!!! (source could be sparse) // Needs vector inserter BOOST_STATIC_ASSERT((boost::is_same<typename ashape::ashape<VectorSrc>::type, typename ashape::ashape<VectorDest>::type>::value)); MTL_THROW_IF(size(src) != size(dest), incompatible_size()); if (with_reset) detail::zero_with_sparse_src(dest, typename traits::category<VectorSrc>::type()); typename traits::index<VectorSrc>::type index(src); typename traits::const_value<VectorSrc>::type value(src); typedef typename traits::range_generator<tag::nz, VectorSrc>::type cursor_type; for (cursor_type cursor = begin<tag::nz>(src), cend = end<tag::nz>(src); cursor != cend; ++cursor) Updater()(dest[index(*cursor)], value(*cursor)); }
// Either changed matrix is uninitialized (i.e. 0x0) or dimensions are equal void check_dim(size_type num_rows, size_type num_cols) const { MTL_DEBUG_THROW_IF(this->num_rows() * this->num_cols() != 0 && (this->num_rows() != num_rows || this->num_cols() != num_cols), incompatible_size()); }