00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #ifndef MTL_MAT_VEC_MULT_INCLUDE
00013 #define MTL_MAT_VEC_MULT_INCLUDE
00014
00015 #include <cassert>
00016 #include <iostream>
00017 #include <boost/mpl/bool.hpp>
00018
00019 #include <boost/numeric/mtl/utility/property_map.hpp>
00020 #include <boost/numeric/mtl/utility/tag.hpp>
00021 #include <boost/numeric/mtl/detail/index.hpp>
00022 #include <boost/numeric/mtl/utility/tag.hpp>
00023 #include <boost/numeric/mtl/operation/set_to_zero.hpp>
00024 #include <boost/numeric/mtl/operation/update.hpp>
00025 #include <boost/numeric/linear_algebra/identity.hpp>
00026 #include <boost/numeric/meta_math/loop.hpp>
00027
00028
00029 namespace mtl { namespace matrix {
00030
00031 namespace impl {
00032
00033 template <std::size_t Index0, std::size_t Max0, std::size_t Index1, std::size_t Max1, typename Assign>
00034 struct fully_unroll_mat_cvec_mult
00035 : public meta_math::loop2<Index0, Max0, Index1, Max1>
00036 {
00037 typedef meta_math::loop2<Index0, Max0, Index1, Max1> base;
00038 typedef fully_unroll_mat_cvec_mult<base::next_index0, Max0, base::next_index1, Max1, Assign> next_t;
00039
00040 template <typename Matrix, typename VectorIn, typename VectorOut>
00041 static inline void apply(const Matrix& A, const VectorIn& v, VectorOut& w)
00042 {
00043 Assign::update(w[base::index0], A[base::index0][base::index1] * v[base::index1]);
00044 next_t::apply(A, v, w);
00045 }
00046 };
00047
00048 template <std::size_t Max0, std::size_t Max1, typename Assign>
00049 struct fully_unroll_mat_cvec_mult<Max0, Max0, Max1, Max1, Assign>
00050 : public meta_math::loop2<Max0, Max0, Max1, Max1>
00051 {
00052 typedef meta_math::loop2<Max0, Max0, Max1, Max1> base;
00053
00054 template <typename Matrix, typename VectorIn, typename VectorOut>
00055 static inline void apply(const Matrix& A, const VectorIn& v, VectorOut& w)
00056 {
00057 Assign::update(w[base::index0], A[base::index0][base::index1] * v[base::index1]);
00058 }
00059 };
00060
00061 struct noop
00062 {
00063 template <typename Matrix, typename VectorIn, typename VectorOut>
00064 static inline void apply(const Matrix& A, const VectorIn& v, VectorOut& w) {}
00065 };
00066 }
00067
00068
00069 template <typename Matrix, typename VectorIn, typename VectorOut, typename Assign>
00070 inline void dense_mat_cvec_mult(const Matrix& A, const VectorIn& v, VectorOut& w, Assign, boost::mpl::true_)
00071 {
00072 typedef typename static_num_rows<Matrix>::type size_type;
00073 static const size_type rows_a= static_num_rows<Matrix>::value, cols_a= static_num_cols<Matrix>::value;
00074
00075 assert(rows_a > 0 && cols_a > 0);
00076
00077 for (size_type i= 0; i < rows_a; i++)
00078 Assign::first_update(w[i], A[i][0] * v[0]);
00079
00080
00081 typedef impl::fully_unroll_mat_cvec_mult<1, rows_a, 2, cols_a, Assign> f2;
00082 typedef typename boost::mpl::if_c<(cols_a > 1), f2, impl::noop>::type f3;
00083 f3::apply(A, v, w);
00084 }
00085
00086
00087 template <typename Matrix, typename VectorIn, typename VectorOut, typename Assign>
00088 inline void dense_mat_cvec_mult(const Matrix& A, const VectorIn& v, VectorOut& w, Assign, boost::mpl::false_)
00089 {
00090
00091
00092 using math::zero; using mtl::vector::set_to_zero;
00093 if (size(w) == 0) return;
00094
00095 if (Assign::init_to_zero) set_to_zero(w);
00096
00097 typedef typename Collection<VectorOut>::value_type value_type;
00098
00099 for (unsigned i= 0; i < num_rows(A); i++) {
00100 value_type tmp= zero(w[i]);
00101 for (unsigned j= 0; j < num_cols(A); j++)
00102 tmp+= A[i][j] * v[j];
00103 Assign::update(w[i], tmp);
00104 }
00105 }
00106
00107
00108 template <typename Matrix, typename VectorIn, typename VectorOut, typename Assign>
00109 inline void mat_cvec_mult(const Matrix& A, const VectorIn& v, VectorOut& w, Assign, tag::dense)
00110 {
00111 # ifdef MTL_NOT_UNROLL_FSIZE_MAT_VEC_MULT
00112 boost::mpl::false_ selector;
00113 # else
00114 mtl::traits::is_static<Matrix> selector;
00115 # endif
00116 dense_mat_cvec_mult(A, v, w, Assign(), selector);
00117 }
00118
00119
00120 template <typename Matrix, typename VectorIn, typename VectorOut, typename Assign>
00121 inline void mat_cvec_mult(const Matrix& A, const VectorIn& v, VectorOut& w, Assign, tag::multi_vector)
00122 {
00123 if (Assign::init_to_zero) set_to_zero(w);
00124 for (unsigned i= 0; i < num_cols(A); i++)
00125 Assign::update(w, A.vector(i) * v[i]);
00126 }
00127
00128
00129 template <typename TransposedMatrix, typename VectorIn, typename VectorOut, typename Assign>
00130 inline void mat_cvec_mult(const TransposedMatrix& A, const VectorIn& v, VectorOut& w, Assign, tag::transposed_multi_vector)
00131 {
00132 typename TransposedMatrix::const_ref_type B= A.ref;
00133
00134 if (Assign::init_to_zero) set_to_zero(w);
00135 for (unsigned i= 0; i < num_cols(B); i++)
00136 Assign::update(w[i], dot_real(B.vector(i), v));
00137 }
00138
00139
00140 template <typename HermitianMatrix, typename VectorIn, typename VectorOut, typename Assign>
00141 inline void mat_cvec_mult(const HermitianMatrix& A, const VectorIn& v, VectorOut& w, Assign, tag::hermitian_multi_vector)
00142 {
00143 typename HermitianMatrix::const_ref_type B= A.const_ref();
00144
00145 if (Assign::init_to_zero) set_to_zero(w);
00146 for (unsigned i= 0; i < num_cols(B); i++)
00147 Assign::update(w[i], dot(B.vector(i), v));
00148 }
00149
00150
00151
00152 template <typename Matrix, typename VectorIn, typename VectorOut, typename Assign>
00153 inline void mat_cvec_mult(const Matrix& A, const VectorIn& v, VectorOut& w, Assign, tag::sparse)
00154 {
00155 smat_cvec_mult(A, v, w, Assign(), typename OrientedCollection<Matrix>::orientation());
00156 }
00157
00158
00159
00160
00161 template <typename Matrix, typename VectorIn, typename VectorOut, typename Assign>
00162 inline void smat_cvec_mult(const Matrix& A, const VectorIn& v, VectorOut& w, Assign, tag::row_major)
00163 {
00164 using namespace tag;
00165 using mtl::traits::range_generator;
00166 using math::zero;
00167 using mtl::vector::set_to_zero;
00168
00169 typedef typename range_generator<row, Matrix>::type a_cur_type;
00170 typedef typename range_generator<nz, a_cur_type>::type a_icur_type;
00171 typename mtl::traits::col<Matrix>::type col_a(A);
00172 typename mtl::traits::const_value<Matrix>::type value_a(A);
00173
00174 if (Assign::init_to_zero) set_to_zero(w);
00175
00176 typedef typename Collection<VectorOut>::value_type value_type;
00177
00178 a_cur_type ac= begin<row>(A), aend= end<row>(A);
00179 for (unsigned i= 0; ac != aend; ++ac, ++i) {
00180 value_type tmp= zero(w[i]);
00181 for (a_icur_type aic= begin<nz>(ac), aiend= end<nz>(ac); aic != aiend; ++aic)
00182 tmp+= value_a(*aic) * v[col_a(*aic)];
00183 Assign::update(w[i], tmp);
00184 }
00185 }
00186
00187
00188 template <typename Matrix, typename VectorIn, typename VectorOut, typename Assign>
00189 inline void smat_cvec_mult(const Matrix& A, const VectorIn& v, VectorOut& w, Assign, tag::col_major)
00190 {
00191 using namespace tag; namespace traits = mtl::traits;
00192 using traits::range_generator;
00193 using mtl::vector::set_to_zero;
00194 typedef typename range_generator<col, Matrix>::type a_cur_type;
00195 typedef typename range_generator<nz, a_cur_type>::type a_icur_type;
00196
00197 typename traits::row<Matrix>::type row_a(A);
00198 typename traits::const_value<Matrix>::type value_a(A);
00199
00200 if (Assign::init_to_zero) set_to_zero(w);
00201
00202 unsigned rv= 0;
00203 for (a_cur_type ac= begin<col>(A), aend= end<col>(A); ac != aend; ++ac, ++rv) {
00204 typename Collection<VectorIn>::value_type vv= v[rv];
00205 for (a_icur_type aic= begin<nz>(ac), aiend= end<nz>(ac); aic != aiend; ++aic)
00206 Assign::update(w[row_a(*aic)], value_a(*aic) * vv);
00207 }
00208 }
00209
00210
00211 }}
00212
00213
00214
00215
00216 #endif // MTL_MAT_VEC_MULT_INCLUDE
00217