00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #ifndef MTL_CRTP_BASE_MATRIX_INCLUDE
00013 #define MTL_CRTP_BASE_MATRIX_INCLUDE
00014
00015 #include <iostream>
00016 #include <algorithm>
00017 #include <boost/mpl/bool.hpp>
00018 #include <boost/utility/enable_if.hpp>
00019 #include <boost/numeric/mtl/operation/print.hpp>
00020
00021 #include <boost/numeric/mtl/mtl_fwd.hpp>
00022 #include <boost/numeric/mtl/concept/collection.hpp>
00023 #include <boost/numeric/mtl/operation/matrix_bracket.hpp>
00024 #include <boost/numeric/mtl/operation/copy.hpp>
00025 #include <boost/numeric/mtl/operation/mult.hpp>
00026 #include <boost/numeric/mtl/operation/right_scale_inplace.hpp>
00027 #include <boost/numeric/mtl/operation/divide_by_inplace.hpp>
00028 #include <boost/numeric/mtl/matrix/all_mat_expr.hpp>
00029 #include <boost/numeric/mtl/matrix/diagonal_setup.hpp>
00030 #include <boost/numeric/mtl/matrix/inserter.hpp>
00031 #include <boost/numeric/mtl/utility/tag.hpp>
00032 #include <boost/numeric/mtl/utility/ashape.hpp>
00033 #include <boost/numeric/mtl/utility/exception.hpp>
00034 #include <boost/numeric/mtl/utility/eval_dense.hpp>
00035 #include <boost/numeric/mtl/utility/irange.hpp>
00036 #include <boost/numeric/mtl/operation/mult_assign_mode.hpp>
00037 #include <boost/numeric/mtl/operation/compute_factors.hpp>
00038
00039 namespace mtl { namespace matrix {
00040
00041 template <typename Source, typename Matrix>
00042 struct crtp_assign
00043 {
00044 Matrix& operator()(const Source& source, Matrix& matrix)
00045 {
00046 return assign(source, matrix, typename ashape::ashape<Source>::type());
00047 }
00048 private:
00050
00051 Matrix& assign(const Source& source, Matrix& matrix, ashape::scal)
00052 {
00053 MTL_DEBUG_THROW_IF(num_rows(matrix) * num_cols(matrix) == 0,
00054 range_error("Trying to initialize a 0 by 0 matrix with a value"));
00055 diagonal_setup(matrix, source);
00056 return matrix;
00057 }
00058
00060 Matrix& assign(const Source& source, Matrix& matrix, typename ashape::ashape<Matrix>::type)
00061 {
00062
00063 matrix.checked_change_dim(num_rows(source), num_cols(source));
00064 matrix_copy(source, matrix);
00065 return matrix;
00066 }
00067 };
00068
00069
00070
00072
00073
00074 template <typename E1, typename E2, typename Matrix>
00075 struct crtp_assign<mat_mat_plus_expr<E1, E2>, Matrix>
00076 {
00077 Matrix& operator()(const mat_mat_plus_expr<E1, E2>& src, Matrix& matrix)
00078 {
00079 matrix.checked_change_dim(num_rows(src.first), num_cols(src.first));
00080 matrix= src.first;
00081 return matrix+= src.second;
00082 }
00083 };
00084
00086
00087
00088 template <typename E1, typename E2, typename Matrix>
00089 struct crtp_assign<mat_mat_minus_expr<E1, E2>, Matrix>
00090 {
00091 Matrix& operator()(const mat_mat_minus_expr<E1, E2>& src, Matrix& matrix)
00092 {
00093 matrix.checked_change_dim(num_rows(src.first), num_cols(src.first));
00094 matrix= src.first;
00095 return matrix-= src.second;
00096 }
00097 };
00098
00100 template <typename E1, typename E2, typename Matrix>
00101 struct crtp_assign<mat_mat_times_expr<E1, E2>, Matrix>
00102 {
00103 Matrix& operator()(const mat_mat_times_expr<E1, E2>& src, Matrix& matrix)
00104 {
00105 operation::compute_factors<Matrix, mat_mat_times_expr<E1, E2> > factors(src);
00106
00107 matrix.checked_change_dim(num_rows(factors.first), num_cols(factors.second));
00108 mult(factors.first, factors.second, matrix);
00109 return matrix;
00110 }
00111 };
00112
00113
00115 template <typename E1, typename E2, typename Matrix>
00116 struct crtp_assign<mat_mat_ele_times_expr<E1, E2>, Matrix>
00117 {
00118 Matrix& operator()(const mat_mat_ele_times_expr<E1, E2>& src, Matrix& matrix)
00119 {
00120 operation::compute_factors<Matrix, mat_mat_ele_times_expr<E1, E2> > factors(src);
00121 matrix.checked_change_dim(num_rows(factors.first), num_cols(factors.first));
00122 matrix= factors.first;
00123 return matrix.ele_rscale(factors.second);
00124 }
00125 };
00126
00127
00128
00130 template <typename Value, unsigned Rows, unsigned Cols, typename Matrix>
00131 struct crtp_assign<Value[Rows][Cols], Matrix>
00132 {
00133 Matrix& operator()(const Value src[Rows][Cols], Matrix& matrix)
00134 {
00135 typedef typename Collection<Matrix>::size_type size_type;
00136
00137 matrix.checked_change_dim(Rows, Cols);
00138 inserter<Matrix> ins(matrix);
00139
00140 for (size_type r= 0; r < Rows; ++r)
00141 for (size_type c= 0; c < Cols; ++c)
00142 ins(r, c) << src[r][c];
00143 return matrix;
00144 }
00145 };
00146
00147
00148 template <typename Vector, typename Matrix>
00149 struct crtp_assign<multi_vector<Vector>, Matrix>
00150 {
00151 Matrix& operator()(const multi_vector<Vector>& src, Matrix& matrix)
00152 {
00153 typedef typename Collection<Matrix>::size_type size_type;
00154
00155 matrix.checked_change_dim(num_rows(src), num_cols(src));
00156 inserter<Matrix> ins(matrix);
00157
00158 for (size_type r= 0; r < num_rows(src); ++r)
00159 for (size_type c= 0; c < num_cols(src); ++c)
00160 ins(r, c) << src[r][c];
00161 return matrix;
00162 }
00163 };
00164
00165
00167 template <typename IFStream, typename OFStream, typename Matrix>
00168 struct crtp_assign<io::matrix_file<IFStream, OFStream>, Matrix>
00169 {
00170 Matrix& operator()(const io::matrix_file<IFStream, OFStream>& file, Matrix& matrix)
00171 {
00172 IFStream stream(file.file_name().c_str());
00173 stream >> matrix;
00174 return matrix;
00175 }
00176 };
00177
00179 template <typename Source, typename Matrix>
00180 struct crtp_plus_assign
00181 {
00182 Matrix& operator()(const Source& source, Matrix& matrix)
00183 {
00184 return assign(source, matrix, typename ashape::ashape<Source>::type());
00185 }
00186 private:
00187 Matrix& assign(const Source& source, Matrix& matrix, typename ashape::ashape<Matrix>::type)
00188 {
00189 matrix_copy_plus(source, matrix);
00190 return matrix;
00191 }
00192 };
00193
00195
00198 template <typename E1, typename E2, typename Matrix>
00199 struct crtp_plus_assign<mat_mat_plus_expr<E1, E2>, Matrix>
00200 {
00201 Matrix& operator()(const mat_mat_plus_expr<E1, E2>& src, Matrix& matrix)
00202 {
00203 matrix+= src.first;
00204 return matrix+= src.second;
00205 }
00206 };
00207
00208 template <typename E1, typename E2, typename Matrix>
00209 struct crtp_plus_assign<mat_mat_minus_expr<E1, E2>, Matrix>
00210 {
00211 Matrix& operator()(const mat_mat_minus_expr<E1, E2>& src, Matrix& matrix)
00212 {
00213 matrix+= src.first;
00214 return matrix-= src.second;
00215 }
00216 };
00217
00218 template <typename E1, typename E2, typename Matrix>
00219 struct crtp_plus_assign<mat_mat_ele_times_expr<E1, E2>, Matrix>
00220 {
00221 Matrix& operator()(const mat_mat_ele_times_expr<E1, E2>& src, Matrix& matrix)
00222 {
00223 Matrix Prod(ele_prod(src.first, src.second));
00224 return matrix+= Prod;
00225 }
00226 };
00227
00228 template <typename E1, typename E2, typename Matrix>
00229 struct crtp_plus_assign<mat_mat_times_expr<E1, E2>, Matrix>
00230 {
00231 Matrix& operator()(const mat_mat_times_expr<E1, E2>& src, Matrix& matrix)
00232 {
00233 operation::compute_factors<Matrix, mat_mat_times_expr<E1, E2> > factors(src);
00234 gen_mult(factors.first, factors.second, matrix, assign::plus_sum(), tag::matrix(), tag::matrix(), tag::matrix());
00235 return matrix;
00236 }
00237 };
00238
00239
00241 template <typename Source, typename Matrix>
00242 struct crtp_minus_assign
00243 {
00244 Matrix& operator()(const Source& source, Matrix& matrix)
00245 {
00246 return assign(source, matrix, typename ashape::ashape<Source>::type());
00247 }
00248 private:
00249 Matrix& assign(const Source& source, Matrix& matrix, typename ashape::ashape<Matrix>::type)
00250 {
00251 matrix_copy_minus(source, matrix);
00252 return matrix;
00253 }
00254 };
00255
00257
00260 template <typename E1, typename E2, typename Matrix>
00261 struct crtp_minus_assign<mat_mat_plus_expr<E1, E2>, Matrix>
00262 {
00263 Matrix& operator()(const mat_mat_plus_expr<E1, E2>& src, Matrix& matrix)
00264 {
00265 matrix-= src.first;
00266 return matrix-= src.second;
00267 }
00268 };
00269
00271
00274 template <typename E1, typename E2, typename Matrix>
00275 struct crtp_minus_assign<mat_mat_minus_expr<E1, E2>, Matrix>
00276 {
00277 Matrix& operator()(const mat_mat_minus_expr<E1, E2>& src, Matrix& matrix)
00278 {
00279 matrix-= src.first;
00280 return matrix+= src.second;
00281 }
00282 };
00283
00284 template <typename E1, typename E2, typename Matrix>
00285 struct crtp_minus_assign<mat_mat_ele_times_expr<E1, E2>, Matrix>
00286 {
00287 Matrix& operator()(const mat_mat_ele_times_expr<E1, E2>& src, Matrix& matrix)
00288 {
00289 Matrix Prod(ele_prod(src.first, src.second));
00290 return matrix-= Prod;
00291 }
00292 };
00293
00295
00296 template <typename E1, typename E2, typename Matrix>
00297 struct crtp_minus_assign<mat_mat_times_expr<E1, E2>, Matrix>
00298 {
00299 Matrix& operator()(const mat_mat_times_expr<E1, E2>& src, Matrix& matrix)
00300 {
00301 operation::compute_factors<Matrix, mat_mat_times_expr<E1, E2> > factors(src);
00302 gen_mult(factors.first, factors.second, matrix, assign::minus_sum(), tag::matrix(), tag::matrix(), tag::matrix());
00303 return matrix;
00304 }
00305 };
00306
00307
00308
00310 template <typename Matrix, typename ValueType, typename SizeType>
00311 struct crtp_matrix_assign
00312 {
00313 private:
00314
00315
00316 template <typename Source>
00317 Matrix& density_assign(const Source& src, boost::mpl::true_)
00318 {
00319
00320 typedef unsigned size_type;
00321
00322
00323 checked_change_dim(num_rows(src), num_cols(src));
00324
00325 Matrix& matrix= static_cast<Matrix&>(*this);
00326 for (size_type r= 0; r < num_rows(matrix); ++r)
00327 for (size_type c= 0; c < num_cols(matrix); ++c)
00328 matrix[r][c]= src[r][c];
00329 return matrix;
00330 }
00331
00332
00333 template <typename Source>
00334 Matrix& density_assign(const Source& src, boost::mpl::false_)
00335 {
00336
00337 return crtp_assign<Source, Matrix>()(src, static_cast<Matrix&>(*this));
00338 }
00339
00340
00341
00342 template <typename Source>
00343 Matrix& density_plus_assign(const Source& src, boost::mpl::true_)
00344 {
00345
00346 typedef unsigned size_type;
00347
00348
00349 checked_change_dim(num_rows(src), num_cols(src));
00350
00351 Matrix& matrix= static_cast<Matrix&>(*this);
00352 for (size_type r= 0; r < num_rows(matrix); ++r)
00353 for (size_type c= 0; c < num_cols(matrix); ++c)
00354 matrix[r][c]+= src[r][c];
00355 return matrix;
00356 }
00357
00358
00359 template <typename Source>
00360 Matrix& density_plus_assign(const Source& src, boost::mpl::false_)
00361 {
00362
00363 return crtp_plus_assign<Source, Matrix>()(src, static_cast<Matrix&>(*this));
00364 }
00365
00366
00367 template <typename Source>
00368 Matrix& density_minus_assign(const Source& src, boost::mpl::true_)
00369 {
00370
00371 typedef unsigned size_type;
00372
00373
00374 checked_change_dim(num_rows(src), num_cols(src));
00375
00376 Matrix& matrix= static_cast<Matrix&>(*this);
00377 for (size_type r= 0; r < num_rows(matrix); ++r)
00378 for (size_type c= 0; c < num_cols(matrix); ++c)
00379 matrix[r][c]-= src[r][c];
00380 return matrix;
00381 }
00382
00383
00384 template <typename Source>
00385 Matrix& density_minus_assign(const Source& src, boost::mpl::false_)
00386 {
00387
00388 return crtp_minus_assign<Source, Matrix>()(src, static_cast<Matrix&>(*this));
00389 }
00390
00391
00392 template <typename Source>
00393 Matrix& density_ele_rscale(const Source& src, boost::mpl::true_)
00394 {
00395
00396 typedef unsigned size_type;
00397
00398
00399 checked_change_dim(num_rows(src), num_cols(src));
00400
00401 Matrix& matrix= static_cast<Matrix&>(*this);
00402 for (size_type r= 0; r < num_rows(matrix); ++r)
00403 for (size_type c= 0; c < num_cols(matrix); ++c)
00404 matrix[r][c]*= src[r][c];
00405 return matrix;
00406 }
00407
00408
00409 template <typename Factor>
00410 Matrix& density_ele_rscale(const Factor& alpha, boost::mpl::false_)
00411 {
00412
00413 matrix_copy_ele_times(alpha, static_cast<Matrix&>(*this));
00414 return static_cast<Matrix&>(*this);
00415 }
00416
00417
00418
00419
00420 public:
00422 void checked_change_dim(SizeType r, SizeType c)
00423 {
00424 Matrix& matrix= static_cast<Matrix&>(*this);
00425 matrix.check_dim(r, c);
00426 matrix.change_dim(r, c);
00427 }
00428
00430
00431
00432 template <typename Source>
00433 typename boost::disable_if_c<boost::is_same<Matrix, Source>::value
00434 || boost::is_same<typename ashape::ashape<Source>::type, ashape::scal>::value,
00435 Matrix&>::type
00436 operator=(const Source& src)
00437 {
00438 return density_assign(src, boost::mpl::bool_< boost::is_same<typename ashape::ashape<Matrix>::type,
00439 typename ashape::ashape<Source>::type>::value
00440 && mtl::traits::eval_dense< mat_mat_asgn_expr<Matrix, Source> >::value >());
00441 }
00442
00443
00444 template <typename Source>
00445 struct scalar_assign
00446 {
00447 scalar_assign(Source src, Matrix& matrix)
00448 : src(src), with_comma(false), r(0), c(0), matrix(matrix), ins(matrix) {}
00449
00450 ~scalar_assign()
00451 {
00452 if (with_comma) {
00453 MTL_DEBUG_THROW_IF(r != num_rows(matrix), incompatible_size("Not all matrix entries initialized!"));
00454 } else {
00455 using std::min;
00456 if (src == math::zero(src))
00457 return;
00458
00459 for (SizeType i= 0, n= min(num_rows(matrix), num_cols(matrix)); i < n; i++)
00460 ins[i][i] << src;
00461 }
00462 }
00463
00464 template <typename ValueSource>
00465 scalar_assign& operator, (ValueSource val)
00466 {
00467 if (!with_comma) {
00468 with_comma= true;
00469 assert(r == 0 && c == 0);
00470 ins[r][c++] << src;
00471 if (c == num_cols(matrix))
00472 c= 0, r++;
00473 }
00474 ins[r][c++] << val;
00475 if (c == num_cols(matrix))
00476 c= 0, r++;
00477 return *this;
00478 }
00479
00480 Source src;
00481 bool with_comma;
00482 SizeType r, c;
00483 Matrix& matrix;
00484 inserter<Matrix> ins;
00485 };
00486
00487 template <typename Source>
00488 typename boost::enable_if<boost::is_same<typename ashape::ashape<Source>::type, ashape::scal>,
00489 scalar_assign<Source> >::type
00490 operator=(Source src)
00491 {
00492 Matrix& matrix= static_cast<Matrix&>(*this);
00493 MTL_DEBUG_THROW_IF(num_rows(matrix) * num_cols(matrix) == 0,
00494 range_error("Trying to initialize a 0 by 0 matrix with a value"));
00495 set_to_zero(matrix);
00496 return scalar_assign<Source>(src, static_cast<Matrix&>(*this));
00497 }
00498
00499 template <typename Source>
00500 Matrix& operator+=(const Source& src)
00501 {
00502 return density_plus_assign(src, mtl::traits::eval_dense< mat_mat_asgn_expr<Matrix, Source> >());
00503 }
00504
00505 template <typename Source>
00506 Matrix& operator-=(const Source& src)
00507 {
00508 return density_minus_assign(src, mtl::traits::eval_dense< mat_mat_asgn_expr<Matrix, Source> >());
00509 }
00510
00512 template <typename Factor>
00513 Matrix& operator*=(const Factor& alpha)
00514 {
00515 right_scale_inplace(static_cast<Matrix&>(*this), alpha);
00516 return static_cast<Matrix&>(*this);
00517 }
00518
00519
00520 template <typename Factor>
00521 Matrix& ele_rscale(const Factor& alpha)
00522 {
00523 return density_ele_rscale(alpha, mtl::traits::eval_dense< mat_mat_asgn_expr<Matrix, Factor> >());
00524 }
00525
00527
00528 template <typename Factor>
00529 Matrix& operator/=(const Factor& alpha)
00530 {
00531 divide_by_inplace(static_cast<Matrix&>(*this), alpha);
00532 return static_cast<Matrix&>(*this);
00533 }
00534 };
00535
00536
00537
00538 template <typename Matrix, typename ValueType, typename SizeType>
00539 struct const_crtp_matrix_bracket
00540 {
00541 operations::bracket_proxy<Matrix, const Matrix&, ValueType>
00542 operator[] (SizeType row) const
00543 {
00544 return operations::bracket_proxy<Matrix, const Matrix&, ValueType>(static_cast<const Matrix&>(*this), row);
00545 }
00546
00547
00548 operations::range_bracket_proxy<Matrix, const Matrix&, const Matrix>
00549 operator[] (irange row_range) const
00550 {
00551 return operations::range_bracket_proxy<Matrix, const Matrix&, const Matrix>(static_cast<const Matrix&>(*this), row_range);
00552 }
00553
00554 };
00555
00556 template <typename Matrix, typename ValueType, typename SizeType>
00557 struct crtp_matrix_bracket
00558 {
00559 operations::bracket_proxy<Matrix, const Matrix&, const ValueType&>
00560 operator[] (SizeType row) const
00561 {
00562 return operations::bracket_proxy<Matrix, const Matrix&, const ValueType&>(static_cast<const Matrix&>(*this), row);
00563 }
00564
00565 operations::bracket_proxy<Matrix, Matrix&, ValueType&>
00566 operator[] (SizeType row)
00567 {
00568 return operations::bracket_proxy<Matrix, Matrix&, ValueType&>(static_cast<Matrix&>(*this), row);
00569 }
00570
00571
00572 operations::range_bracket_proxy<Matrix, const Matrix&, const Matrix>
00573 operator[] (irange row_range) const
00574 {
00575 return operations::range_bracket_proxy<Matrix, const Matrix&, const Matrix>(static_cast<const Matrix&>(*this), row_range);
00576 }
00577
00578
00579 operations::range_bracket_proxy<Matrix, Matrix&, Matrix>
00580 operator[] (irange row_range)
00581 {
00582 return operations::range_bracket_proxy<Matrix, Matrix&, Matrix>(static_cast<Matrix&>(*this), row_range);
00583 }
00584 };
00585
00586 template <typename Matrix, typename ValueType, typename SizeType>
00587 struct crtp_matrix_lvalue
00588 {
00589
00590 ValueType& lvalue(SizeType row, SizeType col)
00591 {
00592 return static_cast<Matrix&>(*this)(row, col);
00593 }
00594 };
00595
00596 template <typename Matrix, typename ValueType, typename SizeType>
00597 struct const_crtp_base_matrix
00598 : public const_crtp_matrix_bracket<Matrix, ValueType, SizeType>
00599 {};
00600
00601 template <typename Matrix, typename ValueType, typename SizeType>
00602 struct mutable_crtp_base_matrix
00603 : public crtp_matrix_bracket<Matrix, ValueType, SizeType>,
00604 public crtp_matrix_assign<Matrix, ValueType, SizeType>
00605 {};
00606
00607 template <typename Matrix, typename ValueType, typename SizeType>
00608 struct crtp_base_matrix
00609 : boost::mpl::if_<boost::is_const<Matrix>,
00610 const_crtp_base_matrix<Matrix, ValueType, SizeType>,
00611 mutable_crtp_base_matrix<Matrix, ValueType, SizeType>
00612 >::type
00613 {};
00614
00615
00616
00617 }}
00618
00619 #endif // MTL_CRTP_BASE_MATRIX_INCLUDE