00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #ifndef MTL_MULT_INCLUDE
00013 #define MTL_MULT_INCLUDE
00014
00015 #include <boost/numeric/mtl/concept/collection.hpp>
00016 #include <boost/numeric/mtl/utility/category.hpp>
00017 #include <boost/numeric/mtl/utility/ashape.hpp>
00018 #include <boost/numeric/mtl/utility/exception.hpp>
00019 #include <boost/numeric/mtl/operation/dmat_dmat_mult.hpp>
00020 #include <boost/numeric/mtl/operation/smat_smat_mult.hpp>
00021 #include <boost/numeric/mtl/operation/smat_dmat_mult.hpp>
00022 #include <boost/numeric/mtl/operation/mat_vec_mult.hpp>
00023 #include <boost/numeric/mtl/operation/mult_specialize.hpp>
00024 #include <boost/numeric/mtl/operation/assign_mode.hpp>
00025 #include <boost/numeric/mtl/operation/mult_assign_mode.hpp>
00026 #include <boost/numeric/mtl/utility/enable_if.hpp>
00027 #include <boost/static_assert.hpp>
00028 #include <boost/mpl/if.hpp>
00029
00030
00031
00032
00033 namespace mtl { namespace vector {
00034
00035
00036
00037 }}
00038
00039
00040
00041 namespace mtl { namespace matrix {
00042
00043
00045
00047 template <typename A, typename B, typename C>
00048 typename mtl::traits::enable_if_matrix<A>::type
00049 inline mult(const A& a, const B& b, C& c)
00050 {
00051 #if 1
00052 MTL_THROW_IF((void*)&a == (void*)&c || (void*)&b == (void*)&c, argument_result_conflict());
00053 #endif
00054
00055
00056 using mtl::traits::category;
00057 gen_mult(a, b, c, assign::assign_sum(), typename category<A>::type(),
00058 typename category<B>::type(), typename category<C>::type());
00059 }
00060
00061
00063
00065 template <typename A, typename B, typename C>
00066 typename mtl::traits::enable_if_matrix<A>::type
00067 inline mult_add(const A& a, const B& b, C& c)
00068 {
00069
00070 using mtl::traits::category;
00071 gen_mult(a, b, c, assign::plus_sum(), typename category<A>::type(),
00072 typename category<B>::type(), typename category<C>::type());
00073 }
00074
00075
00077
00079 template <typename A, typename X, typename Y, typename Z>
00080 inline void mult(const A& a, const X& x, const Y& y, Z& z)
00081 {
00082 mult(a, x, z);
00083 z+= y;
00084 }
00085
00086
00087
00088 template <typename MatrixA, typename MatrixB, typename MatrixC, typename Assign>
00089 inline void gen_mult(const MatrixA& a, const MatrixB& b, MatrixC& c, Assign, tag::matrix, tag::matrix, tag::matrix)
00090 {
00091 #if 1
00092 MTL_THROW_IF((void*)&a == (void*)&c || (void*)&b == (void*)&c, argument_result_conflict());
00093 #else
00094 if ((void*)&a == (void*)&c || (void*)&b == (void*)&c) {
00095 C tmp(num_rows(c), num_cols(c));
00096 mult(a, b, tmp);
00097 swap(C, tmp);
00098 return;
00099 }
00100 #endif
00101
00102 MTL_THROW_IF(num_rows(a) != num_rows(c) || num_cols(a) != num_rows(b) || num_cols(b) != num_cols(c),
00103 incompatible_size());
00104
00105 using mtl::traits::category;
00106 mat_mat_mult(a, b, c, Assign(), typename category<MatrixA>::type(),
00107 typename category<MatrixB>::type(), typename category<MatrixC>::type());
00108 }
00109
00110
00112
00123 template <typename MatrixA, typename MatrixB, typename MatrixC, typename Assign>
00124 inline void mat_mat_mult(const MatrixA& a, const MatrixB& b, MatrixC& c, Assign, tag::dense, tag::dense, tag::dense)
00125 {
00126 using assign::plus_sum; using assign::assign_sum;
00127
00128 static const unsigned long tiling1= detail::dmat_dmat_mult_tiling1<MatrixA, MatrixB, MatrixC>::value;
00129 static const unsigned long tiling2= detail::dmat_dmat_mult_tiling2<MatrixA, MatrixB, MatrixC>::value;
00130 typedef gen_tiling_dmat_dmat_mult_t<tiling1, tiling2, plus_sum> tiling_mult_t;
00131
00132 typedef gen_platform_dmat_dmat_mult_t<plus_sum, tiling_mult_t> platform_mult_t;
00133 typedef gen_recursive_dmat_dmat_mult_t<platform_mult_t> recursive_mult_t;
00134 typedef gen_blas_dmat_dmat_mult_t<assign_sum, recursive_mult_t> blas_mult_t;
00135 typedef size_switch_dmat_dmat_mult_t<straight_dmat_dmat_mult_limit, tiling_mult_t, blas_mult_t> variable_size_t;
00136
00137 typedef fully_unroll_fixes_size_dmat_dmat_mult_t<Assign> fully_unroll_t;
00138 typedef size_switch_dmat_dmat_mult_t<fully_unroll_dmat_dmat_mult_limit, fully_unroll_t, tiling_mult_t> fixes_size_t;
00139
00140 static const bool all_static= mtl::traits::is_static<MatrixA>::value && mtl::traits::is_static<MatrixB>::value
00141 && mtl::traits::is_static<MatrixC>::value;
00142 typedef static_switch_dmat_dmat_mult_t<all_static, fixes_size_t, variable_size_t> default_functor_t;
00143
00145 typedef typename boost::mpl::if_<
00146 detail::dmat_dmat_mult_specialize<MatrixA, MatrixB, MatrixC>
00147 , typename detail::dmat_dmat_mult_specialize<MatrixA, MatrixB, MatrixC>::type
00148 , default_functor_t
00149 >::type raw_functor_type;
00150
00152 typename assign::mult_assign_mode<raw_functor_type, Assign>::type functor;
00153
00154 functor(a, b, c);
00155 }
00156
00157 template <typename MatrixA, typename MatrixB, typename MatrixC, typename Assign>
00158 inline void mat_mat_mult(const MatrixA& a, const MatrixB& b, MatrixC& c, Assign, tag::dense, tag::dense, tag::sparse)
00159 {
00160
00161
00162 dense2D<typename Collection<MatrixC>::value_type, matrix::parameters<> > c_copy(num_rows(c), num_cols(c));
00163 c_copy= c;
00164 mat_mat_mult(a, b, c_copy, Assign(), tag::dense(), tag::dense(), tag::dense());
00165 c= c_copy;
00166 }
00167
00169 template <typename MatrixA, typename MatrixB, typename MatrixC, typename Assign>
00170 inline void mat_mat_mult(const MatrixA& a, const MatrixB& b, MatrixC& c, Assign, tag::sparse, tag::sparse, tag::sparse)
00171 {
00172 smat_smat_mult(a, b, c, Assign(), typename OrientedCollection<MatrixA>::orientation(),
00173 typename OrientedCollection<MatrixB>::orientation());
00174 }
00175
00176 template <typename MatrixA, typename MatrixB, typename MatrixC, typename Assign>
00177 inline void mat_mat_mult(const MatrixA& a, const MatrixB& b, MatrixC& c, Assign, tag::sparse, tag::sparse, tag::dense)
00178 {
00179
00180
00181 compressed2D<typename Collection<MatrixC>::value_type, matrix::parameters<> > c_copy(num_rows(c), num_cols(c));
00182 c_copy= c;
00183 smat_smat_mult(a, b, c_copy, Assign(), typename OrientedCollection<MatrixA>::orientation(),
00184 typename OrientedCollection<MatrixB>::orientation());
00185 c= c_copy;
00186 }
00187
00189
00195 template <typename MatrixA, typename MatrixB, typename MatrixC, typename Assign>
00196 inline void mat_mat_mult(const MatrixA& a, const MatrixB& b, MatrixC& c, Assign, tag::sparse, tag::dense, tag::dense)
00197 {
00198 using assign::plus_sum; using assign::assign_sum;
00199 using namespace functor;
00200
00201
00202
00203
00204 typedef gen_tiling_smat_dmat_mult<8, Assign> default_functor_t;
00205
00206
00207
00208
00209 default_functor_t functor;
00210 functor(a, b, c);
00211 }
00212
00213 template <typename MatrixA, typename MatrixB, typename MatrixC, typename Assign>
00214 inline void mat_mat_mult(const MatrixA& a, const MatrixB& b, MatrixC& c, Assign, tag::sparse, tag::dense, tag::sparse)
00215 {
00216
00217
00218 dense2D<typename Collection<MatrixC>::value_type, matrix::parameters<> > c_copy(num_rows(c), num_cols(c));
00219 c_copy= c;
00220 mat_mat_mult(a, b, c_copy, Assign(), tag::sparse(), tag::dense(), tag::dense());
00221 c= c_copy;
00222 }
00223
00224
00225 template <typename MatrixA, typename MatrixB, typename MatrixC, typename Assign>
00226 inline void mat_mat_mult(const MatrixA& a, const MatrixB& b, MatrixC& c, Assign, tag::dense, tag::sparse, tag::dense)
00227 {
00228
00229
00230
00231 compressed2D<typename Collection<MatrixA>::value_type, matrix::parameters<> > a_copy(num_rows(a), num_cols(a));
00232 a_copy= a;
00233 compressed2D<typename Collection<MatrixC>::value_type, matrix::parameters<> > c_copy(num_rows(c), num_cols(c));
00234 c_copy= c;
00235 mat_mat_mult(a_copy, b, c_copy, Assign(), tag::sparse(), tag::sparse(), tag::sparse());
00236 c= c_copy;
00237 }
00238
00239
00240
00241 template <typename MatrixA, typename MatrixB, typename MatrixC, typename Assign>
00242 inline void mat_mat_mult(const MatrixA& a, const MatrixB& b, MatrixC& c, Assign, tag::dense, tag::sparse, tag::sparse)
00243 {
00244
00245
00246 compressed2D<typename Collection<MatrixA>::value_type, matrix::parameters<> > a_copy(num_rows(a), num_cols(a));
00247 a_copy= a;
00248 mat_mat_mult(a_copy, b, c, Assign(), tag::sparse(), tag::sparse(), tag::sparse());
00249 }
00250
00251
00252
00253
00254 template <typename Matrix, typename VectorIn, typename VectorOut, typename Assign>
00255 inline void gen_mult(const Matrix& a, const VectorIn& v, VectorOut& w, Assign, tag::matrix, tag::vector, tag::vector)
00256 {
00257
00258
00259
00260
00261
00262 BOOST_STATIC_ASSERT((boost::is_same< typename ashape::mult_op<typename ashape::ashape<Matrix>::type,
00263 typename ashape::ashape<VectorIn>::type >::type,
00264 ::mtl::ashape::mat_cvec_mult
00265 >::value));
00266
00267
00268 #if 1
00269 MTL_THROW_IF((void*)&v == (void*)&w, argument_result_conflict());
00270 #else
00271 if ((void*)&v == (void*)&w) {
00272 VectorOut tmp(size(w));
00273 mult(a, b, tmp);
00274 swap(w, tmp);
00275 return;
00276 }
00277 #endif
00278 w.checked_change_dim(num_rows(a));
00279 if(num_rows(a) != size(w) || num_cols(a) != size(v))
00280 std::cout << "num_rows(a) is " << num_rows(a) << ", size(w) is " << size(w)
00281 << ", num_cols(a) is " << num_cols(a) << ", size(v) is " << size(v) << "\n";
00282 MTL_THROW_IF(num_rows(a) != size(w) || num_cols(a) != size(v), incompatible_size());
00283
00284
00285 using mtl::traits::category;
00286
00287 mat_cvec_mult(a, v, w, Assign(), typename category<Matrix>::type());
00288 }
00289
00290
00291
00292 }}
00293
00294 #endif // MTL_MULT_INCLUDE