00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #ifndef MTL_MATRIX_RECURATOR_INCLUDE
00013 #define MTL_MATRIX_RECURATOR_INCLUDE
00014
00015 #include <cmath>
00016 #include <boost/type_traits.hpp>
00017 #include <boost/numeric/mtl/concept/collection.hpp>
00018 #include <boost/numeric/mtl/operation/sub_matrix.hpp>
00019 #include <boost/numeric/mtl/operation/print_matrix.hpp>
00020 #include <boost/numeric/mtl/matrix/transposed_view.hpp>
00021 #include <boost/numeric/mtl/recursion/dim_splitter.hpp>
00022 #include <boost/numeric/mtl/recursion/utility.hpp>
00023 #include <boost/numeric/mtl/utility/exception.hpp>
00024
00025 namespace mtl { namespace matrix {
00026
00027
00028 template <typename Recursator1, typename Recursator2>
00029 void inline equalize_depth(Recursator1& r1, Recursator2& r2);
00030
00031 template <typename Recursator1, typename Recursator2, typename Recursator3>
00032 void inline equalize_depth(Recursator1& r1, Recursator2& r2, Recursator3& r3);
00033
00034
00047 template <typename Matrix>
00048 struct recursator
00049 {
00050 typedef recursator self;
00051 typedef Matrix matrix_type;
00052 typedef typename sub_matrix_t<Matrix>::sub_matrix_type sub_matrix_type;
00053 typedef typename sub_matrix_t<Matrix>::const_sub_matrix_type const_sub_matrix_type;
00054 typedef typename Collection<Matrix>::size_type size_type;
00055 typedef typename Collection<Matrix>::value_type matrix_value_type;
00056 typedef recursion::outer_bound_splitter<self> splitter_type;
00057
00058 private:
00059
00060 template <typename MatrixType>
00061 sub_matrix_type constructor_helper(MatrixType const& matrix)
00062 {
00063 return sub_matrix(matrix, matrix.begin_row(), matrix.end_row(),
00064 matrix.begin_col(), matrix.end_col());
00065 }
00066
00067
00068 template <typename MatrixType>
00069 sub_matrix_type constructor_helper(transposed_view<MatrixType> const& view)
00070 {
00071 typedef typename boost::remove_const<MatrixType>::type tmp_type;
00072 typedef typename sub_matrix_t<tmp_type>::sub_matrix_type ref_sub_type;
00073 typedef boost::shared_ptr<ref_sub_type> pointer_type;
00074 typedef typename transposed_view<MatrixType>::other ref_type;
00075
00076
00077
00078 pointer_type p(new ref_sub_type(sub_matrix(const_cast<ref_type&>(view.ref), view.begin_col(), view.end_col(),
00079 view.begin_row(), view.end_row())));
00080 return sub_matrix_type(p);
00081 }
00082
00083 public:
00092 explicit recursator(Matrix const& matrix,
00093 size_type bound= 0
00094 )
00095 : my_sub_matrix(constructor_helper(matrix)), my_bound(recursion::outer_bound(matrix)),
00096 my_first_row(0), my_first_col(0)
00097 {
00098 if (bound == 0)
00099 my_bound= recursion::outer_bound(matrix);
00100 else {
00101 MTL_DEBUG_THROW_IF(!recursion::is_power_of_2(bound), range_error("Bound must be a power of 2"));
00102 MTL_DEBUG_THROW_IF(bound < num_rows(matrix) || bound < num_cols(matrix),
00103 range_error("Bound must not be smaller than matrix dimensions"));
00104 my_bound= bound;
00105 }
00106 }
00107
00108
00109 private:
00110
00111 template <typename SubMatrix>
00112 sub_matrix_type get_value_dispatch(const SubMatrix& matrix,
00113 size_type br, size_type er, size_type bc, size_type ec) const
00114 {
00115 return sub_matrix(my_sub_matrix, br, er, bc, ec);
00116 }
00117
00118 template <typename SubMatrix>
00119 sub_matrix_type get_value_dispatch(transposed_view<SubMatrix> view,
00120 size_type br, size_type er, size_type bc, size_type ec) const
00121 {
00122 typedef typename sub_matrix_t<SubMatrix>::sub_matrix_type ref_sub_type;
00123 typedef boost::shared_ptr<ref_sub_type> pointer_type;
00124 typedef typename transposed_view<SubMatrix>::other ref_type;
00125
00126 pointer_type p(new ref_sub_type(sub_matrix(const_cast<ref_type&>(view.ref), bc, ec, br, er)));
00127 return sub_matrix_type(p);
00128 }
00129
00130
00131 public:
00132 sub_matrix_type get_value() const
00133 {
00134 using std::min;
00135 size_type begin_row= my_sub_matrix.begin_row() + my_first_row,
00136 end_row= min(begin_row + my_bound, my_sub_matrix.end_row()),
00137 begin_col= my_sub_matrix.begin_col() + my_first_col,
00138 end_col= min(begin_col + my_bound, my_sub_matrix.end_col());
00139
00140 #if 0
00141 std::cout << "get_value [" << begin_row << "-" << end_row << "]["
00142 << begin_col << "-" << end_col << "]\n";
00143 #endif
00144 return get_value_dispatch(my_sub_matrix, begin_row, end_row, begin_col, end_col);
00145 }
00146
00148 sub_matrix_type operator*() const
00149 {
00150 return get_value();
00151 }
00152
00153
00154
00155 self north_west() const
00156 {
00157 self tmp(*this);
00158 tmp.my_bound >>= 1;
00159 return tmp;
00160 }
00161
00162 self south_west() const
00163 {
00164 self tmp(*this);
00165 tmp.my_bound >>= 1;
00166 tmp.my_first_row += tmp.my_bound;
00167 return tmp;
00168 }
00169
00170 self north_east() const
00171 {
00172 self tmp(*this);
00173 tmp.my_bound >>= 1;
00174 tmp.my_first_col += tmp.my_bound;
00175 return tmp;
00176 }
00177
00178 self south_east() const
00179 {
00180 self tmp(*this);
00181 tmp.my_bound >>= 1;
00182 tmp.my_first_row += tmp.my_bound;
00183 tmp.my_first_col += tmp.my_bound;
00184 return tmp;
00185 }
00186
00187 bool is_empty() const
00188 {
00189 return my_first_row >= num_rows(my_sub_matrix) || my_first_col >= num_cols(my_sub_matrix);
00190 }
00191
00192
00194 size_type bound() const
00195 {
00196 return my_bound;
00197 }
00198
00205 void set_bound(size_type b)
00206 {
00207 my_bound= b;
00208 }
00209
00210 template <typename R1, typename R2> friend void equalize_depth (R1&, R2&);
00211 template <typename R1, typename R2, typename R3> friend void equalize_depth (R1&, R2&, R3&);
00212
00213 template <typename M> friend typename recursator<M>::size_type num_rows(const recursator<M>& rec);
00214 template <typename M> friend typename recursator<M>::size_type num_cols(const recursator<M>& rec);
00215
00216
00217 matrix_value_type* first_address()
00218 {
00219 return &my_sub_matrix[my_first_row][my_first_col];
00220 }
00221
00222 const matrix_value_type* first_address() const
00223 {
00224 return &my_sub_matrix[my_first_row][my_first_col];
00225 }
00226
00227 protected:
00228 sub_matrix_type my_sub_matrix;
00229 size_type my_bound,
00230 my_first_row,
00231 my_first_col;
00232 };
00233
00234 #if 0
00235
00236
00237
00238 template <typename Matrix, typename Splitter = recursion::max_dim_splitter<Matrix> >
00239 struct recursator_s
00240 {
00241 typedef recursator_s self;
00242 typedef Matrix matrix_type;
00243 typedef Splitter splitter_type;
00244 typedef typename sub_matrix_t<Matrix>::sub_matrix_type sub_matrix_type;
00245 typedef typename sub_matrix_t<Matrix>::const_sub_matrix_type const_sub_matrix_type;
00246 typedef typename Matrix::size_type size_type;
00247
00248
00249 private:
00250
00251
00252 sub_matrix_type constructor_helper(Matrix const& matrix)
00253 {
00254 return sub_matrix(matrix, matrix.begin_row(), matrix.end_row(),
00255 matrix.begin_col(), matrix.end_col());
00256 }
00257
00258
00259
00260 sub_matrix_type constructor_helper(transposed_view<Matrix> const& matrix)
00261 {
00262 typedef typename sub_matrix_t<Matrix>::sub_matrix_type ref_sub_type;
00263 typedef boost::shared_ptr<ref_sub_type> pointer_type;
00264
00265
00266
00267 pointer_type p(new ref_sub_type(sub_matrix(matrix.ref, matrix.begin_col(), matrix.end_col(),
00268 matrix.begin_row(), matrix.end_row())));
00269 return sub_matrix_type(p);
00270 }
00271
00272 public:
00273
00274
00275
00276 explicit recursator_s(Matrix const& matrix, size_type bound= 0)
00277 : my_sub_matrix(constructor_helper(matrix)), my_bound(outer_bound(matrix)),
00278 splitter(my_sub_matrix)
00279 {
00280 if (bound == 0)
00281 my_bound= outer_bound(matrix);
00282 else {
00283 assert(is_power_of_2(bound));
00284 assert(bound >= matrix.num_rows() && bound >= matrix.num_cols());
00285 my_bound= bound;
00286 }
00287 }
00288
00289
00290
00291
00292 sub_matrix_type& get_value()
00293 {
00294 return my_sub_matrix;
00295 }
00296
00297 sub_matrix_type const& get_value() const
00298 {
00299 return my_sub_matrix;
00300 }
00301
00302
00303
00304 self north_west()
00305 {
00306 sub_matrix_type sm(sub_matrix(my_sub_matrix, my_sub_matrix.begin_row(), splitter.row_split(),
00307 my_sub_matrix.begin_col(), splitter.col_split()));
00308 self tmp(sm, my_bound / 2);
00309 return tmp;
00310 }
00311
00312 self south_west()
00313 {
00314 sub_matrix_type sm(sub_matrix(my_sub_matrix, splitter.row_split(), my_sub_matrix.end_row(),
00315 my_sub_matrix.begin_col(), splitter.col_split()));
00316 self tmp(sm, my_bound / 2);
00317 return tmp;
00318 }
00319
00320 self north_east()
00321 {
00322 sub_matrix_type sm(sub_matrix(my_sub_matrix, my_sub_matrix.begin_row(), splitter.row_split(),
00323 splitter.col_split(), my_sub_matrix.end_col()));
00324 self tmp(sm, my_bound / 2);
00325 return tmp;
00326 }
00327
00328 self south_east()
00329 {
00330 sub_matrix_type sm(sub_matrix(my_sub_matrix, splitter.row_split(), my_sub_matrix.end_row(),
00331 splitter.col_split(), my_sub_matrix.end_col()));
00332 self tmp(sm, my_bound / 2);
00333 return tmp;
00334 }
00335
00336
00337
00338 self const north_west() const
00339 {
00340 sub_matrix_type sm(sub_matrix(const_cast<self*>(this)->my_sub_matrix, my_sub_matrix.begin_row(), splitter.row_split(),
00341 my_sub_matrix.begin_col(), splitter.col_split()));
00342 self tmp(sm, my_bound / 2);
00343 return tmp;
00344 }
00345
00346 self const south_west() const
00347 {
00348 sub_matrix_type sm(sub_matrix(const_cast<self*>(this)->my_sub_matrix, splitter.row_split(), my_sub_matrix.end_row(),
00349 my_sub_matrix.begin_col(), splitter.col_split()));
00350 self tmp(sm, my_bound / 2);
00351 return tmp;
00352 }
00353
00354 self const north_east() const
00355 {
00356 sub_matrix_type sm(sub_matrix(const_cast<self*>(this)->my_sub_matrix, my_sub_matrix.begin_row(), splitter.row_split(),
00357 splitter.col_split(), my_sub_matrix.end_col()));
00358 self tmp(sm, my_bound / 2);
00359 return tmp;
00360 }
00361
00362 self const south_east() const
00363 {
00364 sub_matrix_type sm(sub_matrix(const_cast<self*>(this)->my_sub_matrix, splitter.row_split(), my_sub_matrix.end_row(),
00365 splitter.col_split(), my_sub_matrix.end_col()));
00366 self tmp(sm, my_bound / 2);
00367 return tmp;
00368 }
00369
00370
00371
00372
00373 bool north_west_empty() const
00374 {
00375 return false;
00376 }
00377
00378 bool north_east_empty() const
00379 {
00380 return splitter.col_split() == my_sub_matrix.end_col();
00381 }
00382
00383 bool south_west_empty() const
00384 {
00385 return splitter.row_split() == my_sub_matrix.end_row();
00386 }
00387
00388 bool south_east_empty() const
00389 {
00390 return splitter.row_split() == my_sub_matrix.end_row()
00391 || splitter.col_split() == my_sub_matrix.end_col();
00392 }
00393
00394 bool is_empty() const
00395 {
00396 return my_sub_matrix.begin_row() == my_sub_matrix.end_row()
00397 || my_sub_matrix.begin_col() == my_sub_matrix.end_col();
00398 }
00399
00400 #if 0
00401 bool is_leaf() const
00402 {
00403 return my_sub_matrix.num_rows() < 2 || my_sub_matrix.num_cols() < 2;
00404 }
00405 #endif
00406
00407 size_type bound() const
00408 {
00409 assert(my_bound >= my_sub_matrix.num_rows() && my_bound >= my_sub_matrix.num_cols());
00410 return my_bound;
00411 }
00412
00413 template <typename R1, typename R2> friend void equalize_depth (R1&, R2&);
00414 template <typename R1, typename R2, typename R3> friend void equalize_depth (R1&, R2&, R3&);
00415
00416 protected:
00417 sub_matrix_type my_sub_matrix;
00418 size_type my_bound;
00419 splitter_type splitter;
00420 };
00421
00422 #endif
00423
00424 template <typename Recursator1, typename Recursator2>
00425 void inline equalize_depth(Recursator1& r1, Recursator2& r2)
00426 {
00427 typename Recursator1::size_type max_bound= std::max(r1.bound(), r2.bound());
00428 r1.my_bound= max_bound;
00429 r2.my_bound= max_bound;
00430 }
00431
00432 template <typename Recursator1, typename Recursator2, typename Recursator3>
00433 void inline equalize_depth(Recursator1& r1, Recursator2& r2, Recursator3& r3)
00434 {
00435 typename Recursator1::size_type max_bound= std::max(std::max(r1.bound(), r2.bound()), r3.bound());
00436 r1.my_bound= max_bound;
00437 r2.my_bound= max_bound;
00438 r3.my_bound= max_bound;
00439 }
00440
00441
00442
00443
00448 template <typename Matrix>
00449 recursator<Matrix> inline north_west(const recursator<Matrix>& rec)
00450 {
00451 return rec.north_west();
00452 }
00453
00458 template <typename Matrix>
00459 recursator<Matrix> inline north_east(const recursator<Matrix>& rec)
00460 {
00461 return rec.north_east();
00462 }
00463
00468 template <typename Matrix>
00469 recursator<Matrix> inline south_west(const recursator<Matrix>& rec)
00470 {
00471 return rec.south_west();
00472 }
00473
00478 template <typename Matrix>
00479 recursator<Matrix> inline south_east(const recursator<Matrix>& rec)
00480 {
00481 return rec.south_east();
00482 }
00483
00484
00488 template <typename Matrix>
00489 bool inline is_empty(const recursator<Matrix>& rec)
00490 {
00491 return rec.is_empty();
00492 }
00493
00499 template <typename Matrix>
00500 bool inline is_full(const recursator<Matrix>& rec)
00501 {
00502 return num_rows(rec) == rec.bound() && num_cols(rec) == rec.bound();
00503 }
00504
00508 template <typename Matrix>
00509 typename recursator<Matrix>::size_type
00510 inline num_rows(const recursator<Matrix>& rec)
00511 {
00512 using std::min;
00513 typename recursator<Matrix>::size_type tmp= num_rows(rec.my_sub_matrix);
00514 return rec.my_first_row >= tmp ? 0 : min(rec.my_bound, tmp - rec.my_first_row);
00515 }
00516
00520 template <typename Matrix>
00521 typename recursator<Matrix>::size_type
00522 inline num_cols(const recursator<Matrix>& rec)
00523 {
00524 using std::min;
00525 typename recursator<Matrix>::size_type tmp= num_cols(rec.my_sub_matrix);
00526 return rec.my_first_col >= tmp ? 0 : min(rec.my_bound, tmp - rec.my_first_col);
00527 }
00528
00532 template <typename Matrix>
00533 typename recursator<Matrix>::size_type
00534 inline size(const recursator<Matrix>& rec)
00535 {
00536 return num_rows(rec) * num_cols(rec);
00537 }
00538
00539 }}
00540
00541 #endif // MTL_MATRIX_RECURATOR_INCLUDE