00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #ifndef _BOOST_UBLAS_MATRIX_EXPRESSION_
00014 #define _BOOST_UBLAS_MATRIX_EXPRESSION_
00015
00016 #include <boost/numeric/ublas/vector_expression.hpp>
00017
00018
00019
00020
00021
00022
00023 namespace boost { namespace numeric { namespace ublas {
00024
00025 template<class E>
00026 class matrix_reference:
00027 public matrix_expression<matrix_reference<E> > {
00028
00029 typedef matrix_reference<E> self_type;
00030 public:
00031 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
00032 using matrix_expression<self_type>::operator ();
00033 #endif
00034 typedef typename E::size_type size_type;
00035 typedef typename E::difference_type difference_type;
00036 typedef typename E::value_type value_type;
00037 typedef typename E::const_reference const_reference;
00038 typedef typename boost::mpl::if_<boost::is_const<E>,
00039 typename E::const_reference,
00040 typename E::reference>::type reference;
00041 typedef E referred_type;
00042 typedef const self_type const_closure_type;
00043 typedef self_type closure_type;
00044 typedef typename E::orientation_category orientation_category;
00045 typedef typename E::storage_category storage_category;
00046
00047
00048 BOOST_UBLAS_INLINE
00049 explicit matrix_reference (referred_type &e):
00050 e_ (e) {}
00051
00052
00053 BOOST_UBLAS_INLINE
00054 size_type size1 () const {
00055 return e_.size1 ();
00056 }
00057 BOOST_UBLAS_INLINE
00058 size_type size2 () const {
00059 return e_.size2 ();
00060 }
00061
00062 public:
00063
00064 BOOST_UBLAS_INLINE
00065 const referred_type &expression () const {
00066 return e_;
00067 }
00068 BOOST_UBLAS_INLINE
00069 referred_type &expression () {
00070 return e_;
00071 }
00072
00073 public:
00074
00075 #ifndef BOOST_UBLAS_REFERENCE_CONST_MEMBER
00076 BOOST_UBLAS_INLINE
00077 const_reference operator () (size_type i, size_type j) const {
00078 return expression () (i, j);
00079 }
00080 BOOST_UBLAS_INLINE
00081 reference operator () (size_type i, size_type j) {
00082 return expression () (i, j);
00083 }
00084 #else
00085 BOOST_UBLAS_INLINE
00086 reference operator () (size_type i, size_type j) const {
00087 return expression () (i, j);
00088 }
00089 #endif
00090
00091
00092 BOOST_UBLAS_INLINE
00093 matrix_reference &operator = (const matrix_reference &m) {
00094 expression ().operator = (m);
00095 return *this;
00096 }
00097 template<class AE>
00098 BOOST_UBLAS_INLINE
00099 matrix_reference &operator = (const matrix_expression<AE> &ae) {
00100 expression ().operator = (ae);
00101 return *this;
00102 }
00103 template<class AE>
00104 BOOST_UBLAS_INLINE
00105 matrix_reference &assign (const matrix_expression<AE> &ae) {
00106 expression ().assign (ae);
00107 return *this;
00108 }
00109 template<class AE>
00110 BOOST_UBLAS_INLINE
00111 matrix_reference &operator += (const matrix_expression<AE> &ae) {
00112 expression ().operator += (ae);
00113 return *this;
00114 }
00115 template<class AE>
00116 BOOST_UBLAS_INLINE
00117 matrix_reference &plus_assign (const matrix_expression<AE> &ae) {
00118 expression ().plus_assign (ae);
00119 return *this;
00120 }
00121 template<class AE>
00122 BOOST_UBLAS_INLINE
00123 matrix_reference &operator -= (const matrix_expression<AE> &ae) {
00124 expression ().operator -= (ae);
00125 return *this;
00126 }
00127 template<class AE>
00128 BOOST_UBLAS_INLINE
00129 matrix_reference &minus_assign (const matrix_expression<AE> &ae) {
00130 expression ().minus_assign (ae);
00131 return *this;
00132 }
00133 template<class AT>
00134 BOOST_UBLAS_INLINE
00135 matrix_reference &operator *= (const AT &at) {
00136 expression ().operator *= (at);
00137 return *this;
00138 }
00139 template<class AT>
00140 BOOST_UBLAS_INLINE
00141 matrix_reference &operator /= (const AT &at) {
00142 expression ().operator /= (at);
00143 return *this;
00144 }
00145
00146
00147 BOOST_UBLAS_INLINE
00148 void swap (matrix_reference &m) {
00149 expression ().swap (m.expression ());
00150 }
00151
00152
00153 BOOST_UBLAS_INLINE
00154 bool same_closure (const matrix_reference &mr) const {
00155 return &(*this).e_ == &mr.e_;
00156 }
00157
00158
00159 typedef typename E::const_iterator1 const_iterator1;
00160 typedef typename boost::mpl::if_<boost::is_const<E>,
00161 typename E::const_iterator1,
00162 typename E::iterator1>::type iterator1;
00163 typedef typename E::const_iterator2 const_iterator2;
00164 typedef typename boost::mpl::if_<boost::is_const<E>,
00165 typename E::const_iterator2,
00166 typename E::iterator2>::type iterator2;
00167
00168
00169 BOOST_UBLAS_INLINE
00170 const_iterator1 find1 (int rank, size_type i, size_type j) const {
00171 return expression ().find1 (rank, i, j);
00172 }
00173 BOOST_UBLAS_INLINE
00174 iterator1 find1 (int rank, size_type i, size_type j) {
00175 return expression ().find1 (rank, i, j);
00176 }
00177 BOOST_UBLAS_INLINE
00178 const_iterator2 find2 (int rank, size_type i, size_type j) const {
00179 return expression ().find2 (rank, i, j);
00180 }
00181 BOOST_UBLAS_INLINE
00182 iterator2 find2 (int rank, size_type i, size_type j) {
00183 return expression ().find2 (rank, i, j);
00184 }
00185
00186
00187
00188 BOOST_UBLAS_INLINE
00189 const_iterator1 begin1 () const {
00190 return expression ().begin1 ();
00191 }
00192 BOOST_UBLAS_INLINE
00193 const_iterator1 end1 () const {
00194 return expression ().end1 ();
00195 }
00196
00197 BOOST_UBLAS_INLINE
00198 iterator1 begin1 () {
00199 return expression ().begin1 ();
00200 }
00201 BOOST_UBLAS_INLINE
00202 iterator1 end1 () {
00203 return expression ().end1 ();
00204 }
00205
00206 BOOST_UBLAS_INLINE
00207 const_iterator2 begin2 () const {
00208 return expression ().begin2 ();
00209 }
00210 BOOST_UBLAS_INLINE
00211 const_iterator2 end2 () const {
00212 return expression ().end2 ();
00213 }
00214
00215 BOOST_UBLAS_INLINE
00216 iterator2 begin2 () {
00217 return expression ().begin2 ();
00218 }
00219 BOOST_UBLAS_INLINE
00220 iterator2 end2 () {
00221 return expression ().end2 ();
00222 }
00223
00224
00225 typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
00226 typedef reverse_iterator_base1<iterator1> reverse_iterator1;
00227
00228 BOOST_UBLAS_INLINE
00229 const_reverse_iterator1 rbegin1 () const {
00230 return const_reverse_iterator1 (end1 ());
00231 }
00232 BOOST_UBLAS_INLINE
00233 const_reverse_iterator1 rend1 () const {
00234 return const_reverse_iterator1 (begin1 ());
00235 }
00236
00237 BOOST_UBLAS_INLINE
00238 reverse_iterator1 rbegin1 () {
00239 return reverse_iterator1 (end1 ());
00240 }
00241 BOOST_UBLAS_INLINE
00242 reverse_iterator1 rend1 () {
00243 return reverse_iterator1 (begin1 ());
00244 }
00245
00246 typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
00247 typedef reverse_iterator_base2<iterator2> reverse_iterator2;
00248
00249 BOOST_UBLAS_INLINE
00250 const_reverse_iterator2 rbegin2 () const {
00251 return const_reverse_iterator2 (end2 ());
00252 }
00253 BOOST_UBLAS_INLINE
00254 const_reverse_iterator2 rend2 () const {
00255 return const_reverse_iterator2 (begin2 ());
00256 }
00257
00258 BOOST_UBLAS_INLINE
00259 reverse_iterator2 rbegin2 () {
00260 return reverse_iterator2 (end2 ());
00261 }
00262 BOOST_UBLAS_INLINE
00263 reverse_iterator2 rend2 () {
00264 return reverse_iterator2 (begin2 ());
00265 }
00266
00267 private:
00268 referred_type &e_;
00269 };
00270
00271
00272 template<class E1, class E2, class F>
00273 class vector_matrix_binary:
00274 public matrix_expression<vector_matrix_binary<E1, E2, F> > {
00275
00276 typedef E1 expression1_type;
00277 typedef E2 expression2_type;
00278 public:
00279 typedef typename E1::const_closure_type expression1_closure_type;
00280 typedef typename E2::const_closure_type expression2_closure_type;
00281 private:
00282 typedef vector_matrix_binary<E1, E2, F> self_type;
00283 public:
00284 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
00285 using matrix_expression<self_type>::operator ();
00286 #endif
00287 typedef F functor_type;
00288 typedef typename promote_traits<typename E1::size_type, typename E2::size_type>::promote_type size_type;
00289 typedef typename promote_traits<typename E1::difference_type, typename E2::difference_type>::promote_type difference_type;
00290 typedef typename F::result_type value_type;
00291 typedef value_type const_reference;
00292 typedef const_reference reference;
00293 typedef const self_type const_closure_type;
00294 typedef const_closure_type closure_type;
00295 typedef unknown_orientation_tag orientation_category;
00296 typedef unknown_storage_tag storage_category;
00297
00298
00299 BOOST_UBLAS_INLINE
00300 vector_matrix_binary (const expression1_type &e1, const expression2_type &e2):
00301 e1_ (e1), e2_ (e2) {}
00302
00303
00304 BOOST_UBLAS_INLINE
00305 size_type size1 () const {
00306 return e1_.size ();
00307 }
00308 BOOST_UBLAS_INLINE
00309 size_type size2 () const {
00310 return e2_.size ();
00311 }
00312
00313 public:
00314
00315 BOOST_UBLAS_INLINE
00316 const expression1_closure_type &expression1 () const {
00317 return e1_;
00318 }
00319 BOOST_UBLAS_INLINE
00320 const expression2_closure_type &expression2 () const {
00321 return e2_;
00322 }
00323
00324 public:
00325
00326 BOOST_UBLAS_INLINE
00327 const_reference operator () (size_type i, size_type j) const {
00328 return functor_type::apply (e1_ (i), e2_ (j));
00329 }
00330
00331
00332 BOOST_UBLAS_INLINE
00333 bool same_closure (const vector_matrix_binary &vmb) const {
00334 return (*this).expression1 ().same_closure (vmb.expression1 ()) &&
00335 (*this).expression2 ().same_closure (vmb.expression2 ());
00336 }
00337
00338
00339 private:
00340 typedef typename E1::const_iterator const_subiterator1_type;
00341 typedef typename E2::const_iterator const_subiterator2_type;
00342 typedef const value_type *const_pointer;
00343
00344 public:
00345 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
00346 typedef typename iterator_restrict_traits<typename const_subiterator1_type::iterator_category,
00347 typename const_subiterator2_type::iterator_category>::iterator_category iterator_category;
00348 typedef indexed_const_iterator1<const_closure_type, iterator_category> const_iterator1;
00349 typedef const_iterator1 iterator1;
00350 typedef indexed_const_iterator2<const_closure_type, iterator_category> const_iterator2;
00351 typedef const_iterator2 iterator2;
00352 #else
00353 class const_iterator1;
00354 typedef const_iterator1 iterator1;
00355 class const_iterator2;
00356 typedef const_iterator2 iterator2;
00357 #endif
00358 typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
00359 typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
00360
00361
00362 BOOST_UBLAS_INLINE
00363 const_iterator1 find1 (int rank, size_type i, size_type j) const {
00364 const_subiterator1_type it1 (e1_.find (i));
00365 const_subiterator1_type it1_end (e1_.find (size1 ()));
00366 const_subiterator2_type it2 (e2_.find (j));
00367 const_subiterator2_type it2_end (e2_.find (size2 ()));
00368 if (it2 == it2_end || (rank == 1 && (it2.index () != j || *it2 == value_type()))) {
00369 it1 = it1_end;
00370 it2 = it2_end;
00371 }
00372 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
00373 return const_iterator1 (*this, it1.index (), it2.index ());
00374 #else
00375 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
00376 return const_iterator1 (*this, it1, it2, it2 != it2_end ? *it2 : value_type());
00377 #else
00378 return const_iterator1 (*this, it1, it2);
00379 #endif
00380 #endif
00381 }
00382 BOOST_UBLAS_INLINE
00383 const_iterator2 find2 (int rank, size_type i, size_type j) const {
00384 const_subiterator2_type it2 (e2_.find (j));
00385 const_subiterator2_type it2_end (e2_.find (size2 ()));
00386 const_subiterator1_type it1 (e1_.find (i));
00387 const_subiterator1_type it1_end (e1_.find (size1 ()));
00388 if (it1 == it1_end || (rank == 1 && (it1.index () != i || *it1 == value_type()))) {
00389 it2 = it2_end;
00390 it1 = it1_end;
00391 }
00392 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
00393 return const_iterator2 (*this, it1.index (), it2.index ());
00394 #else
00395 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
00396 return const_iterator2 (*this, it1, it2, it1 != it1_end ? *it1 : value_type());
00397 #else
00398 return const_iterator2 (*this, it1, it2);
00399 #endif
00400 #endif
00401 }
00402
00403
00404
00405
00406 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
00407 class const_iterator1:
00408 public container_const_reference<vector_matrix_binary>,
00409 public iterator_base_traits<typename iterator_restrict_traits<typename E1::const_iterator::iterator_category,
00410 typename E2::const_iterator::iterator_category>::iterator_category>::template
00411 iterator_base<const_iterator1, value_type>::type {
00412 public:
00413 typedef typename iterator_restrict_traits<typename E1::const_iterator::iterator_category,
00414 typename E2::const_iterator::iterator_category>::iterator_category iterator_category;
00415 typedef typename vector_matrix_binary::difference_type difference_type;
00416 typedef typename vector_matrix_binary::value_type value_type;
00417 typedef typename vector_matrix_binary::const_reference reference;
00418 typedef typename vector_matrix_binary::const_pointer pointer;
00419
00420 typedef const_iterator2 dual_iterator_type;
00421 typedef const_reverse_iterator2 dual_reverse_iterator_type;
00422
00423
00424 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
00425 BOOST_UBLAS_INLINE
00426 const_iterator1 ():
00427 container_const_reference<self_type> (), it1_ (), it2_ (), t2_ () {}
00428 BOOST_UBLAS_INLINE
00429 const_iterator1 (const self_type &vmb, const const_subiterator1_type &it1, const const_subiterator2_type &it2, value_type t2):
00430 container_const_reference<self_type> (vmb), it1_ (it1), it2_ (it2), t2_ (t2) {}
00431 #else
00432 BOOST_UBLAS_INLINE
00433 const_iterator1 ():
00434 container_const_reference<self_type> (), it1_ (), it2_ () {}
00435 BOOST_UBLAS_INLINE
00436 const_iterator1 (const self_type &vmb, const const_subiterator1_type &it1, const const_subiterator2_type &it2):
00437 container_const_reference<self_type> (vmb), it1_ (it1), it2_ (it2) {}
00438 #endif
00439
00440
00441 BOOST_UBLAS_INLINE
00442 const_iterator1 &operator ++ () {
00443 ++ it1_;
00444 return *this;
00445 }
00446 BOOST_UBLAS_INLINE
00447 const_iterator1 &operator -- () {
00448 -- it1_;
00449 return *this;
00450 }
00451 BOOST_UBLAS_INLINE
00452 const_iterator1 &operator += (difference_type n) {
00453 it1_ += n;
00454 return *this;
00455 }
00456 BOOST_UBLAS_INLINE
00457 const_iterator1 &operator -= (difference_type n) {
00458 it1_ -= n;
00459 return *this;
00460 }
00461 BOOST_UBLAS_INLINE
00462 difference_type operator - (const const_iterator1 &it) const {
00463 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
00464 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
00465 return it1_ - it.it1_;
00466 }
00467
00468
00469 BOOST_UBLAS_INLINE
00470 const_reference operator * () const {
00471 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
00472 return functor_type::apply (*it1_, t2_);
00473 #else
00474 return functor_type::apply (*it1_, *it2_);
00475 #endif
00476 }
00477 BOOST_UBLAS_INLINE
00478 const_reference operator [] (difference_type n) const {
00479 return *(*this + n);
00480 }
00481
00482 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
00483 BOOST_UBLAS_INLINE
00484 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
00485 typename self_type::
00486 #endif
00487 const_iterator2 begin () const {
00488 return (*this) ().find2 (1, index1 (), 0);
00489 }
00490 BOOST_UBLAS_INLINE
00491 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
00492 typename self_type::
00493 #endif
00494 const_iterator2 end () const {
00495 return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
00496 }
00497 BOOST_UBLAS_INLINE
00498 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
00499 typename self_type::
00500 #endif
00501 const_reverse_iterator2 rbegin () const {
00502 return const_reverse_iterator2 (end ());
00503 }
00504 BOOST_UBLAS_INLINE
00505 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
00506 typename self_type::
00507 #endif
00508 const_reverse_iterator2 rend () const {
00509 return const_reverse_iterator2 (begin ());
00510 }
00511 #endif
00512
00513
00514 BOOST_UBLAS_INLINE
00515 size_type index1 () const {
00516 return it1_.index ();
00517 }
00518 BOOST_UBLAS_INLINE
00519 size_type index2 () const {
00520 return it2_.index ();
00521 }
00522
00523
00524 BOOST_UBLAS_INLINE
00525 const_iterator1 &operator = (const const_iterator1 &it) {
00526 container_const_reference<self_type>::assign (&it ());
00527 it1_ = it.it1_;
00528 it2_ = it.it2_;
00529 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
00530 t2_ = it.t2_;
00531 #endif
00532 return *this;
00533 }
00534
00535
00536 BOOST_UBLAS_INLINE
00537 bool operator == (const const_iterator1 &it) const {
00538 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
00539 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
00540 return it1_ == it.it1_;
00541 }
00542 BOOST_UBLAS_INLINE
00543 bool operator < (const const_iterator1 &it) const {
00544 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
00545 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
00546 return it1_ < it.it1_;
00547 }
00548
00549 private:
00550 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
00551 const_subiterator1_type it1_;
00552
00553 const_subiterator2_type it2_;
00554 value_type t2_;
00555 #else
00556 const_subiterator1_type it1_;
00557 const_subiterator2_type it2_;
00558 #endif
00559 };
00560 #endif
00561
00562 BOOST_UBLAS_INLINE
00563 const_iterator1 begin1 () const {
00564 return find1 (0, 0, 0);
00565 }
00566 BOOST_UBLAS_INLINE
00567 const_iterator1 end1 () const {
00568 return find1 (0, size1 (), 0);
00569 }
00570
00571 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
00572 class const_iterator2:
00573 public container_const_reference<vector_matrix_binary>,
00574 public iterator_base_traits<typename iterator_restrict_traits<typename E1::const_iterator::iterator_category,
00575 typename E2::const_iterator::iterator_category>::iterator_category>::template
00576 iterator_base<const_iterator2, value_type>::type {
00577 public:
00578 typedef typename iterator_restrict_traits<typename E1::const_iterator::iterator_category,
00579 typename E2::const_iterator::iterator_category>::iterator_category iterator_category;
00580 typedef typename vector_matrix_binary::difference_type difference_type;
00581 typedef typename vector_matrix_binary::value_type value_type;
00582 typedef typename vector_matrix_binary::const_reference reference;
00583 typedef typename vector_matrix_binary::const_pointer pointer;
00584
00585 typedef const_iterator1 dual_iterator_type;
00586 typedef const_reverse_iterator1 dual_reverse_iterator_type;
00587
00588
00589 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
00590 BOOST_UBLAS_INLINE
00591 const_iterator2 ():
00592 container_const_reference<self_type> (), it1_ (), it2_ (), t1_ () {}
00593 BOOST_UBLAS_INLINE
00594 const_iterator2 (const self_type &vmb, const const_subiterator1_type &it1, const const_subiterator2_type &it2, value_type t1):
00595 container_const_reference<self_type> (vmb), it1_ (it1), it2_ (it2), t1_ (t1) {}
00596 #else
00597 BOOST_UBLAS_INLINE
00598 const_iterator2 ():
00599 container_const_reference<self_type> (), it1_ (), it2_ () {}
00600 BOOST_UBLAS_INLINE
00601 const_iterator2 (const self_type &vmb, const const_subiterator1_type &it1, const const_subiterator2_type &it2):
00602 container_const_reference<self_type> (vmb), it1_ (it1), it2_ (it2) {}
00603 #endif
00604
00605
00606 BOOST_UBLAS_INLINE
00607 const_iterator2 &operator ++ () {
00608 ++ it2_;
00609 return *this;
00610 }
00611 BOOST_UBLAS_INLINE
00612 const_iterator2 &operator -- () {
00613 -- it2_;
00614 return *this;
00615 }
00616 BOOST_UBLAS_INLINE
00617 const_iterator2 &operator += (difference_type n) {
00618 it2_ += n;
00619 return *this;
00620 }
00621 BOOST_UBLAS_INLINE
00622 const_iterator2 &operator -= (difference_type n) {
00623 it2_ -= n;
00624 return *this;
00625 }
00626 BOOST_UBLAS_INLINE
00627 difference_type operator - (const const_iterator2 &it) const {
00628 BOOST_UBLAS_CHECK ((*this) ().same_closure(it ()), external_logic ());
00629 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
00630 return it2_ - it.it2_;
00631 }
00632
00633
00634 BOOST_UBLAS_INLINE
00635 const_reference operator * () const {
00636 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
00637 return functor_type::apply (t1_, *it2_);
00638 #else
00639 return functor_type::apply (*it1_, *it2_);
00640 #endif
00641 }
00642 BOOST_UBLAS_INLINE
00643 const_reference operator [] (difference_type n) const {
00644 return *(*this + n);
00645 }
00646
00647 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
00648 BOOST_UBLAS_INLINE
00649 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
00650 typename self_type::
00651 #endif
00652 const_iterator1 begin () const {
00653 return (*this) ().find1 (1, 0, index2 ());
00654 }
00655 BOOST_UBLAS_INLINE
00656 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
00657 typename self_type::
00658 #endif
00659 const_iterator1 end () const {
00660 return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
00661 }
00662 BOOST_UBLAS_INLINE
00663 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
00664 typename self_type::
00665 #endif
00666 const_reverse_iterator1 rbegin () const {
00667 return const_reverse_iterator1 (end ());
00668 }
00669 BOOST_UBLAS_INLINE
00670 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
00671 typename self_type::
00672 #endif
00673 const_reverse_iterator1 rend () const {
00674 return const_reverse_iterator1 (begin ());
00675 }
00676 #endif
00677
00678
00679 BOOST_UBLAS_INLINE
00680 size_type index1 () const {
00681 return it1_.index ();
00682 }
00683 BOOST_UBLAS_INLINE
00684 size_type index2 () const {
00685 return it2_.index ();
00686 }
00687
00688
00689 BOOST_UBLAS_INLINE
00690 const_iterator2 &operator = (const const_iterator2 &it) {
00691 container_const_reference<self_type>::assign (&it ());
00692 it1_ = it.it1_;
00693 it2_ = it.it2_;
00694 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
00695 t1_ = it.t1_;
00696 #endif
00697 return *this;
00698 }
00699
00700
00701 BOOST_UBLAS_INLINE
00702 bool operator == (const const_iterator2 &it) const {
00703 BOOST_UBLAS_CHECK ((*this) ().same_closure( it ()), external_logic ());
00704 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
00705 return it2_ == it.it2_;
00706 }
00707 BOOST_UBLAS_INLINE
00708 bool operator < (const const_iterator2 &it) const {
00709 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
00710 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
00711 return it2_ < it.it2_;
00712 }
00713
00714 private:
00715 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
00716
00717 const_subiterator1_type it1_;
00718 const_subiterator2_type it2_;
00719 value_type t1_;
00720 #else
00721 const_subiterator1_type it1_;
00722 const_subiterator2_type it2_;
00723 #endif
00724 };
00725 #endif
00726
00727 BOOST_UBLAS_INLINE
00728 const_iterator2 begin2 () const {
00729 return find2 (0, 0, 0);
00730 }
00731 BOOST_UBLAS_INLINE
00732 const_iterator2 end2 () const {
00733 return find2 (0, 0, size2 ());
00734 }
00735
00736
00737
00738 BOOST_UBLAS_INLINE
00739 const_reverse_iterator1 rbegin1 () const {
00740 return const_reverse_iterator1 (end1 ());
00741 }
00742 BOOST_UBLAS_INLINE
00743 const_reverse_iterator1 rend1 () const {
00744 return const_reverse_iterator1 (begin1 ());
00745 }
00746
00747 BOOST_UBLAS_INLINE
00748 const_reverse_iterator2 rbegin2 () const {
00749 return const_reverse_iterator2 (end2 ());
00750 }
00751 BOOST_UBLAS_INLINE
00752 const_reverse_iterator2 rend2 () const {
00753 return const_reverse_iterator2 (begin2 ());
00754 }
00755
00756 private:
00757 expression1_closure_type e1_;
00758 expression2_closure_type e2_;
00759 };
00760
00761 template<class E1, class E2, class F>
00762 struct vector_matrix_binary_traits {
00763 typedef vector_matrix_binary<E1, E2, F> expression_type;
00764 #ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
00765 typedef expression_type result_type;
00766 #else
00767
00768 typedef matrix<typename F::value_type> result_type;
00769 #endif
00770 };
00771
00772
00773 template<class E1, class E2>
00774 BOOST_UBLAS_INLINE
00775 typename vector_matrix_binary_traits<E1, E2, scalar_multiplies<typename E1::value_type, typename E2::value_type> >::result_type
00776 outer_prod (const vector_expression<E1> &e1,
00777 const vector_expression<E2> &e2) {
00778 BOOST_STATIC_ASSERT (E1::complexity == 0 && E2::complexity == 0);
00779 typedef typename vector_matrix_binary_traits<E1, E2, scalar_multiplies<typename E1::value_type, typename E2::value_type> >::expression_type expression_type;
00780 return expression_type (e1 (), e2 ());
00781 }
00782
00783 template<class E, class F>
00784 class matrix_unary1:
00785 public matrix_expression<matrix_unary1<E, F> > {
00786
00787 typedef E expression_type;
00788 typedef F functor_type;
00789 public:
00790 typedef typename E::const_closure_type expression_closure_type;
00791 private:
00792 typedef matrix_unary1<E, F> self_type;
00793 public:
00794 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
00795 using matrix_expression<self_type>::operator ();
00796 #endif
00797 typedef typename E::size_type size_type;
00798 typedef typename E::difference_type difference_type;
00799 typedef typename F::result_type value_type;
00800 typedef value_type const_reference;
00801 typedef const_reference reference;
00802 typedef const self_type const_closure_type;
00803 typedef const_closure_type closure_type;
00804 typedef typename E::orientation_category orientation_category;
00805 typedef unknown_storage_tag storage_category;
00806
00807
00808 BOOST_UBLAS_INLINE
00809 explicit matrix_unary1 (const expression_type &e):
00810 e_ (e) {}
00811
00812
00813 BOOST_UBLAS_INLINE
00814 size_type size1 () const {
00815 return e_.size1 ();
00816 }
00817 BOOST_UBLAS_INLINE
00818 size_type size2 () const {
00819 return e_.size2 ();
00820 }
00821
00822 public:
00823
00824 BOOST_UBLAS_INLINE
00825 const expression_closure_type &expression () const {
00826 return e_;
00827 }
00828
00829 public:
00830
00831 BOOST_UBLAS_INLINE
00832 const_reference operator () (size_type i, size_type j) const {
00833 return functor_type::apply (e_ (i, j));
00834 }
00835
00836
00837 BOOST_UBLAS_INLINE
00838 bool same_closure (const matrix_unary1 &mu1) const {
00839 return (*this).expression ().same_closure (mu1.expression ());
00840 }
00841
00842
00843 private:
00844 typedef typename E::const_iterator1 const_subiterator1_type;
00845 typedef typename E::const_iterator2 const_subiterator2_type;
00846 typedef const value_type *const_pointer;
00847
00848 public:
00849 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
00850 typedef indexed_const_iterator1<const_closure_type, typename const_subiterator1_type::iterator_category> const_iterator1;
00851 typedef const_iterator1 iterator1;
00852 typedef indexed_const_iterator2<const_closure_type, typename const_subiterator2_type::iterator_category> const_iterator2;
00853 typedef const_iterator2 iterator2;
00854 #else
00855 class const_iterator1;
00856 typedef const_iterator1 iterator1;
00857 class const_iterator2;
00858 typedef const_iterator2 iterator2;
00859 #endif
00860 typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
00861 typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
00862
00863
00864 BOOST_UBLAS_INLINE
00865 const_iterator1 find1 (int rank, size_type i, size_type j) const {
00866 const_subiterator1_type it1 (e_.find1 (rank, i, j));
00867 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
00868 return const_iterator1 (*this, it1.index1 (), it1.index2 ());
00869 #else
00870 return const_iterator1 (*this, it1);
00871 #endif
00872 }
00873 BOOST_UBLAS_INLINE
00874 const_iterator2 find2 (int rank, size_type i, size_type j) const {
00875 const_subiterator2_type it2 (e_.find2 (rank, i, j));
00876 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
00877 return const_iterator2 (*this, it2.index1 (), it2.index2 ());
00878 #else
00879 return const_iterator2 (*this, it2);
00880 #endif
00881 }
00882
00883
00884
00885
00886 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
00887 class const_iterator1:
00888 public container_const_reference<matrix_unary1>,
00889 public iterator_base_traits<typename E::const_iterator1::iterator_category>::template
00890 iterator_base<const_iterator1, value_type>::type {
00891 public:
00892 typedef typename E::const_iterator1::iterator_category iterator_category;
00893 typedef typename matrix_unary1::difference_type difference_type;
00894 typedef typename matrix_unary1::value_type value_type;
00895 typedef typename matrix_unary1::const_reference reference;
00896 typedef typename matrix_unary1::const_pointer pointer;
00897
00898 typedef const_iterator2 dual_iterator_type;
00899 typedef const_reverse_iterator2 dual_reverse_iterator_type;
00900
00901
00902 BOOST_UBLAS_INLINE
00903 const_iterator1 ():
00904 container_const_reference<self_type> (), it_ () {}
00905 BOOST_UBLAS_INLINE
00906 const_iterator1 (const self_type &mu, const const_subiterator1_type &it):
00907 container_const_reference<self_type> (mu), it_ (it) {}
00908
00909
00910 BOOST_UBLAS_INLINE
00911 const_iterator1 &operator ++ () {
00912 ++ it_;
00913 return *this;
00914 }
00915 BOOST_UBLAS_INLINE
00916 const_iterator1 &operator -- () {
00917 -- it_;
00918 return *this;
00919 }
00920 BOOST_UBLAS_INLINE
00921 const_iterator1 &operator += (difference_type n) {
00922 it_ += n;
00923 return *this;
00924 }
00925 BOOST_UBLAS_INLINE
00926 const_iterator1 &operator -= (difference_type n) {
00927 it_ -= n;
00928 return *this;
00929 }
00930 BOOST_UBLAS_INLINE
00931 difference_type operator - (const const_iterator1 &it) const {
00932 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
00933 return it_ - it.it_;
00934 }
00935
00936
00937 BOOST_UBLAS_INLINE
00938 const_reference operator * () const {
00939 return functor_type::apply (*it_);
00940 }
00941 BOOST_UBLAS_INLINE
00942 const_reference operator [] (difference_type n) const {
00943 return *(*this + n);
00944 }
00945
00946 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
00947 BOOST_UBLAS_INLINE
00948 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
00949 typename self_type::
00950 #endif
00951 const_iterator2 begin () const {
00952 return (*this) ().find2 (1, index1 (), 0);
00953 }
00954 BOOST_UBLAS_INLINE
00955 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
00956 typename self_type::
00957 #endif
00958 const_iterator2 end () const {
00959 return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
00960 }
00961 BOOST_UBLAS_INLINE
00962 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
00963 typename self_type::
00964 #endif
00965 const_reverse_iterator2 rbegin () const {
00966 return const_reverse_iterator2 (end ());
00967 }
00968 BOOST_UBLAS_INLINE
00969 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
00970 typename self_type::
00971 #endif
00972 const_reverse_iterator2 rend () const {
00973 return const_reverse_iterator2 (begin ());
00974 }
00975 #endif
00976
00977
00978 BOOST_UBLAS_INLINE
00979 size_type index1 () const {
00980 return it_.index1 ();
00981 }
00982 BOOST_UBLAS_INLINE
00983 size_type index2 () const {
00984 return it_.index2 ();
00985 }
00986
00987
00988 BOOST_UBLAS_INLINE
00989 const_iterator1 &operator = (const const_iterator1 &it) {
00990 container_const_reference<self_type>::assign (&it ());
00991 it_ = it.it_;
00992 return *this;
00993 }
00994
00995
00996 BOOST_UBLAS_INLINE
00997 bool operator == (const const_iterator1 &it) const {
00998 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
00999 return it_ == it.it_;
01000 }
01001 BOOST_UBLAS_INLINE
01002 bool operator < (const const_iterator1 &it) const {
01003 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
01004 return it_ < it.it_;
01005 }
01006
01007 private:
01008 const_subiterator1_type it_;
01009 };
01010 #endif
01011
01012 BOOST_UBLAS_INLINE
01013 const_iterator1 begin1 () const {
01014 return find1 (0, 0, 0);
01015 }
01016 BOOST_UBLAS_INLINE
01017 const_iterator1 end1 () const {
01018 return find1 (0, size1 (), 0);
01019 }
01020
01021 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
01022 class const_iterator2:
01023 public container_const_reference<matrix_unary1>,
01024 public iterator_base_traits<typename E::const_iterator2::iterator_category>::template
01025 iterator_base<const_iterator2, value_type>::type {
01026 public:
01027 typedef typename E::const_iterator2::iterator_category iterator_category;
01028 typedef typename matrix_unary1::difference_type difference_type;
01029 typedef typename matrix_unary1::value_type value_type;
01030 typedef typename matrix_unary1::const_reference reference;
01031 typedef typename matrix_unary1::const_pointer pointer;
01032
01033 typedef const_iterator1 dual_iterator_type;
01034 typedef const_reverse_iterator1 dual_reverse_iterator_type;
01035
01036
01037 BOOST_UBLAS_INLINE
01038 const_iterator2 ():
01039 container_const_reference<self_type> (), it_ () {}
01040 BOOST_UBLAS_INLINE
01041 const_iterator2 (const self_type &mu, const const_subiterator2_type &it):
01042 container_const_reference<self_type> (mu), it_ (it) {}
01043
01044
01045 BOOST_UBLAS_INLINE
01046 const_iterator2 &operator ++ () {
01047 ++ it_;
01048 return *this;
01049 }
01050 BOOST_UBLAS_INLINE
01051 const_iterator2 &operator -- () {
01052 -- it_;
01053 return *this;
01054 }
01055 BOOST_UBLAS_INLINE
01056 const_iterator2 &operator += (difference_type n) {
01057 it_ += n;
01058 return *this;
01059 }
01060 BOOST_UBLAS_INLINE
01061 const_iterator2 &operator -= (difference_type n) {
01062 it_ -= n;
01063 return *this;
01064 }
01065 BOOST_UBLAS_INLINE
01066 difference_type operator - (const const_iterator2 &it) const {
01067 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
01068 return it_ - it.it_;
01069 }
01070
01071
01072 BOOST_UBLAS_INLINE
01073 const_reference operator * () const {
01074 return functor_type::apply (*it_);
01075 }
01076 BOOST_UBLAS_INLINE
01077 const_reference operator [] (difference_type n) const {
01078 return *(*this + n);
01079 }
01080
01081 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
01082 BOOST_UBLAS_INLINE
01083 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
01084 typename self_type::
01085 #endif
01086 const_iterator1 begin () const {
01087 return (*this) ().find1 (1, 0, index2 ());
01088 }
01089 BOOST_UBLAS_INLINE
01090 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
01091 typename self_type::
01092 #endif
01093 const_iterator1 end () const {
01094 return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
01095 }
01096 BOOST_UBLAS_INLINE
01097 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
01098 typename self_type::
01099 #endif
01100 const_reverse_iterator1 rbegin () const {
01101 return const_reverse_iterator1 (end ());
01102 }
01103 BOOST_UBLAS_INLINE
01104 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
01105 typename self_type::
01106 #endif
01107 const_reverse_iterator1 rend () const {
01108 return const_reverse_iterator1 (begin ());
01109 }
01110 #endif
01111
01112
01113 BOOST_UBLAS_INLINE
01114 size_type index1 () const {
01115 return it_.index1 ();
01116 }
01117 BOOST_UBLAS_INLINE
01118 size_type index2 () const {
01119 return it_.index2 ();
01120 }
01121
01122
01123 BOOST_UBLAS_INLINE
01124 const_iterator2 &operator = (const const_iterator2 &it) {
01125 container_const_reference<self_type>::assign (&it ());
01126 it_ = it.it_;
01127 return *this;
01128 }
01129
01130
01131 BOOST_UBLAS_INLINE
01132 bool operator == (const const_iterator2 &it) const {
01133 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
01134 return it_ == it.it_;
01135 }
01136 BOOST_UBLAS_INLINE
01137 bool operator < (const const_iterator2 &it) const {
01138 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
01139 return it_ < it.it_;
01140 }
01141
01142 private:
01143 const_subiterator2_type it_;
01144 };
01145 #endif
01146
01147 BOOST_UBLAS_INLINE
01148 const_iterator2 begin2 () const {
01149 return find2 (0, 0, 0);
01150 }
01151 BOOST_UBLAS_INLINE
01152 const_iterator2 end2 () const {
01153 return find2 (0, 0, size2 ());
01154 }
01155
01156
01157
01158 BOOST_UBLAS_INLINE
01159 const_reverse_iterator1 rbegin1 () const {
01160 return const_reverse_iterator1 (end1 ());
01161 }
01162 BOOST_UBLAS_INLINE
01163 const_reverse_iterator1 rend1 () const {
01164 return const_reverse_iterator1 (begin1 ());
01165 }
01166
01167 BOOST_UBLAS_INLINE
01168 const_reverse_iterator2 rbegin2 () const {
01169 return const_reverse_iterator2 (end2 ());
01170 }
01171 BOOST_UBLAS_INLINE
01172 const_reverse_iterator2 rend2 () const {
01173 return const_reverse_iterator2 (begin2 ());
01174 }
01175
01176 private:
01177 expression_closure_type e_;
01178 };
01179
01180 template<class E, class F>
01181 struct matrix_unary1_traits {
01182 typedef matrix_unary1<E, F> expression_type;
01183 #ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
01184 typedef expression_type result_type;
01185 #else
01186 typedef typename E::matrix_temporary_type result_type;
01187 #endif
01188 };
01189
01190
01191 template<class E>
01192 BOOST_UBLAS_INLINE
01193 typename matrix_unary1_traits<E, scalar_negate<typename E::value_type> >::result_type
01194 operator - (const matrix_expression<E> &e) {
01195 typedef typename matrix_unary1_traits<E, scalar_negate<typename E::value_type> >::expression_type expression_type;
01196 return expression_type (e ());
01197 }
01198
01199
01200 template<class E>
01201 BOOST_UBLAS_INLINE
01202 typename matrix_unary1_traits<E, scalar_conj<typename E::value_type> >::result_type
01203 conj (const matrix_expression<E> &e) {
01204 typedef typename matrix_unary1_traits<E, scalar_conj<typename E::value_type> >::expression_type expression_type;
01205 return expression_type (e ());
01206 }
01207
01208
01209 template<class E>
01210 BOOST_UBLAS_INLINE
01211 typename matrix_unary1_traits<E, scalar_real<typename E::value_type> >::result_type
01212 real (const matrix_expression<E> &e) {
01213 typedef typename matrix_unary1_traits<E, scalar_real<typename E::value_type> >::expression_type expression_type;
01214 return expression_type (e ());
01215 }
01216
01217
01218 template<class E>
01219 BOOST_UBLAS_INLINE
01220 typename matrix_unary1_traits<E, scalar_imag<typename E::value_type> >::result_type
01221 imag (const matrix_expression<E> &e) {
01222 typedef typename matrix_unary1_traits<E, scalar_imag<typename E::value_type> >::expression_type expression_type;
01223 return expression_type (e ());
01224 }
01225
01226 template<class E, class F>
01227 class matrix_unary2:
01228 public matrix_expression<matrix_unary2<E, F> > {
01229
01230 typedef typename boost::mpl::if_<boost::is_same<F, scalar_identity<typename E::value_type> >,
01231 E,
01232 const E>::type expression_type;
01233 typedef F functor_type;
01234 public:
01235 typedef typename boost::mpl::if_<boost::is_const<expression_type>,
01236 typename E::const_closure_type,
01237 typename E::closure_type>::type expression_closure_type;
01238 private:
01239 typedef matrix_unary2<E, F> self_type;
01240 public:
01241 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
01242 using matrix_expression<self_type>::operator ();
01243 #endif
01244 typedef typename E::size_type size_type;
01245 typedef typename E::difference_type difference_type;
01246 typedef typename F::result_type value_type;
01247 typedef value_type const_reference;
01248 typedef typename boost::mpl::if_<boost::is_same<F, scalar_identity<value_type> >,
01249 typename E::reference,
01250 value_type>::type reference;
01251
01252 typedef const self_type const_closure_type;
01253 typedef self_type closure_type;
01254 typedef typename boost::mpl::if_<boost::is_same<typename E::orientation_category,
01255 row_major_tag>,
01256 column_major_tag,
01257 typename boost::mpl::if_<boost::is_same<typename E::orientation_category,
01258 column_major_tag>,
01259 row_major_tag,
01260 typename E::orientation_category>::type>::type orientation_category;
01261 typedef typename E::storage_category storage_category;
01262
01263
01264 BOOST_UBLAS_INLINE
01265
01266
01267 explicit matrix_unary2 (expression_type &e):
01268 e_ (e) {}
01269
01270
01271 BOOST_UBLAS_INLINE
01272 size_type size1 () const {
01273 return e_.size2 ();
01274 }
01275 BOOST_UBLAS_INLINE
01276 size_type size2 () const {
01277 return e_.size1 ();
01278 }
01279
01280 public:
01281
01282 BOOST_UBLAS_INLINE
01283 const expression_closure_type &expression () const {
01284 return e_;
01285 }
01286
01287 public:
01288
01289 BOOST_UBLAS_INLINE
01290 const_reference operator () (size_type i, size_type j) const {
01291 return functor_type::apply (e_ (j, i));
01292 }
01293 BOOST_UBLAS_INLINE
01294 reference operator () (size_type i, size_type j) {
01295 BOOST_STATIC_ASSERT ((boost::is_same<functor_type, scalar_identity<value_type > >::value));
01296 return e_ (j, i);
01297 }
01298
01299
01300 BOOST_UBLAS_INLINE
01301 bool same_closure (const matrix_unary2 &mu2) const {
01302 return (*this).expression ().same_closure (mu2.expression ());
01303 }
01304
01305
01306 private:
01307 typedef typename E::const_iterator1 const_subiterator2_type;
01308 typedef typename E::const_iterator2 const_subiterator1_type;
01309 typedef const value_type *const_pointer;
01310
01311 public:
01312 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
01313 typedef indexed_const_iterator1<const_closure_type, typename const_subiterator1_type::iterator_category> const_iterator1;
01314 typedef const_iterator1 iterator1;
01315 typedef indexed_const_iterator2<const_closure_type, typename const_subiterator2_type::iterator_category> const_iterator2;
01316 typedef const_iterator2 iterator2;
01317 #else
01318 class const_iterator1;
01319 typedef const_iterator1 iterator1;
01320 class const_iterator2;
01321 typedef const_iterator2 iterator2;
01322 #endif
01323 typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
01324 typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
01325
01326
01327 BOOST_UBLAS_INLINE
01328 const_iterator1 find1 (int rank, size_type i, size_type j) const {
01329 const_subiterator1_type it1 (e_.find2 (rank, j, i));
01330 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
01331 return const_iterator1 (*this, it1.index2 (), it1.index1 ());
01332 #else
01333 return const_iterator1 (*this, it1);
01334 #endif
01335 }
01336 BOOST_UBLAS_INLINE
01337 const_iterator2 find2 (int rank, size_type i, size_type j) const {
01338 const_subiterator2_type it2 (e_.find1 (rank, j, i));
01339 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
01340 return const_iterator2 (*this, it2.index2 (), it2.index1 ());
01341 #else
01342 return const_iterator2 (*this, it2);
01343 #endif
01344 }
01345
01346
01347
01348
01349 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
01350 class const_iterator1:
01351 public container_const_reference<matrix_unary2>,
01352 public iterator_base_traits<typename E::const_iterator2::iterator_category>::template
01353 iterator_base<const_iterator1, value_type>::type {
01354 public:
01355 typedef typename E::const_iterator2::iterator_category iterator_category;
01356 typedef typename matrix_unary2::difference_type difference_type;
01357 typedef typename matrix_unary2::value_type value_type;
01358 typedef typename matrix_unary2::const_reference reference;
01359 typedef typename matrix_unary2::const_pointer pointer;
01360
01361 typedef const_iterator2 dual_iterator_type;
01362 typedef const_reverse_iterator2 dual_reverse_iterator_type;
01363
01364
01365 BOOST_UBLAS_INLINE
01366 const_iterator1 ():
01367 container_const_reference<self_type> (), it_ () {}
01368 BOOST_UBLAS_INLINE
01369 const_iterator1 (const self_type &mu, const const_subiterator1_type &it):
01370 container_const_reference<self_type> (mu), it_ (it) {}
01371
01372
01373 BOOST_UBLAS_INLINE
01374 const_iterator1 &operator ++ () {
01375 ++ it_;
01376 return *this;
01377 }
01378 BOOST_UBLAS_INLINE
01379 const_iterator1 &operator -- () {
01380 -- it_;
01381 return *this;
01382 }
01383 BOOST_UBLAS_INLINE
01384 const_iterator1 &operator += (difference_type n) {
01385 it_ += n;
01386 return *this;
01387 }
01388 BOOST_UBLAS_INLINE
01389 const_iterator1 &operator -= (difference_type n) {
01390 it_ -= n;
01391 return *this;
01392 }
01393 BOOST_UBLAS_INLINE
01394 difference_type operator - (const const_iterator1 &it) const {
01395 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
01396 return it_ - it.it_;
01397 }
01398
01399
01400 BOOST_UBLAS_INLINE
01401 const_reference operator * () const {
01402 return functor_type::apply (*it_);
01403 }
01404 BOOST_UBLAS_INLINE
01405 const_reference operator [] (difference_type n) const {
01406 return *(*this + n);
01407 }
01408
01409 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
01410 BOOST_UBLAS_INLINE
01411 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
01412 typename self_type::
01413 #endif
01414 const_iterator2 begin () const {
01415 return (*this) ().find2 (1, index1 (), 0);
01416 }
01417 BOOST_UBLAS_INLINE
01418 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
01419 typename self_type::
01420 #endif
01421 const_iterator2 end () const {
01422 return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
01423 }
01424 BOOST_UBLAS_INLINE
01425 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
01426 typename self_type::
01427 #endif
01428 const_reverse_iterator2 rbegin () const {
01429 return const_reverse_iterator2 (end ());
01430 }
01431 BOOST_UBLAS_INLINE
01432 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
01433 typename self_type::
01434 #endif
01435 const_reverse_iterator2 rend () const {
01436 return const_reverse_iterator2 (begin ());
01437 }
01438 #endif
01439
01440
01441 BOOST_UBLAS_INLINE
01442 size_type index1 () const {
01443 return it_.index2 ();
01444 }
01445 BOOST_UBLAS_INLINE
01446 size_type index2 () const {
01447 return it_.index1 ();
01448 }
01449
01450
01451 BOOST_UBLAS_INLINE
01452 const_iterator1 &operator = (const const_iterator1 &it) {
01453 container_const_reference<self_type>::assign (&it ());
01454 it_ = it.it_;
01455 return *this;
01456 }
01457
01458
01459 BOOST_UBLAS_INLINE
01460 bool operator == (const const_iterator1 &it) const {
01461 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
01462 return it_ == it.it_;
01463 }
01464 BOOST_UBLAS_INLINE
01465 bool operator < (const const_iterator1 &it) const {
01466 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
01467 return it_ < it.it_;
01468 }
01469
01470 private:
01471 const_subiterator1_type it_;
01472 };
01473 #endif
01474
01475 BOOST_UBLAS_INLINE
01476 const_iterator1 begin1 () const {
01477 return find1 (0, 0, 0);
01478 }
01479 BOOST_UBLAS_INLINE
01480 const_iterator1 end1 () const {
01481 return find1 (0, size1 (), 0);
01482 }
01483
01484 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
01485 class const_iterator2:
01486 public container_const_reference<matrix_unary2>,
01487 public iterator_base_traits<typename E::const_iterator1::iterator_category>::template
01488 iterator_base<const_iterator2, value_type>::type {
01489 public:
01490 typedef typename E::const_iterator1::iterator_category iterator_category;
01491 typedef typename matrix_unary2::difference_type difference_type;
01492 typedef typename matrix_unary2::value_type value_type;
01493 typedef typename matrix_unary2::const_reference reference;
01494 typedef typename matrix_unary2::const_pointer pointer;
01495
01496 typedef const_iterator1 dual_iterator_type;
01497 typedef const_reverse_iterator1 dual_reverse_iterator_type;
01498
01499
01500 BOOST_UBLAS_INLINE
01501 const_iterator2 ():
01502 container_const_reference<self_type> (), it_ () {}
01503 BOOST_UBLAS_INLINE
01504 const_iterator2 (const self_type &mu, const const_subiterator2_type &it):
01505 container_const_reference<self_type> (mu), it_ (it) {}
01506
01507
01508 BOOST_UBLAS_INLINE
01509 const_iterator2 &operator ++ () {
01510 ++ it_;
01511 return *this;
01512 }
01513 BOOST_UBLAS_INLINE
01514 const_iterator2 &operator -- () {
01515 -- it_;
01516 return *this;
01517 }
01518 BOOST_UBLAS_INLINE
01519 const_iterator2 &operator += (difference_type n) {
01520 it_ += n;
01521 return *this;
01522 }
01523 BOOST_UBLAS_INLINE
01524 const_iterator2 &operator -= (difference_type n) {
01525 it_ -= n;
01526 return *this;
01527 }
01528 BOOST_UBLAS_INLINE
01529 difference_type operator - (const const_iterator2 &it) const {
01530 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
01531 return it_ - it.it_;
01532 }
01533
01534
01535 BOOST_UBLAS_INLINE
01536 const_reference operator * () const {
01537 return functor_type::apply (*it_);
01538 }
01539 BOOST_UBLAS_INLINE
01540 const_reference operator [] (difference_type n) const {
01541 return *(*this + n);
01542 }
01543
01544 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
01545 BOOST_UBLAS_INLINE
01546 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
01547 typename self_type::
01548 #endif
01549 const_iterator1 begin () const {
01550 return (*this) ().find1 (1, 0, index2 ());
01551 }
01552 BOOST_UBLAS_INLINE
01553 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
01554 typename self_type::
01555 #endif
01556 const_iterator1 end () const {
01557 return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
01558 }
01559 BOOST_UBLAS_INLINE
01560 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
01561 typename self_type::
01562 #endif
01563 const_reverse_iterator1 rbegin () const {
01564 return const_reverse_iterator1 (end ());
01565 }
01566 BOOST_UBLAS_INLINE
01567 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
01568 typename self_type::
01569 #endif
01570 const_reverse_iterator1 rend () const {
01571 return const_reverse_iterator1 (begin ());
01572 }
01573 #endif
01574
01575
01576 BOOST_UBLAS_INLINE
01577 size_type index1 () const {
01578 return it_.index2 ();
01579 }
01580 BOOST_UBLAS_INLINE
01581 size_type index2 () const {
01582 return it_.index1 ();
01583 }
01584
01585
01586 BOOST_UBLAS_INLINE
01587 const_iterator2 &operator = (const const_iterator2 &it) {
01588 container_const_reference<self_type>::assign (&it ());
01589 it_ = it.it_;
01590 return *this;
01591 }
01592
01593
01594 BOOST_UBLAS_INLINE
01595 bool operator == (const const_iterator2 &it) const {
01596 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
01597 return it_ == it.it_;
01598 }
01599 BOOST_UBLAS_INLINE
01600 bool operator < (const const_iterator2 &it) const {
01601 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
01602 return it_ < it.it_;
01603 }
01604
01605 private:
01606 const_subiterator2_type it_;
01607 };
01608 #endif
01609
01610 BOOST_UBLAS_INLINE
01611 const_iterator2 begin2 () const {
01612 return find2 (0, 0, 0);
01613 }
01614 BOOST_UBLAS_INLINE
01615 const_iterator2 end2 () const {
01616 return find2 (0, 0, size2 ());
01617 }
01618
01619
01620
01621 BOOST_UBLAS_INLINE
01622 const_reverse_iterator1 rbegin1 () const {
01623 return const_reverse_iterator1 (end1 ());
01624 }
01625 BOOST_UBLAS_INLINE
01626 const_reverse_iterator1 rend1 () const {
01627 return const_reverse_iterator1 (begin1 ());
01628 }
01629
01630 BOOST_UBLAS_INLINE
01631 const_reverse_iterator2 rbegin2 () const {
01632 return const_reverse_iterator2 (end2 ());
01633 }
01634 BOOST_UBLAS_INLINE
01635 const_reverse_iterator2 rend2 () const {
01636 return const_reverse_iterator2 (begin2 ());
01637 }
01638
01639 private:
01640 expression_closure_type e_;
01641 };
01642
01643 template<class E, class F>
01644 struct matrix_unary2_traits {
01645 typedef matrix_unary2<E, F> expression_type;
01646 #ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
01647 typedef expression_type result_type;
01648 #else
01649 typedef typename E::matrix_temporary_type result_type;
01650 #endif
01651 };
01652
01653
01654 template<class E>
01655 BOOST_UBLAS_INLINE
01656 typename matrix_unary2_traits<const E, scalar_identity<typename E::value_type> >::result_type
01657 trans (const matrix_expression<E> &e) {
01658 typedef typename matrix_unary2_traits<const E, scalar_identity<typename E::value_type> >::expression_type expression_type;
01659 return expression_type (e ());
01660 }
01661 template<class E>
01662 BOOST_UBLAS_INLINE
01663 typename matrix_unary2_traits<E, scalar_identity<typename E::value_type> >::result_type
01664 trans (matrix_expression<E> &e) {
01665 typedef typename matrix_unary2_traits<E, scalar_identity<typename E::value_type> >::expression_type expression_type;
01666 return expression_type (e ());
01667 }
01668
01669
01670 template<class E>
01671 BOOST_UBLAS_INLINE
01672 typename matrix_unary2_traits<E, scalar_conj<typename E::value_type> >::result_type
01673 herm (const matrix_expression<E> &e) {
01674 typedef typename matrix_unary2_traits<E, scalar_conj<typename E::value_type> >::expression_type expression_type;
01675 return expression_type (e ());
01676 }
01677
01678 template<class E1, class E2, class F>
01679 class matrix_binary:
01680 public matrix_expression<matrix_binary<E1, E2, F> > {
01681
01682 typedef E1 expression1_type;
01683 typedef E2 expression2_type;
01684 typedef F functor_type;
01685 public:
01686 typedef typename E1::const_closure_type expression1_closure_type;
01687 typedef typename E2::const_closure_type expression2_closure_type;
01688 private:
01689 typedef matrix_binary<E1, E2, F> self_type;
01690 public:
01691 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
01692 using matrix_expression<self_type>::operator ();
01693 #endif
01694 typedef typename promote_traits<typename E1::size_type, typename E2::size_type>::promote_type size_type;
01695 typedef typename promote_traits<typename E1::difference_type, typename E2::difference_type>::promote_type difference_type;
01696 typedef typename F::result_type value_type;
01697 typedef value_type const_reference;
01698 typedef const_reference reference;
01699 typedef const self_type const_closure_type;
01700 typedef const_closure_type closure_type;
01701 typedef unknown_orientation_tag orientation_category;
01702 typedef unknown_storage_tag storage_category;
01703
01704
01705 BOOST_UBLAS_INLINE
01706 matrix_binary (const E1 &e1, const E2 &e2):
01707 e1_ (e1), e2_ (e2) {}
01708
01709
01710 BOOST_UBLAS_INLINE
01711 size_type size1 () const {
01712 return BOOST_UBLAS_SAME (e1_.size1 (), e2_.size1 ());
01713 }
01714 BOOST_UBLAS_INLINE
01715 size_type size2 () const {
01716 return BOOST_UBLAS_SAME (e1_.size2 (), e2_.size2 ());
01717 }
01718
01719 public:
01720
01721 BOOST_UBLAS_INLINE
01722 const expression1_closure_type &expression1 () const {
01723 return e1_;
01724 }
01725 BOOST_UBLAS_INLINE
01726 const expression2_closure_type &expression2 () const {
01727 return e2_;
01728 }
01729
01730 public:
01731
01732 BOOST_UBLAS_INLINE
01733 const_reference operator () (size_type i, size_type j) const {
01734 return functor_type::apply (e1_ (i, j), e2_ (i, j));
01735 }
01736
01737
01738 BOOST_UBLAS_INLINE
01739 bool same_closure (const matrix_binary &mb) const {
01740 return (*this).expression1 ().same_closure (mb.expression1 ()) &&
01741 (*this).expression2 ().same_closure (mb.expression2 ());
01742 }
01743
01744
01745 private:
01746 typedef typename E1::const_iterator1 const_iterator11_type;
01747 typedef typename E1::const_iterator2 const_iterator12_type;
01748 typedef typename E2::const_iterator1 const_iterator21_type;
01749 typedef typename E2::const_iterator2 const_iterator22_type;
01750 typedef const value_type *const_pointer;
01751
01752 public:
01753 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
01754 typedef typename iterator_restrict_traits<typename const_iterator11_type::iterator_category,
01755 typename const_iterator21_type::iterator_category>::iterator_category iterator_category1;
01756 typedef indexed_const_iterator1<const_closure_type, iterator_category1> const_iterator1;
01757 typedef const_iterator1 iterator1;
01758 typedef typename iterator_restrict_traits<typename const_iterator12_type::iterator_category,
01759 typename const_iterator22_type::iterator_category>::iterator_category iterator_category2;
01760 typedef indexed_const_iterator2<const_closure_type, iterator_category2> const_iterator2;
01761 typedef const_iterator2 iterator2;
01762 #else
01763 class const_iterator1;
01764 typedef const_iterator1 iterator1;
01765 class const_iterator2;
01766 typedef const_iterator2 iterator2;
01767 #endif
01768 typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
01769 typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
01770
01771
01772 BOOST_UBLAS_INLINE
01773 const_iterator1 find1 (int rank, size_type i, size_type j) const {
01774 const_iterator11_type it11 (e1_.find1 (rank, i, j));
01775 const_iterator11_type it11_end (e1_.find1 (rank, size1 (), j));
01776 const_iterator21_type it21 (e2_.find1 (rank, i, j));
01777 const_iterator21_type it21_end (e2_.find1 (rank, size1 (), j));
01778 BOOST_UBLAS_CHECK (rank == 0 || it11 == it11_end || it11.index2 () == j, internal_logic ())
01779 BOOST_UBLAS_CHECK (rank == 0 || it21 == it21_end || it21.index2 () == j, internal_logic ())
01780 i = (std::min) (it11 != it11_end ? it11.index1 () : size1 (),
01781 it21 != it21_end ? it21.index1 () : size1 ());
01782 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
01783 return const_iterator1 (*this, i, j);
01784 #else
01785 return const_iterator1 (*this, i, j, it11, it11_end, it21, it21_end);
01786 #endif
01787 }
01788 BOOST_UBLAS_INLINE
01789 const_iterator2 find2 (int rank, size_type i, size_type j) const {
01790 const_iterator12_type it12 (e1_.find2 (rank, i, j));
01791 const_iterator12_type it12_end (e1_.find2 (rank, i, size2 ()));
01792 const_iterator22_type it22 (e2_.find2 (rank, i, j));
01793 const_iterator22_type it22_end (e2_.find2 (rank, i, size2 ()));
01794 BOOST_UBLAS_CHECK (rank == 0 || it12 == it12_end || it12.index1 () == i, internal_logic ())
01795 BOOST_UBLAS_CHECK (rank == 0 || it22 == it22_end || it22.index1 () == i, internal_logic ())
01796 j = (std::min) (it12 != it12_end ? it12.index2 () : size2 (),
01797 it22 != it22_end ? it22.index2 () : size2 ());
01798 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
01799 return const_iterator2 (*this, i, j);
01800 #else
01801 return const_iterator2 (*this, i, j, it12, it12_end, it22, it22_end);
01802 #endif
01803 }
01804
01805
01806
01807
01808 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
01809 class const_iterator1:
01810 public container_const_reference<matrix_binary>,
01811 public iterator_base_traits<typename iterator_restrict_traits<typename E1::const_iterator1::iterator_category,
01812 typename E2::const_iterator1::iterator_category>::iterator_category>::template
01813 iterator_base<const_iterator1, value_type>::type {
01814 public:
01815 typedef typename iterator_restrict_traits<typename E1::const_iterator1::iterator_category,
01816 typename E2::const_iterator1::iterator_category>::iterator_category iterator_category;
01817 typedef typename matrix_binary::difference_type difference_type;
01818 typedef typename matrix_binary::value_type value_type;
01819 typedef typename matrix_binary::const_reference reference;
01820 typedef typename matrix_binary::const_pointer pointer;
01821
01822 typedef const_iterator2 dual_iterator_type;
01823 typedef const_reverse_iterator2 dual_reverse_iterator_type;
01824
01825
01826 BOOST_UBLAS_INLINE
01827 const_iterator1 ():
01828 container_const_reference<self_type> (), i_ (), j_ (), it1_ (), it1_end_ (), it2_ (), it2_end_ () {}
01829 BOOST_UBLAS_INLINE
01830 const_iterator1 (const self_type &mb, size_type i, size_type j,
01831 const const_iterator11_type &it1, const const_iterator11_type &it1_end,
01832 const const_iterator21_type &it2, const const_iterator21_type &it2_end):
01833 container_const_reference<self_type> (mb), i_ (i), j_ (j), it1_ (it1), it1_end_ (it1_end), it2_ (it2), it2_end_ (it2_end) {}
01834
01835 private:
01836
01837 BOOST_UBLAS_INLINE
01838 void increment (dense_random_access_iterator_tag) {
01839 ++ i_; ++ it1_; ++ it2_;
01840 }
01841 BOOST_UBLAS_INLINE
01842 void decrement (dense_random_access_iterator_tag) {
01843 -- i_; -- it1_; -- it2_;
01844 }
01845 BOOST_UBLAS_INLINE
01846 void increment (dense_random_access_iterator_tag, difference_type n) {
01847 i_ += n; it1_ += n; it2_ += n;
01848 }
01849 BOOST_UBLAS_INLINE
01850 void decrement (dense_random_access_iterator_tag, difference_type n) {
01851 i_ -= n; it1_ -= n; it2_ -= n;
01852 }
01853 BOOST_UBLAS_INLINE
01854 value_type dereference (dense_random_access_iterator_tag) const {
01855 return functor_type::apply (*it1_, *it2_);
01856 }
01857
01858
01859 BOOST_UBLAS_INLINE
01860 void increment (packed_random_access_iterator_tag) {
01861 if (it1_ != it1_end_)
01862 if (it1_.index1 () <= i_)
01863 ++ it1_;
01864 if (it2_ != it2_end_)
01865 if (it2_.index1 () <= i_)
01866 ++ it2_;
01867 ++ i_;
01868 }
01869 BOOST_UBLAS_INLINE
01870 void decrement (packed_random_access_iterator_tag) {
01871 if (it1_ != it1_end_)
01872 if (i_ <= it1_.index1 ())
01873 -- it1_;
01874 if (it2_ != it2_end_)
01875 if (i_ <= it2_.index1 ())
01876 -- it2_;
01877 -- i_;
01878 }
01879 BOOST_UBLAS_INLINE
01880 void increment (packed_random_access_iterator_tag, difference_type n) {
01881 while (n > 0) {
01882 increment (packed_random_access_iterator_tag ());
01883 --n;
01884 }
01885 while (n < 0) {
01886 decrement (packed_random_access_iterator_tag ());
01887 ++n;
01888 }
01889 }
01890 BOOST_UBLAS_INLINE
01891 void decrement (packed_random_access_iterator_tag, difference_type n) {
01892 while (n > 0) {
01893 decrement (packed_random_access_iterator_tag ());
01894 --n;
01895 }
01896 while (n < 0) {
01897 increment (packed_random_access_iterator_tag ());
01898 ++n;
01899 }
01900 }
01901 BOOST_UBLAS_INLINE
01902 value_type dereference (packed_random_access_iterator_tag) const {
01903 value_type t1 = value_type();
01904 if (it1_ != it1_end_) {
01905 BOOST_UBLAS_CHECK (it1_.index2 () == j_, internal_logic ());
01906 if (it1_.index1 () == i_)
01907 t1 = *it1_;
01908 }
01909 value_type t2 = value_type();
01910 if (it2_ != it2_end_) {
01911 BOOST_UBLAS_CHECK (it2_.index2 () == j_, internal_logic ());
01912 if (it2_.index1 () == i_)
01913 t2 = *it2_;
01914 }
01915 return functor_type::apply (t1, t2);
01916 }
01917
01918
01919 BOOST_UBLAS_INLINE
01920 void increment (sparse_bidirectional_iterator_tag) {
01921 size_type index1 = (*this) ().size1 ();
01922 if (it1_ != it1_end_) {
01923 if (it1_.index1 () <= i_)
01924 ++ it1_;
01925 if (it1_ != it1_end_)
01926 index1 = it1_.index1 ();
01927 }
01928 size_type index2 = (*this) ().size1 ();
01929 if (it2_ != it2_end_)
01930 if (it2_.index1 () <= i_)
01931 ++ it2_;
01932 if (it2_ != it2_end_) {
01933 index2 = it2_.index1 ();
01934 }
01935 i_ = (std::min) (index1, index2);
01936 }
01937 BOOST_UBLAS_INLINE
01938 void decrement (sparse_bidirectional_iterator_tag) {
01939 size_type index1 = (*this) ().size1 ();
01940 if (it1_ != it1_end_) {
01941 if (i_ <= it1_.index1 ())
01942 -- it1_;
01943 if (it1_ != it1_end_)
01944 index1 = it1_.index1 ();
01945 }
01946 size_type index2 = (*this) ().size1 ();
01947 if (it2_ != it2_end_) {
01948 if (i_ <= it2_.index1 ())
01949 -- it2_;
01950 if (it2_ != it2_end_)
01951 index2 = it2_.index1 ();
01952 }
01953 i_ = (std::max) (index1, index2);
01954 }
01955 BOOST_UBLAS_INLINE
01956 void increment (sparse_bidirectional_iterator_tag, difference_type n) {
01957 while (n > 0) {
01958 increment (sparse_bidirectional_iterator_tag ());
01959 --n;
01960 }
01961 while (n < 0) {
01962 decrement (sparse_bidirectional_iterator_tag ());
01963 ++n;
01964 }
01965 }
01966 BOOST_UBLAS_INLINE
01967 void decrement (sparse_bidirectional_iterator_tag, difference_type n) {
01968 while (n > 0) {
01969 decrement (sparse_bidirectional_iterator_tag ());
01970 --n;
01971 }
01972 while (n < 0) {
01973 increment (sparse_bidirectional_iterator_tag ());
01974 ++n;
01975 }
01976 }
01977 BOOST_UBLAS_INLINE
01978 value_type dereference (sparse_bidirectional_iterator_tag) const {
01979 value_type t1 = value_type();
01980 if (it1_ != it1_end_) {
01981 BOOST_UBLAS_CHECK (it1_.index2 () == j_, internal_logic ());
01982 if (it1_.index1 () == i_)
01983 t1 = *it1_;
01984 }
01985 value_type t2 = value_type();
01986 if (it2_ != it2_end_) {
01987 BOOST_UBLAS_CHECK (it2_.index2 () == j_, internal_logic ());
01988 if (it2_.index1 () == i_)
01989 t2 = *it2_;
01990 }
01991 return functor_type::apply (t1, t2);
01992 }
01993
01994 public:
01995
01996 BOOST_UBLAS_INLINE
01997 const_iterator1 &operator ++ () {
01998 increment (iterator_category ());
01999 return *this;
02000 }
02001 BOOST_UBLAS_INLINE
02002 const_iterator1 &operator -- () {
02003 decrement (iterator_category ());
02004 return *this;
02005 }
02006 BOOST_UBLAS_INLINE
02007 const_iterator1 &operator += (difference_type n) {
02008 increment (iterator_category (), n);
02009 return *this;
02010 }
02011 BOOST_UBLAS_INLINE
02012 const_iterator1 &operator -= (difference_type n) {
02013 decrement (iterator_category (), n);
02014 return *this;
02015 }
02016 BOOST_UBLAS_INLINE
02017 difference_type operator - (const const_iterator1 &it) const {
02018 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
02019 BOOST_UBLAS_CHECK (index2 () == it.index2 (), external_logic ());
02020 return index1 () - it.index1 ();
02021 }
02022
02023
02024 BOOST_UBLAS_INLINE
02025 const_reference operator * () const {
02026 return dereference (iterator_category ());
02027 }
02028 BOOST_UBLAS_INLINE
02029 const_reference operator [] (difference_type n) const {
02030 return *(*this + n);
02031 }
02032
02033 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
02034 BOOST_UBLAS_INLINE
02035 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
02036 typename self_type::
02037 #endif
02038 const_iterator2 begin () const {
02039 return (*this) ().find2 (1, index1 (), 0);
02040 }
02041 BOOST_UBLAS_INLINE
02042 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
02043 typename self_type::
02044 #endif
02045 const_iterator2 end () const {
02046 return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
02047 }
02048 BOOST_UBLAS_INLINE
02049 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
02050 typename self_type::
02051 #endif
02052 const_reverse_iterator2 rbegin () const {
02053 return const_reverse_iterator2 (end ());
02054 }
02055 BOOST_UBLAS_INLINE
02056 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
02057 typename self_type::
02058 #endif
02059 const_reverse_iterator2 rend () const {
02060 return const_reverse_iterator2 (begin ());
02061 }
02062 #endif
02063
02064
02065 BOOST_UBLAS_INLINE
02066 size_type index1 () const {
02067 return i_;
02068 }
02069 BOOST_UBLAS_INLINE
02070 size_type index2 () const {
02071
02072
02073
02074 return j_;
02075 }
02076
02077
02078 BOOST_UBLAS_INLINE
02079 const_iterator1 &operator = (const const_iterator1 &it) {
02080 container_const_reference<self_type>::assign (&it ());
02081 i_ = it.i_;
02082 j_ = it.j_;
02083 it1_ = it.it1_;
02084 it1_end_ = it.it1_end_;
02085 it2_ = it.it2_;
02086 it2_end_ = it.it2_end_;
02087 return *this;
02088 }
02089
02090
02091 BOOST_UBLAS_INLINE
02092 bool operator == (const const_iterator1 &it) const {
02093 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
02094 BOOST_UBLAS_CHECK (index2 () == it.index2 (), external_logic ());
02095 return index1 () == it.index1 ();
02096 }
02097 BOOST_UBLAS_INLINE
02098 bool operator < (const const_iterator1 &it) const {
02099 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
02100 BOOST_UBLAS_CHECK (index2 () == it.index2 (), external_logic ());
02101 return index1 () < it.index1 ();
02102 }
02103
02104 private:
02105 size_type i_;
02106 size_type j_;
02107 const_iterator11_type it1_;
02108 const_iterator11_type it1_end_;
02109 const_iterator21_type it2_;
02110 const_iterator21_type it2_end_;
02111 };
02112 #endif
02113
02114 BOOST_UBLAS_INLINE
02115 const_iterator1 begin1 () const {
02116 return find1 (0, 0, 0);
02117 }
02118 BOOST_UBLAS_INLINE
02119 const_iterator1 end1 () const {
02120 return find1 (0, size1 (), 0);
02121 }
02122
02123 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
02124 class const_iterator2:
02125 public container_const_reference<matrix_binary>,
02126 public iterator_base_traits<typename iterator_restrict_traits<typename E1::const_iterator2::iterator_category,
02127 typename E2::const_iterator2::iterator_category>::iterator_category>::template
02128 iterator_base<const_iterator2, value_type>::type {
02129 public:
02130 typedef typename iterator_restrict_traits<typename E1::const_iterator2::iterator_category,
02131 typename E2::const_iterator2::iterator_category>::iterator_category iterator_category;
02132 typedef typename matrix_binary::difference_type difference_type;
02133 typedef typename matrix_binary::value_type value_type;
02134 typedef typename matrix_binary::const_reference reference;
02135 typedef typename matrix_binary::const_pointer pointer;
02136
02137 typedef const_iterator1 dual_iterator_type;
02138 typedef const_reverse_iterator1 dual_reverse_iterator_type;
02139
02140
02141 BOOST_UBLAS_INLINE
02142 const_iterator2 ():
02143 container_const_reference<self_type> (), i_ (), j_ (), it1_ (), it1_end_ (), it2_ (), it2_end_ () {}
02144 BOOST_UBLAS_INLINE
02145 const_iterator2 (const self_type &mb, size_type i, size_type j,
02146 const const_iterator12_type &it1, const const_iterator12_type &it1_end,
02147 const const_iterator22_type &it2, const const_iterator22_type &it2_end):
02148 container_const_reference<self_type> (mb), i_ (i), j_ (j), it1_ (it1), it1_end_ (it1_end), it2_ (it2), it2_end_ (it2_end) {}
02149
02150 private:
02151
02152 BOOST_UBLAS_INLINE
02153 void increment (dense_random_access_iterator_tag) {
02154 ++ j_; ++ it1_; ++ it2_;
02155 }
02156 BOOST_UBLAS_INLINE
02157 void decrement (dense_random_access_iterator_tag) {
02158 -- j_; -- it1_; -- it2_;
02159 }
02160 BOOST_UBLAS_INLINE
02161 void increment (dense_random_access_iterator_tag, difference_type n) {
02162 j_ += n; it1_ += n; it2_ += n;
02163 }
02164 BOOST_UBLAS_INLINE
02165 void decrement (dense_random_access_iterator_tag, difference_type n) {
02166 j_ -= n; it1_ -= n; it2_ -= n;
02167 }
02168 BOOST_UBLAS_INLINE
02169 value_type dereference (dense_random_access_iterator_tag) const {
02170 return functor_type::apply (*it1_, *it2_);
02171 }
02172
02173
02174 BOOST_UBLAS_INLINE
02175 void increment (packed_random_access_iterator_tag) {
02176 if (it1_ != it1_end_)
02177 if (it1_.index2 () <= j_)
02178 ++ it1_;
02179 if (it2_ != it2_end_)
02180 if (it2_.index2 () <= j_)
02181 ++ it2_;
02182 ++ j_;
02183 }
02184 BOOST_UBLAS_INLINE
02185 void decrement (packed_random_access_iterator_tag) {
02186 if (it1_ != it1_end_)
02187 if (j_ <= it1_.index2 ())
02188 -- it1_;
02189 if (it2_ != it2_end_)
02190 if (j_ <= it2_.index2 ())
02191 -- it2_;
02192 -- j_;
02193 }
02194 BOOST_UBLAS_INLINE
02195 void increment (packed_random_access_iterator_tag, difference_type n) {
02196 while (n > 0) {
02197 increment (packed_random_access_iterator_tag ());
02198 --n;
02199 }
02200 while (n < 0) {
02201 decrement (packed_random_access_iterator_tag ());
02202 ++n;
02203 }
02204 }
02205 BOOST_UBLAS_INLINE
02206 void decrement (packed_random_access_iterator_tag, difference_type n) {
02207 while (n > 0) {
02208 decrement (packed_random_access_iterator_tag ());
02209 --n;
02210 }
02211 while (n < 0) {
02212 increment (packed_random_access_iterator_tag ());
02213 ++n;
02214 }
02215 }
02216 BOOST_UBLAS_INLINE
02217 value_type dereference (packed_random_access_iterator_tag) const {
02218 value_type t1 = value_type();
02219 if (it1_ != it1_end_) {
02220 BOOST_UBLAS_CHECK (it1_.index1 () == i_, internal_logic ());
02221 if (it1_.index2 () == j_)
02222 t1 = *it1_;
02223 }
02224 value_type t2 = value_type();
02225 if (it2_ != it2_end_) {
02226 BOOST_UBLAS_CHECK (it2_.index1 () == i_, internal_logic ());
02227 if (it2_.index2 () == j_)
02228 t2 = *it2_;
02229 }
02230 return functor_type::apply (t1, t2);
02231 }
02232
02233
02234 BOOST_UBLAS_INLINE
02235 void increment (sparse_bidirectional_iterator_tag) {
02236 size_type index1 = (*this) ().size2 ();
02237 if (it1_ != it1_end_) {
02238 if (it1_.index2 () <= j_)
02239 ++ it1_;
02240 if (it1_ != it1_end_)
02241 index1 = it1_.index2 ();
02242 }
02243 size_type index2 = (*this) ().size2 ();
02244 if (it2_ != it2_end_) {
02245 if (it2_.index2 () <= j_)
02246 ++ it2_;
02247 if (it2_ != it2_end_)
02248 index2 = it2_.index2 ();
02249 }
02250 j_ = (std::min) (index1, index2);
02251 }
02252 BOOST_UBLAS_INLINE
02253 void decrement (sparse_bidirectional_iterator_tag) {
02254 size_type index1 = (*this) ().size2 ();
02255 if (it1_ != it1_end_) {
02256 if (j_ <= it1_.index2 ())
02257 -- it1_;
02258 if (it1_ != it1_end_)
02259 index1 = it1_.index2 ();
02260 }
02261 size_type index2 = (*this) ().size2 ();
02262 if (it2_ != it2_end_) {
02263 if (j_ <= it2_.index2 ())
02264 -- it2_;
02265 if (it2_ != it2_end_)
02266 index2 = it2_.index2 ();
02267 }
02268 j_ = (std::max) (index1, index2);
02269 }
02270 BOOST_UBLAS_INLINE
02271 void increment (sparse_bidirectional_iterator_tag, difference_type n) {
02272 while (n > 0) {
02273 increment (sparse_bidirectional_iterator_tag ());
02274 --n;
02275 }
02276 while (n < 0) {
02277 decrement (sparse_bidirectional_iterator_tag ());
02278 ++n;
02279 }
02280 }
02281 BOOST_UBLAS_INLINE
02282 void decrement (sparse_bidirectional_iterator_tag, difference_type n) {
02283 while (n > 0) {
02284 decrement (sparse_bidirectional_iterator_tag ());
02285 --n;
02286 }
02287 while (n < 0) {
02288 increment (sparse_bidirectional_iterator_tag ());
02289 ++n;
02290 }
02291 }
02292 BOOST_UBLAS_INLINE
02293 value_type dereference (sparse_bidirectional_iterator_tag) const {
02294 value_type t1 = value_type();
02295 if (it1_ != it1_end_) {
02296 BOOST_UBLAS_CHECK (it1_.index1 () == i_, internal_logic ());
02297 if (it1_.index2 () == j_)
02298 t1 = *it1_;
02299 }
02300 value_type t2 = value_type();
02301 if (it2_ != it2_end_) {
02302 BOOST_UBLAS_CHECK (it2_.index1 () == i_, internal_logic ());
02303 if (it2_.index2 () == j_)
02304 t2 = *it2_;
02305 }
02306 return functor_type::apply (t1, t2);
02307 }
02308
02309 public:
02310
02311 BOOST_UBLAS_INLINE
02312 const_iterator2 &operator ++ () {
02313 increment (iterator_category ());
02314 return *this;
02315 }
02316 BOOST_UBLAS_INLINE
02317 const_iterator2 &operator -- () {
02318 decrement (iterator_category ());
02319 return *this;
02320 }
02321 BOOST_UBLAS_INLINE
02322 const_iterator2 &operator += (difference_type n) {
02323 increment (iterator_category (), n);
02324 return *this;
02325 }
02326 BOOST_UBLAS_INLINE
02327 const_iterator2 &operator -= (difference_type n) {
02328 decrement (iterator_category (), n);
02329 return *this;
02330 }
02331 BOOST_UBLAS_INLINE
02332 difference_type operator - (const const_iterator2 &it) const {
02333 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
02334 BOOST_UBLAS_CHECK (index1 () == it.index1 (), external_logic ());
02335 return index2 () - it.index2 ();
02336 }
02337
02338
02339 BOOST_UBLAS_INLINE
02340 const_reference operator * () const {
02341 return dereference (iterator_category ());
02342 }
02343 BOOST_UBLAS_INLINE
02344 const_reference operator [] (difference_type n) const {
02345 return *(*this + n);
02346 }
02347
02348 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
02349 BOOST_UBLAS_INLINE
02350 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
02351 typename self_type::
02352 #endif
02353 const_iterator1 begin () const {
02354 return (*this) ().find1 (1, 0, index2 ());
02355 }
02356 BOOST_UBLAS_INLINE
02357 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
02358 typename self_type::
02359 #endif
02360 const_iterator1 end () const {
02361 return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
02362 }
02363 BOOST_UBLAS_INLINE
02364 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
02365 typename self_type::
02366 #endif
02367 const_reverse_iterator1 rbegin () const {
02368 return const_reverse_iterator1 (end ());
02369 }
02370 BOOST_UBLAS_INLINE
02371 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
02372 typename self_type::
02373 #endif
02374 const_reverse_iterator1 rend () const {
02375 return const_reverse_iterator1 (begin ());
02376 }
02377 #endif
02378
02379
02380 BOOST_UBLAS_INLINE
02381 size_type index1 () const {
02382
02383
02384
02385 return i_;
02386 }
02387 BOOST_UBLAS_INLINE
02388 size_type index2 () const {
02389 return j_;
02390 }
02391
02392
02393 BOOST_UBLAS_INLINE
02394 const_iterator2 &operator = (const const_iterator2 &it) {
02395 container_const_reference<self_type>::assign (&it ());
02396 i_ = it.i_;
02397 j_ = it.j_;
02398 it1_ = it.it1_;
02399 it1_end_ = it.it1_end_;
02400 it2_ = it.it2_;
02401 it2_end_ = it.it2_end_;
02402 return *this;
02403 }
02404
02405
02406 BOOST_UBLAS_INLINE
02407 bool operator == (const const_iterator2 &it) const {
02408 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
02409 BOOST_UBLAS_CHECK (index1 () == it.index1 (), external_logic ());
02410 return index2 () == it.index2 ();
02411 }
02412 BOOST_UBLAS_INLINE
02413 bool operator < (const const_iterator2 &it) const {
02414 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
02415 BOOST_UBLAS_CHECK (index1 () == it.index1 (), external_logic ());
02416 return index2 () < it.index2 ();
02417 }
02418
02419 private:
02420 size_type i_;
02421 size_type j_;
02422 const_iterator12_type it1_;
02423 const_iterator12_type it1_end_;
02424 const_iterator22_type it2_;
02425 const_iterator22_type it2_end_;
02426 };
02427 #endif
02428
02429 BOOST_UBLAS_INLINE
02430 const_iterator2 begin2 () const {
02431 return find2 (0, 0, 0);
02432 }
02433 BOOST_UBLAS_INLINE
02434 const_iterator2 end2 () const {
02435 return find2 (0, 0, size2 ());
02436 }
02437
02438
02439
02440 BOOST_UBLAS_INLINE
02441 const_reverse_iterator1 rbegin1 () const {
02442 return const_reverse_iterator1 (end1 ());
02443 }
02444 BOOST_UBLAS_INLINE
02445 const_reverse_iterator1 rend1 () const {
02446 return const_reverse_iterator1 (begin1 ());
02447 }
02448
02449 BOOST_UBLAS_INLINE
02450 const_reverse_iterator2 rbegin2 () const {
02451 return const_reverse_iterator2 (end2 ());
02452 }
02453 BOOST_UBLAS_INLINE
02454 const_reverse_iterator2 rend2 () const {
02455 return const_reverse_iterator2 (begin2 ());
02456 }
02457
02458 private:
02459 expression1_closure_type e1_;
02460 expression2_closure_type e2_;
02461 };
02462
02463 template<class E1, class E2, class F>
02464 struct matrix_binary_traits {
02465 typedef matrix_binary<E1, E2, F> expression_type;
02466 #ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
02467 typedef expression_type result_type;
02468 #else
02469 typedef typename E1::matrix_temporary_type result_type;
02470 #endif
02471 };
02472
02473
02474 template<class E1, class E2>
02475 BOOST_UBLAS_INLINE
02476 typename matrix_binary_traits<E1, E2, scalar_plus<typename E1::value_type,
02477 typename E2::value_type> >::result_type
02478 operator + (const matrix_expression<E1> &e1,
02479 const matrix_expression<E2> &e2) {
02480 typedef typename matrix_binary_traits<E1, E2, scalar_plus<typename E1::value_type,
02481 typename E2::value_type> >::expression_type expression_type;
02482 return expression_type (e1 (), e2 ());
02483 }
02484
02485
02486 template<class E1, class E2>
02487 BOOST_UBLAS_INLINE
02488 typename matrix_binary_traits<E1, E2, scalar_minus<typename E1::value_type,
02489 typename E2::value_type> >::result_type
02490 operator - (const matrix_expression<E1> &e1,
02491 const matrix_expression<E2> &e2) {
02492 typedef typename matrix_binary_traits<E1, E2, scalar_minus<typename E1::value_type,
02493 typename E2::value_type> >::expression_type expression_type;
02494 return expression_type (e1 (), e2 ());
02495 }
02496
02497
02498 template<class E1, class E2>
02499 BOOST_UBLAS_INLINE
02500 typename matrix_binary_traits<E1, E2, scalar_multiplies<typename E1::value_type,
02501 typename E2::value_type> >::result_type
02502 element_prod (const matrix_expression<E1> &e1,
02503 const matrix_expression<E2> &e2) {
02504 typedef typename matrix_binary_traits<E1, E2, scalar_multiplies<typename E1::value_type,
02505 typename E2::value_type> >::expression_type expression_type;
02506 return expression_type (e1 (), e2 ());
02507 }
02508
02509
02510 template<class E1, class E2>
02511 BOOST_UBLAS_INLINE
02512 typename matrix_binary_traits<E1, E2, scalar_divides<typename E1::value_type,
02513 typename E2::value_type> >::result_type
02514 element_div (const matrix_expression<E1> &e1,
02515 const matrix_expression<E2> &e2) {
02516 typedef typename matrix_binary_traits<E1, E2, scalar_divides<typename E1::value_type,
02517 typename E2::value_type> >::expression_type expression_type;
02518 return expression_type (e1 (), e2 ());
02519 }
02520
02521 template<class E1, class E2, class F>
02522 class matrix_binary_scalar1:
02523 public matrix_expression<matrix_binary_scalar1<E1, E2, F> > {
02524
02525 typedef E1 expression1_type;
02526 typedef E2 expression2_type;
02527 typedef F functor_type;
02528 typedef const E1& expression1_closure_type;
02529 typedef typename E2::const_closure_type expression2_closure_type;
02530 typedef matrix_binary_scalar1<E1, E2, F> self_type;
02531 public:
02532 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
02533 using matrix_expression<self_type>::operator ();
02534 #endif
02535 typedef typename E2::size_type size_type;
02536 typedef typename E2::difference_type difference_type;
02537 typedef typename F::result_type value_type;
02538 typedef value_type const_reference;
02539 typedef const_reference reference;
02540 typedef const self_type const_closure_type;
02541 typedef const_closure_type closure_type;
02542 typedef typename E2::orientation_category orientation_category;
02543 typedef unknown_storage_tag storage_category;
02544
02545
02546 BOOST_UBLAS_INLINE
02547 matrix_binary_scalar1 (const expression1_type &e1, const expression2_type &e2):
02548 e1_ (e1), e2_ (e2) {}
02549
02550
02551 BOOST_UBLAS_INLINE
02552 size_type size1 () const {
02553 return e2_.size1 ();
02554 }
02555 BOOST_UBLAS_INLINE
02556 size_type size2 () const {
02557 return e2_.size2 ();
02558 }
02559
02560 public:
02561
02562 BOOST_UBLAS_INLINE
02563 const_reference operator () (size_type i, size_type j) const {
02564 return functor_type::apply (expression1_type (e1_), e2_ (i, j));
02565 }
02566
02567
02568 BOOST_UBLAS_INLINE
02569 bool same_closure (const matrix_binary_scalar1 &mbs1) const {
02570 return &e1_ == &(mbs1.e1_) &&
02571 (*this).e2_.same_closure (mbs1.e2_);
02572 }
02573
02574
02575 private:
02576 typedef expression1_type const_subiterator1_type;
02577 typedef typename E2::const_iterator1 const_iterator21_type;
02578 typedef typename E2::const_iterator2 const_iterator22_type;
02579 typedef const value_type *const_pointer;
02580
02581 public:
02582 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
02583 typedef indexed_const_iterator1<const_closure_type, typename const_iterator21_type::iterator_category> const_iterator1;
02584 typedef const_iterator1 iterator1;
02585 typedef indexed_const_iterator2<const_closure_type, typename const_iterator22_type::iterator_category> const_iterator2;
02586 typedef const_iterator2 iterator2;
02587 #else
02588 class const_iterator1;
02589 typedef const_iterator1 iterator1;
02590 class const_iterator2;
02591 typedef const_iterator2 iterator2;
02592 #endif
02593 typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
02594 typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
02595
02596
02597 BOOST_UBLAS_INLINE
02598 const_iterator1 find1 (int rank, size_type i, size_type j) const {
02599 const_iterator21_type it21 (e2_.find1 (rank, i, j));
02600 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
02601 return const_iterator1 (*this, it21.index1 (), it21.index2 ());
02602 #else
02603 return const_iterator1 (*this, const_subiterator1_type (e1_), it21);
02604 #endif
02605 }
02606 BOOST_UBLAS_INLINE
02607 const_iterator2 find2 (int rank, size_type i, size_type j) const {
02608 const_iterator22_type it22 (e2_.find2 (rank, i, j));
02609 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
02610 return const_iterator2 (*this, it22.index1 (), it22.index2 ());
02611 #else
02612 return const_iterator2 (*this, const_subiterator1_type (e1_), it22);
02613 #endif
02614 }
02615
02616
02617
02618
02619 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
02620 class const_iterator1:
02621 public container_const_reference<matrix_binary_scalar1>,
02622 public iterator_base_traits<typename E2::const_iterator1::iterator_category>::template
02623 iterator_base<const_iterator1, value_type>::type {
02624 public:
02625 typedef typename E2::const_iterator1::iterator_category iterator_category;
02626 typedef typename matrix_binary_scalar1::difference_type difference_type;
02627 typedef typename matrix_binary_scalar1::value_type value_type;
02628 typedef typename matrix_binary_scalar1::const_reference reference;
02629 typedef typename matrix_binary_scalar1::const_pointer pointer;
02630
02631 typedef const_iterator2 dual_iterator_type;
02632 typedef const_reverse_iterator2 dual_reverse_iterator_type;
02633
02634
02635 BOOST_UBLAS_INLINE
02636 const_iterator1 ():
02637 container_const_reference<self_type> (), it1_ (), it2_ () {}
02638 BOOST_UBLAS_INLINE
02639 const_iterator1 (const self_type &mbs, const const_subiterator1_type &it1, const const_iterator21_type &it2):
02640 container_const_reference<self_type> (mbs), it1_ (it1), it2_ (it2) {}
02641
02642
02643 BOOST_UBLAS_INLINE
02644 const_iterator1 &operator ++ () {
02645 ++ it2_;
02646 return *this;
02647 }
02648 BOOST_UBLAS_INLINE
02649 const_iterator1 &operator -- () {
02650 -- it2_ ;
02651 return *this;
02652 }
02653 BOOST_UBLAS_INLINE
02654 const_iterator1 &operator += (difference_type n) {
02655 it2_ += n;
02656 return *this;
02657 }
02658 BOOST_UBLAS_INLINE
02659 const_iterator1 &operator -= (difference_type n) {
02660 it2_ -= n;
02661 return *this;
02662 }
02663 BOOST_UBLAS_INLINE
02664 difference_type operator - (const const_iterator1 &it) const {
02665 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
02666
02667
02668 return it2_ - it.it2_;
02669 }
02670
02671
02672 BOOST_UBLAS_INLINE
02673 const_reference operator * () const {
02674 return functor_type::apply (it1_, *it2_);
02675 }
02676 BOOST_UBLAS_INLINE
02677 const_reference operator [] (difference_type n) const {
02678 return *(*this + n);
02679 }
02680
02681 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
02682 BOOST_UBLAS_INLINE
02683 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
02684 typename self_type::
02685 #endif
02686 const_iterator2 begin () const {
02687 return (*this) ().find2 (1, index1 (), 0);
02688 }
02689 BOOST_UBLAS_INLINE
02690 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
02691 typename self_type::
02692 #endif
02693 const_iterator2 end () const {
02694 return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
02695 }
02696 BOOST_UBLAS_INLINE
02697 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
02698 typename self_type::
02699 #endif
02700 const_reverse_iterator2 rbegin () const {
02701 return const_reverse_iterator2 (end ());
02702 }
02703 BOOST_UBLAS_INLINE
02704 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
02705 typename self_type::
02706 #endif
02707 const_reverse_iterator2 rend () const {
02708 return const_reverse_iterator2 (begin ());
02709 }
02710 #endif
02711
02712
02713 BOOST_UBLAS_INLINE
02714 size_type index1 () const {
02715 return it2_.index1 ();
02716 }
02717 BOOST_UBLAS_INLINE
02718 size_type index2 () const {
02719 return it2_.index2 ();
02720 }
02721
02722
02723 BOOST_UBLAS_INLINE
02724 const_iterator1 &operator = (const const_iterator1 &it) {
02725 container_const_reference<self_type>::assign (&it ());
02726 it1_ = it.it1_;
02727 it2_ = it.it2_;
02728 return *this;
02729 }
02730
02731
02732 BOOST_UBLAS_INLINE
02733 bool operator == (const const_iterator1 &it) const {
02734 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
02735
02736
02737 return it2_ == it.it2_;
02738 }
02739 BOOST_UBLAS_INLINE
02740 bool operator < (const const_iterator1 &it) const {
02741 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
02742
02743
02744 return it2_ < it.it2_;
02745 }
02746
02747 private:
02748 const_subiterator1_type it1_;
02749 const_iterator21_type it2_;
02750 };
02751 #endif
02752
02753 BOOST_UBLAS_INLINE
02754 const_iterator1 begin1 () const {
02755 return find1 (0, 0, 0);
02756 }
02757 BOOST_UBLAS_INLINE
02758 const_iterator1 end1 () const {
02759 return find1 (0, size1 (), 0);
02760 }
02761
02762 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
02763 class const_iterator2:
02764 public container_const_reference<matrix_binary_scalar1>,
02765 public iterator_base_traits<typename E2::const_iterator2::iterator_category>::template
02766 iterator_base<const_iterator2, value_type>::type {
02767 public:
02768 typedef typename E2::const_iterator2::iterator_category iterator_category;
02769 typedef typename matrix_binary_scalar1::difference_type difference_type;
02770 typedef typename matrix_binary_scalar1::value_type value_type;
02771 typedef typename matrix_binary_scalar1::const_reference reference;
02772 typedef typename matrix_binary_scalar1::const_pointer pointer;
02773
02774 typedef const_iterator1 dual_iterator_type;
02775 typedef const_reverse_iterator1 dual_reverse_iterator_type;
02776
02777
02778 BOOST_UBLAS_INLINE
02779 const_iterator2 ():
02780 container_const_reference<self_type> (), it1_ (), it2_ () {}
02781 BOOST_UBLAS_INLINE
02782 const_iterator2 (const self_type &mbs, const const_subiterator1_type &it1, const const_iterator22_type &it2):
02783 container_const_reference<self_type> (mbs), it1_ (it1), it2_ (it2) {}
02784
02785
02786 BOOST_UBLAS_INLINE
02787 const_iterator2 &operator ++ () {
02788 ++ it2_;
02789 return *this;
02790 }
02791 BOOST_UBLAS_INLINE
02792 const_iterator2 &operator -- () {
02793 -- it2_;
02794 return *this;
02795 }
02796 BOOST_UBLAS_INLINE
02797 const_iterator2 &operator += (difference_type n) {
02798 it2_ += n;
02799 return *this;
02800 }
02801 BOOST_UBLAS_INLINE
02802 const_iterator2 &operator -= (difference_type n) {
02803 it2_ -= n;
02804 return *this;
02805 }
02806 BOOST_UBLAS_INLINE
02807 difference_type operator - (const const_iterator2 &it) const {
02808 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
02809
02810
02811 return it2_ - it.it2_;
02812 }
02813
02814
02815 BOOST_UBLAS_INLINE
02816 const_reference operator * () const {
02817 return functor_type::apply (it1_, *it2_);
02818 }
02819 BOOST_UBLAS_INLINE
02820 const_reference operator [] (difference_type n) const {
02821 return *(*this + n);
02822 }
02823
02824 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
02825 BOOST_UBLAS_INLINE
02826 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
02827 typename self_type::
02828 #endif
02829 const_iterator1 begin () const {
02830 return (*this) ().find1 (1, 0, index2 ());
02831 }
02832 BOOST_UBLAS_INLINE
02833 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
02834 typename self_type::
02835 #endif
02836 const_iterator1 end () const {
02837 return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
02838 }
02839 BOOST_UBLAS_INLINE
02840 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
02841 typename self_type::
02842 #endif
02843 const_reverse_iterator1 rbegin () const {
02844 return const_reverse_iterator1 (end ());
02845 }
02846 BOOST_UBLAS_INLINE
02847 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
02848 typename self_type::
02849 #endif
02850 const_reverse_iterator1 rend () const {
02851 return const_reverse_iterator1 (begin ());
02852 }
02853 #endif
02854
02855
02856 BOOST_UBLAS_INLINE
02857 size_type index1 () const {
02858 return it2_.index1 ();
02859 }
02860 BOOST_UBLAS_INLINE
02861 size_type index2 () const {
02862 return it2_.index2 ();
02863 }
02864
02865
02866 BOOST_UBLAS_INLINE
02867 const_iterator2 &operator = (const const_iterator2 &it) {
02868 container_const_reference<self_type>::assign (&it ());
02869 it1_ = it.it1_;
02870 it2_ = it.it2_;
02871 return *this;
02872 }
02873
02874
02875 BOOST_UBLAS_INLINE
02876 bool operator == (const const_iterator2 &it) const {
02877 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
02878
02879
02880 return it2_ == it.it2_;
02881 }
02882 BOOST_UBLAS_INLINE
02883 bool operator < (const const_iterator2 &it) const {
02884 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
02885
02886
02887 return it2_ < it.it2_;
02888 }
02889
02890 private:
02891 const_subiterator1_type it1_;
02892 const_iterator22_type it2_;
02893 };
02894 #endif
02895
02896 BOOST_UBLAS_INLINE
02897 const_iterator2 begin2 () const {
02898 return find2 (0, 0, 0);
02899 }
02900 BOOST_UBLAS_INLINE
02901 const_iterator2 end2 () const {
02902 return find2 (0, 0, size2 ());
02903 }
02904
02905
02906
02907 BOOST_UBLAS_INLINE
02908 const_reverse_iterator1 rbegin1 () const {
02909 return const_reverse_iterator1 (end1 ());
02910 }
02911 BOOST_UBLAS_INLINE
02912 const_reverse_iterator1 rend1 () const {
02913 return const_reverse_iterator1 (begin1 ());
02914 }
02915
02916 BOOST_UBLAS_INLINE
02917 const_reverse_iterator2 rbegin2 () const {
02918 return const_reverse_iterator2 (end2 ());
02919 }
02920 BOOST_UBLAS_INLINE
02921 const_reverse_iterator2 rend2 () const {
02922 return const_reverse_iterator2 (begin2 ());
02923 }
02924
02925 private:
02926 expression1_closure_type e1_;
02927 expression2_closure_type e2_;
02928 };
02929
02930 template<class E1, class E2, class F>
02931 struct matrix_binary_scalar1_traits {
02932 typedef matrix_binary_scalar1<E1, E2, F> expression_type;
02933 #ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
02934 typedef expression_type result_type;
02935 #else
02936 typedef typename E2::matrix_temporary_type result_type;
02937 #endif
02938 };
02939
02940
02941 template<class T1, class E2>
02942 BOOST_UBLAS_INLINE
02943 typename enable_if< is_convertible<T1, typename E2::value_type >,
02944 typename matrix_binary_scalar1_traits<const T1, E2, scalar_multiplies<T1, typename E2::value_type> >::result_type
02945 >::type
02946 operator * (const T1 &e1,
02947 const matrix_expression<E2> &e2) {
02948 typedef typename matrix_binary_scalar1_traits<const T1, E2, scalar_multiplies<T1, typename E2::value_type> >::expression_type expression_type;
02949 return expression_type (e1, e2 ());
02950 }
02951
02952
02953 template<class E1, class E2, class F>
02954 class matrix_binary_scalar2:
02955 public matrix_expression<matrix_binary_scalar2<E1, E2, F> > {
02956
02957 typedef E1 expression1_type;
02958 typedef E2 expression2_type;
02959 typedef F functor_type;
02960 public:
02961 typedef typename E1::const_closure_type expression1_closure_type;
02962 typedef const E2& expression2_closure_type;
02963 private:
02964 typedef matrix_binary_scalar2<E1, E2, F> self_type;
02965 public:
02966 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
02967 using matrix_expression<self_type>::operator ();
02968 #endif
02969 typedef typename E1::size_type size_type;
02970 typedef typename E1::difference_type difference_type;
02971 typedef typename F::result_type value_type;
02972 typedef value_type const_reference;
02973 typedef const_reference reference;
02974
02975 typedef const self_type const_closure_type;
02976 typedef const_closure_type closure_type;
02977 typedef typename E1::orientation_category orientation_category;
02978 typedef unknown_storage_tag storage_category;
02979
02980
02981 BOOST_UBLAS_INLINE
02982 matrix_binary_scalar2 (const expression1_type &e1, const expression2_type &e2):
02983 e1_ (e1), e2_ (e2) {}
02984
02985
02986 BOOST_UBLAS_INLINE
02987 size_type size1 () const {
02988 return e1_.size1 ();
02989 }
02990 BOOST_UBLAS_INLINE
02991 size_type size2 () const {
02992 return e1_.size2 ();
02993 }
02994
02995 public:
02996
02997 BOOST_UBLAS_INLINE
02998 const_reference operator () (size_type i, size_type j) const {
02999 return functor_type::apply (e1_ (i, j), expression2_type (e2_));
03000 }
03001
03002
03003 BOOST_UBLAS_INLINE
03004 bool same_closure (const matrix_binary_scalar2 &mbs2) const {
03005 return (*this).e1_.same_closure (mbs2.e1_) &&
03006 &e2_ == &(mbs2.e2_);
03007 }
03008
03009
03010 private:
03011 typedef typename E1::const_iterator1 const_iterator11_type;
03012 typedef typename E1::const_iterator2 const_iterator12_type;
03013 typedef expression2_type const_subiterator2_type;
03014 typedef const value_type *const_pointer;
03015
03016 public:
03017 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
03018 typedef indexed_const_iterator1<const_closure_type, typename const_iterator11_type::iterator_category> const_iterator1;
03019 typedef const_iterator1 iterator1;
03020 typedef indexed_const_iterator2<const_closure_type, typename const_iterator12_type::iterator_category> const_iterator2;
03021 typedef const_iterator2 iterator2;
03022 #else
03023 class const_iterator1;
03024 typedef const_iterator1 iterator1;
03025 class const_iterator2;
03026 typedef const_iterator2 iterator2;
03027 #endif
03028 typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
03029 typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
03030
03031
03032 BOOST_UBLAS_INLINE
03033 const_iterator1 find1 (int rank, size_type i, size_type j) const {
03034 const_iterator11_type it11 (e1_.find1 (rank, i, j));
03035 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
03036 return const_iterator1 (*this, it11.index1 (), it11.index2 ());
03037 #else
03038 return const_iterator1 (*this, it11, const_subiterator2_type (e2_));
03039 #endif
03040 }
03041 BOOST_UBLAS_INLINE
03042 const_iterator2 find2 (int rank, size_type i, size_type j) const {
03043 const_iterator12_type it12 (e1_.find2 (rank, i, j));
03044 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
03045 return const_iterator2 (*this, it12.index1 (), it12.index2 ());
03046 #else
03047 return const_iterator2 (*this, it12, const_subiterator2_type (e2_));
03048 #endif
03049 }
03050
03051
03052
03053
03054 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
03055 class const_iterator1:
03056 public container_const_reference<matrix_binary_scalar2>,
03057 public iterator_base_traits<typename E1::const_iterator1::iterator_category>::template
03058 iterator_base<const_iterator1, value_type>::type {
03059 public:
03060 typedef typename E1::const_iterator1::iterator_category iterator_category;
03061 typedef typename matrix_binary_scalar2::difference_type difference_type;
03062 typedef typename matrix_binary_scalar2::value_type value_type;
03063 typedef typename matrix_binary_scalar2::const_reference reference;
03064 typedef typename matrix_binary_scalar2::const_pointer pointer;
03065
03066 typedef const_iterator2 dual_iterator_type;
03067 typedef const_reverse_iterator2 dual_reverse_iterator_type;
03068
03069
03070 BOOST_UBLAS_INLINE
03071 const_iterator1 ():
03072 container_const_reference<self_type> (), it1_ (), it2_ () {}
03073 BOOST_UBLAS_INLINE
03074 const_iterator1 (const self_type &mbs, const const_iterator11_type &it1, const const_subiterator2_type &it2):
03075 container_const_reference<self_type> (mbs), it1_ (it1), it2_ (it2) {}
03076
03077
03078 BOOST_UBLAS_INLINE
03079 const_iterator1 &operator ++ () {
03080 ++ it1_;
03081 return *this;
03082 }
03083 BOOST_UBLAS_INLINE
03084 const_iterator1 &operator -- () {
03085 -- it1_ ;
03086 return *this;
03087 }
03088 BOOST_UBLAS_INLINE
03089 const_iterator1 &operator += (difference_type n) {
03090 it1_ += n;
03091 return *this;
03092 }
03093 BOOST_UBLAS_INLINE
03094 const_iterator1 &operator -= (difference_type n) {
03095 it1_ -= n;
03096 return *this;
03097 }
03098 BOOST_UBLAS_INLINE
03099 difference_type operator - (const const_iterator1 &it) const {
03100 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
03101
03102
03103 return it1_ - it.it1_;
03104 }
03105
03106
03107 BOOST_UBLAS_INLINE
03108 const_reference operator * () const {
03109 return functor_type::apply (*it1_, it2_);
03110 }
03111 BOOST_UBLAS_INLINE
03112 const_reference operator [] (difference_type n) const {
03113 return *(*this + n);
03114 }
03115
03116 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
03117 BOOST_UBLAS_INLINE
03118 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
03119 typename self_type::
03120 #endif
03121 const_iterator2 begin () const {
03122 return (*this) ().find2 (1, index1 (), 0);
03123 }
03124 BOOST_UBLAS_INLINE
03125 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
03126 typename self_type::
03127 #endif
03128 const_iterator2 end () const {
03129 return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
03130 }
03131 BOOST_UBLAS_INLINE
03132 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
03133 typename self_type::
03134 #endif
03135 const_reverse_iterator2 rbegin () const {
03136 return const_reverse_iterator2 (end ());
03137 }
03138 BOOST_UBLAS_INLINE
03139 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
03140 typename self_type::
03141 #endif
03142 const_reverse_iterator2 rend () const {
03143 return const_reverse_iterator2 (begin ());
03144 }
03145 #endif
03146
03147
03148 BOOST_UBLAS_INLINE
03149 size_type index1 () const {
03150 return it1_.index1 ();
03151 }
03152 BOOST_UBLAS_INLINE
03153 size_type index2 () const {
03154 return it1_.index2 ();
03155 }
03156
03157
03158 BOOST_UBLAS_INLINE
03159 const_iterator1 &operator = (const const_iterator1 &it) {
03160 container_const_reference<self_type>::assign (&it ());
03161 it1_ = it.it1_;
03162 it2_ = it.it2_;
03163 return *this;
03164 }
03165
03166
03167 BOOST_UBLAS_INLINE
03168 bool operator == (const const_iterator1 &it) const {
03169 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
03170
03171
03172 return it1_ == it.it1_;
03173 }
03174 BOOST_UBLAS_INLINE
03175 bool operator < (const const_iterator1 &it) const {
03176 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
03177
03178
03179 return it1_ < it.it1_;
03180 }
03181
03182 private:
03183 const_iterator11_type it1_;
03184 const_subiterator2_type it2_;
03185 };
03186 #endif
03187
03188 BOOST_UBLAS_INLINE
03189 const_iterator1 begin1 () const {
03190 return find1 (0, 0, 0);
03191 }
03192 BOOST_UBLAS_INLINE
03193 const_iterator1 end1 () const {
03194 return find1 (0, size1 (), 0);
03195 }
03196
03197 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
03198 class const_iterator2:
03199 public container_const_reference<matrix_binary_scalar2>,
03200 public iterator_base_traits<typename E1::const_iterator2::iterator_category>::template
03201 iterator_base<const_iterator2, value_type>::type {
03202 public:
03203 typedef typename E1::const_iterator2::iterator_category iterator_category;
03204 typedef typename matrix_binary_scalar2::difference_type difference_type;
03205 typedef typename matrix_binary_scalar2::value_type value_type;
03206 typedef typename matrix_binary_scalar2::const_reference reference;
03207 typedef typename matrix_binary_scalar2::const_pointer pointer;
03208
03209 typedef const_iterator1 dual_iterator_type;
03210 typedef const_reverse_iterator1 dual_reverse_iterator_type;
03211
03212
03213 BOOST_UBLAS_INLINE
03214 const_iterator2 ():
03215 container_const_reference<self_type> (), it1_ (), it2_ () {}
03216 BOOST_UBLAS_INLINE
03217 const_iterator2 (const self_type &mbs, const const_iterator12_type &it1, const const_subiterator2_type &it2):
03218 container_const_reference<self_type> (mbs), it1_ (it1), it2_ (it2) {}
03219
03220
03221 BOOST_UBLAS_INLINE
03222 const_iterator2 &operator ++ () {
03223 ++ it1_;
03224 return *this;
03225 }
03226 BOOST_UBLAS_INLINE
03227 const_iterator2 &operator -- () {
03228 -- it1_;
03229 return *this;
03230 }
03231 BOOST_UBLAS_INLINE
03232 const_iterator2 &operator += (difference_type n) {
03233 it1_ += n;
03234 return *this;
03235 }
03236 BOOST_UBLAS_INLINE
03237 const_iterator2 &operator -= (difference_type n) {
03238 it1_ -= n;
03239 return *this;
03240 }
03241 BOOST_UBLAS_INLINE
03242 difference_type operator - (const const_iterator2 &it) const {
03243 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
03244
03245
03246 return it1_ - it.it1_;
03247 }
03248
03249
03250 BOOST_UBLAS_INLINE
03251 const_reference operator * () const {
03252 return functor_type::apply (*it1_, it2_);
03253 }
03254 BOOST_UBLAS_INLINE
03255 const_reference operator [] (difference_type n) const {
03256 return *(*this + n);
03257 }
03258
03259 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
03260 BOOST_UBLAS_INLINE
03261 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
03262 typename self_type::
03263 #endif
03264 const_iterator1 begin () const {
03265 return (*this) ().find1 (1, 0, index2 ());
03266 }
03267 BOOST_UBLAS_INLINE
03268 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
03269 typename self_type::
03270 #endif
03271 const_iterator1 end () const {
03272 return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
03273 }
03274 BOOST_UBLAS_INLINE
03275 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
03276 typename self_type::
03277 #endif
03278 const_reverse_iterator1 rbegin () const {
03279 return const_reverse_iterator1 (end ());
03280 }
03281 BOOST_UBLAS_INLINE
03282 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
03283 typename self_type::
03284 #endif
03285 const_reverse_iterator1 rend () const {
03286 return const_reverse_iterator1 (begin ());
03287 }
03288 #endif
03289
03290
03291 BOOST_UBLAS_INLINE
03292 size_type index1 () const {
03293 return it1_.index1 ();
03294 }
03295 BOOST_UBLAS_INLINE
03296 size_type index2 () const {
03297 return it1_.index2 ();
03298 }
03299
03300
03301 BOOST_UBLAS_INLINE
03302 const_iterator2 &operator = (const const_iterator2 &it) {
03303 container_const_reference<self_type>::assign (&it ());
03304 it1_ = it.it1_;
03305 it2_ = it.it2_;
03306 return *this;
03307 }
03308
03309
03310 BOOST_UBLAS_INLINE
03311 bool operator == (const const_iterator2 &it) const {
03312 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
03313
03314
03315 return it1_ == it.it1_;
03316 }
03317 BOOST_UBLAS_INLINE
03318 bool operator < (const const_iterator2 &it) const {
03319 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
03320
03321
03322 return it1_ < it.it1_;
03323 }
03324
03325 private:
03326 const_iterator12_type it1_;
03327 const_subiterator2_type it2_;
03328 };
03329 #endif
03330
03331 BOOST_UBLAS_INLINE
03332 const_iterator2 begin2 () const {
03333 return find2 (0, 0, 0);
03334 }
03335 BOOST_UBLAS_INLINE
03336 const_iterator2 end2 () const {
03337 return find2 (0, 0, size2 ());
03338 }
03339
03340
03341
03342 BOOST_UBLAS_INLINE
03343 const_reverse_iterator1 rbegin1 () const {
03344 return const_reverse_iterator1 (end1 ());
03345 }
03346 BOOST_UBLAS_INLINE
03347 const_reverse_iterator1 rend1 () const {
03348 return const_reverse_iterator1 (begin1 ());
03349 }
03350
03351 BOOST_UBLAS_INLINE
03352 const_reverse_iterator2 rbegin2 () const {
03353 return const_reverse_iterator2 (end2 ());
03354 }
03355 BOOST_UBLAS_INLINE
03356 const_reverse_iterator2 rend2 () const {
03357 return const_reverse_iterator2 (begin2 ());
03358 }
03359
03360 private:
03361 expression1_closure_type e1_;
03362 expression2_closure_type e2_;
03363 };
03364
03365 template<class E1, class E2, class F>
03366 struct matrix_binary_scalar2_traits {
03367 typedef matrix_binary_scalar2<E1, E2, F> expression_type;
03368 #ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
03369 typedef expression_type result_type;
03370 #else
03371 typedef typename E1::matrix_temporary_type result_type;
03372 #endif
03373 };
03374
03375
03376 template<class E1, class T2>
03377 BOOST_UBLAS_INLINE
03378 typename enable_if< is_convertible<T2, typename E1::value_type>,
03379 typename matrix_binary_scalar2_traits<E1, const T2, scalar_multiplies<typename E1::value_type, T2> >::result_type
03380 >::type
03381 operator * (const matrix_expression<E1> &e1,
03382 const T2 &e2) {
03383 typedef typename matrix_binary_scalar2_traits<E1, const T2, scalar_multiplies<typename E1::value_type, T2> >::expression_type expression_type;
03384 return expression_type (e1 (), e2);
03385 }
03386
03387
03388 template<class E1, class T2>
03389 BOOST_UBLAS_INLINE
03390 typename matrix_binary_scalar2_traits<E1, const T2, scalar_divides<typename E1::value_type, T2> >::result_type
03391 operator / (const matrix_expression<E1> &e1,
03392 const T2 &e2) {
03393 typedef typename matrix_binary_scalar2_traits<E1, const T2, scalar_divides<typename E1::value_type, T2> >::expression_type expression_type;
03394 return expression_type (e1 (), e2);
03395 }
03396
03397
03398 template<class E1, class E2, class F>
03399 class matrix_vector_binary1:
03400 public vector_expression<matrix_vector_binary1<E1, E2, F> > {
03401
03402 public:
03403 typedef E1 expression1_type;
03404 typedef E2 expression2_type;
03405 private:
03406 typedef F functor_type;
03407 public:
03408 typedef typename E1::const_closure_type expression1_closure_type;
03409 typedef typename E2::const_closure_type expression2_closure_type;
03410 private:
03411 typedef matrix_vector_binary1<E1, E2, F> self_type;
03412 public:
03413 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
03414 using vector_expression<self_type>::operator ();
03415 #endif
03416 static const unsigned complexity = 1;
03417 typedef typename promote_traits<typename E1::size_type, typename E2::size_type>::promote_type size_type;
03418 typedef typename promote_traits<typename E1::difference_type, typename E2::difference_type>::promote_type difference_type;
03419 typedef typename F::result_type value_type;
03420 typedef value_type const_reference;
03421 typedef const_reference reference;
03422 typedef const self_type const_closure_type;
03423 typedef const_closure_type closure_type;
03424 typedef unknown_storage_tag storage_category;
03425
03426
03427 BOOST_UBLAS_INLINE
03428 matrix_vector_binary1 (const expression1_type &e1, const expression2_type &e2):
03429 e1_ (e1), e2_ (e2) {}
03430
03431
03432 BOOST_UBLAS_INLINE
03433 size_type size () const {
03434 return e1_.size1 ();
03435 }
03436
03437 public:
03438
03439 BOOST_UBLAS_INLINE
03440 const expression1_closure_type &expression1 () const {
03441 return e1_;
03442 }
03443 BOOST_UBLAS_INLINE
03444 const expression2_closure_type &expression2 () const {
03445 return e2_;
03446 }
03447
03448 public:
03449
03450 BOOST_UBLAS_INLINE
03451 const_reference operator () (size_type i) const {
03452 return functor_type::apply (e1_, e2_, i);
03453 }
03454
03455
03456 BOOST_UBLAS_INLINE
03457 bool same_closure (const matrix_vector_binary1 &mvb1) const {
03458 return (*this).expression1 ().same_closure (mvb1.expression1 ()) &&
03459 (*this).expression2 ().same_closure (mvb1.expression2 ());
03460 }
03461
03462
03463 private:
03464 typedef typename E1::const_iterator1 const_subiterator1_type;
03465 typedef typename E2::const_iterator const_subiterator2_type;
03466 typedef const value_type *const_pointer;
03467
03468 public:
03469 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
03470 typedef indexed_const_iterator<const_closure_type, typename const_subiterator1_type::iterator_category> const_iterator;
03471 typedef const_iterator iterator;
03472 #else
03473 class const_iterator;
03474 typedef const_iterator iterator;
03475 #endif
03476
03477
03478 BOOST_UBLAS_INLINE
03479 const_iterator find (size_type i) const {
03480 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
03481 const_subiterator1_type it1 (e1_.find1 (0, i, 0));
03482 return const_iterator (*this, it1.index1 ());
03483 #else
03484 return const_iterator (*this, e1_.find1 (0, i, 0));
03485 #endif
03486 }
03487
03488
03489 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
03490 class const_iterator:
03491 public container_const_reference<matrix_vector_binary1>,
03492 public iterator_base_traits<typename iterator_restrict_traits<typename E1::const_iterator1::iterator_category,
03493 typename E2::const_iterator::iterator_category>::iterator_category>::template
03494 iterator_base<const_iterator, value_type>::type {
03495 public:
03496 typedef typename iterator_restrict_traits<typename E1::const_iterator1::iterator_category,
03497 typename E2::const_iterator::iterator_category>::iterator_category iterator_category;
03498 typedef typename matrix_vector_binary1::difference_type difference_type;
03499 typedef typename matrix_vector_binary1::value_type value_type;
03500 typedef typename matrix_vector_binary1::const_reference reference;
03501 typedef typename matrix_vector_binary1::const_pointer pointer;
03502
03503
03504 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
03505 BOOST_UBLAS_INLINE
03506 const_iterator ():
03507 container_const_reference<self_type> (), it1_ (), e2_begin_ (), e2_end_ () {}
03508 BOOST_UBLAS_INLINE
03509 const_iterator (const self_type &mvb, const const_subiterator1_type &it1):
03510 container_const_reference<self_type> (mvb), it1_ (it1), e2_begin_ (mvb.expression2 ().begin ()), e2_end_ (mvb.expression2 ().end ()) {}
03511 #else
03512 BOOST_UBLAS_INLINE
03513 const_iterator ():
03514 container_const_reference<self_type> (), it1_ () {}
03515 BOOST_UBLAS_INLINE
03516 const_iterator (const self_type &mvb, const const_subiterator1_type &it1):
03517 container_const_reference<self_type> (mvb), it1_ (it1) {}
03518 #endif
03519
03520 private:
03521
03522 BOOST_UBLAS_INLINE
03523 value_type dereference (dense_random_access_iterator_tag) const {
03524 const self_type &mvb = (*this) ();
03525 #ifdef BOOST_UBLAS_USE_INDEXING
03526 return mvb (index ());
03527 #elif BOOST_UBLAS_USE_ITERATING
03528 difference_type size = BOOST_UBLAS_SAME (mvb.expression1 ().size2 (), mvb.expression2 ().size ());
03529 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
03530 return functor_type::apply (size, it1_.begin (), e2_begin_);
03531 #else
03532 return functor_type::apply (size, it1_.begin (), mvb.expression2 ().begin ());
03533 #endif
03534 #else
03535 difference_type size = BOOST_UBLAS_SAME (mvb.expression1 ().size2 (), mvb.expression2 ().size ());
03536 if (size >= BOOST_UBLAS_ITERATOR_THRESHOLD)
03537 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
03538 return functor_type::apply (size, it1_.begin (), e2_begin_);
03539 #else
03540 return functor_type::apply (size, it1_.begin (), mvb.expression2 ().begin ());
03541 #endif
03542 else
03543 return mvb (index ());
03544 #endif
03545 }
03546
03547
03548 BOOST_UBLAS_INLINE
03549 value_type dereference (packed_random_access_iterator_tag) const {
03550 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
03551 return functor_type::apply (it1_.begin (), it1_.end (), e2_begin_, e2_end_);
03552 #else
03553 const self_type &mvb = (*this) ();
03554 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
03555 return functor_type::apply (it1_.begin (), it1_.end (),
03556 mvb.expression2 ().begin (), mvb.expression2 ().end ());
03557 #else
03558 return functor_type::apply (boost::numeric::ublas::begin (it1_, iterator1_tag ()),
03559 boost::numeric::ublas::end (it1_, iterator1_tag ()),
03560 mvb.expression2 ().begin (), mvb.expression2 ().end ());
03561 #endif
03562 #endif
03563 }
03564
03565
03566 BOOST_UBLAS_INLINE
03567 value_type dereference (sparse_bidirectional_iterator_tag) const {
03568 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
03569 return functor_type::apply (it1_.begin (), it1_.end (), e2_begin_, e2_end_, sparse_bidirectional_iterator_tag ());
03570 #else
03571 const self_type &mvb = (*this) ();
03572 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
03573 return functor_type::apply (it1_.begin (), it1_.end (),
03574 mvb.expression2 ().begin (), mvb.expression2 ().end (), sparse_bidirectional_iterator_tag ());
03575 #else
03576 return functor_type::apply (boost::numeric::ublas::begin (it1_, iterator1_tag ()),
03577 boost::numeric::ublas::end (it1_, iterator1_tag ()),
03578 mvb.expression2 ().begin (), mvb.expression2 ().end (), sparse_bidirectional_iterator_tag ());
03579 #endif
03580 #endif
03581 }
03582
03583 public:
03584
03585 BOOST_UBLAS_INLINE
03586 const_iterator &operator ++ () {
03587 ++ it1_;
03588 return *this;
03589 }
03590 BOOST_UBLAS_INLINE
03591 const_iterator &operator -- () {
03592 -- it1_;
03593 return *this;
03594 }
03595 BOOST_UBLAS_INLINE
03596 const_iterator &operator += (difference_type n) {
03597 it1_ += n;
03598 return *this;
03599 }
03600 BOOST_UBLAS_INLINE
03601 const_iterator &operator -= (difference_type n) {
03602 it1_ -= n;
03603 return *this;
03604 }
03605 BOOST_UBLAS_INLINE
03606 difference_type operator - (const const_iterator &it) const {
03607 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
03608 return it1_ - it.it1_;
03609 }
03610
03611
03612 BOOST_UBLAS_INLINE
03613 const_reference operator * () const {
03614 return dereference (iterator_category ());
03615 }
03616 BOOST_UBLAS_INLINE
03617 const_reference operator [] (difference_type n) const {
03618 return *(*this + n);
03619 }
03620
03621
03622 BOOST_UBLAS_INLINE
03623 size_type index () const {
03624 return it1_.index1 ();
03625 }
03626
03627
03628 BOOST_UBLAS_INLINE
03629 const_iterator &operator = (const const_iterator &it) {
03630 container_const_reference<self_type>::assign (&it ());
03631 it1_ = it.it1_;
03632 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
03633 e2_begin_ = it.e2_begin_;
03634 e2_end_ = it.e2_end_;
03635 #endif
03636 return *this;
03637 }
03638
03639
03640 BOOST_UBLAS_INLINE
03641 bool operator == (const const_iterator &it) const {
03642 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
03643 return it1_ == it.it1_;
03644 }
03645 BOOST_UBLAS_INLINE
03646 bool operator < (const const_iterator &it) const {
03647 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
03648 return it1_ < it.it1_;
03649 }
03650
03651 private:
03652 const_subiterator1_type it1_;
03653 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
03654
03655 const_subiterator2_type e2_begin_;
03656 const_subiterator2_type e2_end_;
03657 #endif
03658 };
03659 #endif
03660
03661 BOOST_UBLAS_INLINE
03662 const_iterator begin () const {
03663 return find (0);
03664 }
03665 BOOST_UBLAS_INLINE
03666 const_iterator end () const {
03667 return find (size ());
03668 }
03669
03670
03671 typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
03672
03673 BOOST_UBLAS_INLINE
03674 const_reverse_iterator rbegin () const {
03675 return const_reverse_iterator (end ());
03676 }
03677 BOOST_UBLAS_INLINE
03678 const_reverse_iterator rend () const {
03679 return const_reverse_iterator (begin ());
03680 }
03681
03682 private:
03683 expression1_closure_type e1_;
03684 expression2_closure_type e2_;
03685 };
03686
03687 template<class T1, class E1, class T2, class E2>
03688 struct matrix_vector_binary1_traits {
03689 typedef unknown_storage_tag storage_category;
03690 typedef row_major_tag orientation_category;
03691 typedef typename promote_traits<T1, T2>::promote_type promote_type;
03692 typedef matrix_vector_binary1<E1, E2, matrix_vector_prod1<E1, E2, promote_type> > expression_type;
03693 #ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
03694 typedef expression_type result_type;
03695 #else
03696 typedef typename E1::vector_temporary_type result_type;
03697 #endif
03698 };
03699
03700 template<class E1, class E2>
03701 BOOST_UBLAS_INLINE
03702 typename matrix_vector_binary1_traits<typename E1::value_type, E1,
03703 typename E2::value_type, E2>::result_type
03704 prod (const matrix_expression<E1> &e1,
03705 const vector_expression<E2> &e2,
03706 unknown_storage_tag,
03707 row_major_tag) {
03708 typedef typename matrix_vector_binary1_traits<typename E1::value_type, E1,
03709 typename E2::value_type, E2>::expression_type expression_type;
03710 return expression_type (e1 (), e2 ());
03711 }
03712
03713
03714 template<class E1, class E2>
03715 BOOST_UBLAS_INLINE
03716 typename matrix_vector_binary1_traits<typename E1::value_type, E1,
03717 typename E2::value_type, E2>::result_type
03718 prod (const matrix_expression<E1> &e1,
03719 const vector_expression<E2> &e2) {
03720 BOOST_STATIC_ASSERT (E2::complexity == 0);
03721 typedef typename matrix_vector_binary1_traits<typename E1::value_type, E1,
03722 typename E2::value_type, E2>::storage_category storage_category;
03723 typedef typename matrix_vector_binary1_traits<typename E1::value_type, E1,
03724 typename E2::value_type, E2>::orientation_category orientation_category;
03725 return prod (e1, e2, storage_category (), orientation_category ());
03726 }
03727
03728 template<class E1, class E2>
03729 BOOST_UBLAS_INLINE
03730 typename matrix_vector_binary1_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
03731 typename type_traits<typename E2::value_type>::precision_type, E2>::result_type
03732 prec_prod (const matrix_expression<E1> &e1,
03733 const vector_expression<E2> &e2,
03734 unknown_storage_tag,
03735 row_major_tag) {
03736 typedef typename matrix_vector_binary1_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
03737 typename type_traits<typename E2::value_type>::precision_type, E2>::expression_type expression_type;
03738 return expression_type (e1 (), e2 ());
03739 }
03740
03741
03742 template<class E1, class E2>
03743 BOOST_UBLAS_INLINE
03744 typename matrix_vector_binary1_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
03745 typename type_traits<typename E2::value_type>::precision_type, E2>::result_type
03746 prec_prod (const matrix_expression<E1> &e1,
03747 const vector_expression<E2> &e2) {
03748 BOOST_STATIC_ASSERT (E2::complexity == 0);
03749 typedef typename matrix_vector_binary1_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
03750 typename type_traits<typename E2::value_type>::precision_type, E2>::storage_category storage_category;
03751 typedef typename matrix_vector_binary1_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
03752 typename type_traits<typename E2::value_type>::precision_type, E2>::orientation_category orientation_category;
03753 return prec_prod (e1, e2, storage_category (), orientation_category ());
03754 }
03755
03756 template<class V, class E1, class E2>
03757 BOOST_UBLAS_INLINE
03758 V &
03759 prod (const matrix_expression<E1> &e1,
03760 const vector_expression<E2> &e2,
03761 V &v) {
03762 return v.assign (prod (e1, e2));
03763 }
03764
03765 template<class V, class E1, class E2>
03766 BOOST_UBLAS_INLINE
03767 V &
03768 prec_prod (const matrix_expression<E1> &e1,
03769 const vector_expression<E2> &e2,
03770 V &v) {
03771 return v.assign (prec_prod (e1, e2));
03772 }
03773
03774 template<class V, class E1, class E2>
03775 BOOST_UBLAS_INLINE
03776 V
03777 prod (const matrix_expression<E1> &e1,
03778 const vector_expression<E2> &e2) {
03779 return V (prod (e1, e2));
03780 }
03781
03782 template<class V, class E1, class E2>
03783 BOOST_UBLAS_INLINE
03784 V
03785 prec_prod (const matrix_expression<E1> &e1,
03786 const vector_expression<E2> &e2) {
03787 return V (prec_prod (e1, e2));
03788 }
03789
03790 template<class E1, class E2, class F>
03791 class matrix_vector_binary2:
03792 public vector_expression<matrix_vector_binary2<E1, E2, F> > {
03793
03794 typedef E1 expression1_type;
03795 typedef E2 expression2_type;
03796 typedef F functor_type;
03797 public:
03798 typedef typename E1::const_closure_type expression1_closure_type;
03799 typedef typename E2::const_closure_type expression2_closure_type;
03800 private:
03801 typedef matrix_vector_binary2<E1, E2, F> self_type;
03802 public:
03803 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
03804 using vector_expression<self_type>::operator ();
03805 #endif
03806 static const unsigned complexity = 1;
03807 typedef typename promote_traits<typename E1::size_type, typename E2::size_type>::promote_type size_type;
03808 typedef typename promote_traits<typename E1::difference_type, typename E2::difference_type>::promote_type difference_type;
03809 typedef typename F::result_type value_type;
03810 typedef value_type const_reference;
03811 typedef const_reference reference;
03812 typedef const self_type const_closure_type;
03813 typedef const_closure_type closure_type;
03814 typedef unknown_storage_tag storage_category;
03815
03816
03817 BOOST_UBLAS_INLINE
03818 matrix_vector_binary2 (const expression1_type &e1, const expression2_type &e2):
03819 e1_ (e1), e2_ (e2) {}
03820
03821
03822 BOOST_UBLAS_INLINE
03823 size_type size () const {
03824 return e2_.size2 ();
03825 }
03826
03827 public:
03828
03829 BOOST_UBLAS_INLINE
03830 const expression1_closure_type &expression1 () const {
03831 return e1_;
03832 }
03833 BOOST_UBLAS_INLINE
03834 const expression2_closure_type &expression2 () const {
03835 return e2_;
03836 }
03837 public:
03838
03839
03840 BOOST_UBLAS_INLINE
03841 const_reference operator () (size_type j) const {
03842 return functor_type::apply (e1_, e2_, j);
03843 }
03844
03845
03846 BOOST_UBLAS_INLINE
03847 bool same_closure (const matrix_vector_binary2 &mvb2) const {
03848 return (*this).expression1 ().same_closure (mvb2.expression1 ()) &&
03849 (*this).expression2 ().same_closure (mvb2.expression2 ());
03850 }
03851
03852
03853 private:
03854 typedef typename E1::const_iterator const_subiterator1_type;
03855 typedef typename E2::const_iterator2 const_subiterator2_type;
03856 typedef const value_type *const_pointer;
03857
03858 public:
03859 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
03860 typedef indexed_const_iterator<const_closure_type, typename const_subiterator2_type::iterator_category> const_iterator;
03861 typedef const_iterator iterator;
03862 #else
03863 class const_iterator;
03864 typedef const_iterator iterator;
03865 #endif
03866
03867
03868 BOOST_UBLAS_INLINE
03869 const_iterator find (size_type j) const {
03870 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
03871 const_subiterator2_type it2 (e2_.find2 (0, 0, j));
03872 return const_iterator (*this, it2.index2 ());
03873 #else
03874 return const_iterator (*this, e2_.find2 (0, 0, j));
03875 #endif
03876 }
03877
03878
03879 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
03880 class const_iterator:
03881 public container_const_reference<matrix_vector_binary2>,
03882 public iterator_base_traits<typename iterator_restrict_traits<typename E1::const_iterator::iterator_category,
03883 typename E2::const_iterator2::iterator_category>::iterator_category>::template
03884 iterator_base<const_iterator, value_type>::type {
03885 public:
03886 typedef typename iterator_restrict_traits<typename E1::const_iterator::iterator_category,
03887 typename E2::const_iterator2::iterator_category>::iterator_category iterator_category;
03888 typedef typename matrix_vector_binary2::difference_type difference_type;
03889 typedef typename matrix_vector_binary2::value_type value_type;
03890 typedef typename matrix_vector_binary2::const_reference reference;
03891 typedef typename matrix_vector_binary2::const_pointer pointer;
03892
03893
03894 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
03895 BOOST_UBLAS_INLINE
03896 const_iterator ():
03897 container_const_reference<self_type> (), it2_ (), e1_begin_ (), e1_end_ () {}
03898 BOOST_UBLAS_INLINE
03899 const_iterator (const self_type &mvb, const const_subiterator2_type &it2):
03900 container_const_reference<self_type> (mvb), it2_ (it2), e1_begin_ (mvb.expression1 ().begin ()), e1_end_ (mvb.expression1 ().end ()) {}
03901 #else
03902 BOOST_UBLAS_INLINE
03903 const_iterator ():
03904 container_const_reference<self_type> (), it2_ () {}
03905 BOOST_UBLAS_INLINE
03906 const_iterator (const self_type &mvb, const const_subiterator2_type &it2):
03907 container_const_reference<self_type> (mvb), it2_ (it2) {}
03908 #endif
03909
03910 private:
03911
03912 BOOST_UBLAS_INLINE
03913 value_type dereference (dense_random_access_iterator_tag) const {
03914 const self_type &mvb = (*this) ();
03915 #ifdef BOOST_UBLAS_USE_INDEXING
03916 return mvb (index ());
03917 #elif BOOST_UBLAS_USE_ITERATING
03918 difference_type size = BOOST_UBLAS_SAME (mvb.expression2 ().size1 (), mvb.expression1 ().size ());
03919 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
03920 return functor_type::apply (size, e1_begin_, it2_.begin ());
03921 #else
03922 return functor_type::apply (size, mvb.expression1 ().begin (), it2_.begin ());
03923 #endif
03924 #else
03925 difference_type size = BOOST_UBLAS_SAME (mvb.expression2 ().size1 (), mvb.expression1 ().size ());
03926 if (size >= BOOST_UBLAS_ITERATOR_THRESHOLD)
03927 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
03928 return functor_type::apply (size, e1_begin_, it2_.begin ());
03929 #else
03930 return functor_type::apply (size, mvb.expression1 ().begin (), it2_.begin ());
03931 #endif
03932 else
03933 return mvb (index ());
03934 #endif
03935 }
03936
03937
03938 BOOST_UBLAS_INLINE
03939 value_type dereference (packed_random_access_iterator_tag) const {
03940 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
03941 return functor_type::apply (e1_begin_, e1_end_, it2_.begin (), it2_.end ());
03942 #else
03943 const self_type &mvb = (*this) ();
03944 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
03945 return functor_type::apply (mvb.expression1 ().begin (), mvb.expression1 ().end (),
03946 it2_.begin (), it2_.end ());
03947 #else
03948 return functor_type::apply (mvb.expression1 ().begin (), mvb.expression1 ().end (),
03949 boost::numeric::ublas::begin (it2_, iterator2_tag ()),
03950 boost::numeric::ublas::end (it2_, iterator2_tag ()));
03951 #endif
03952 #endif
03953 }
03954
03955
03956 BOOST_UBLAS_INLINE
03957 value_type dereference (sparse_bidirectional_iterator_tag) const {
03958 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
03959 return functor_type::apply (e1_begin_, e1_end_, it2_.begin (), it2_.end (), sparse_bidirectional_iterator_tag ());
03960 #else
03961 const self_type &mvb = (*this) ();
03962 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
03963 return functor_type::apply (mvb.expression1 ().begin (), mvb.expression1 ().end (),
03964 it2_.begin (), it2_.end (), sparse_bidirectional_iterator_tag ());
03965 #else
03966 return functor_type::apply (mvb.expression1 ().begin (), mvb.expression1 ().end (),
03967 boost::numeric::ublas::begin (it2_, iterator2_tag ()),
03968 boost::numeric::ublas::end (it2_, iterator2_tag ()), sparse_bidirectional_iterator_tag ());
03969 #endif
03970 #endif
03971 }
03972
03973 public:
03974
03975 BOOST_UBLAS_INLINE
03976 const_iterator &operator ++ () {
03977 ++ it2_;
03978 return *this;
03979 }
03980 BOOST_UBLAS_INLINE
03981 const_iterator &operator -- () {
03982 -- it2_;
03983 return *this;
03984 }
03985 BOOST_UBLAS_INLINE
03986 const_iterator &operator += (difference_type n) {
03987 it2_ += n;
03988 return *this;
03989 }
03990 BOOST_UBLAS_INLINE
03991 const_iterator &operator -= (difference_type n) {
03992 it2_ -= n;
03993 return *this;
03994 }
03995 BOOST_UBLAS_INLINE
03996 difference_type operator - (const const_iterator &it) const {
03997 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
03998 return it2_ - it.it2_;
03999 }
04000
04001
04002 BOOST_UBLAS_INLINE
04003 const_reference operator * () const {
04004 return dereference (iterator_category ());
04005 }
04006 BOOST_UBLAS_INLINE
04007 const_reference operator [] (difference_type n) const {
04008 return *(*this + n);
04009 }
04010
04011
04012 BOOST_UBLAS_INLINE
04013 size_type index () const {
04014 return it2_.index2 ();
04015 }
04016
04017
04018 BOOST_UBLAS_INLINE
04019 const_iterator &operator = (const const_iterator &it) {
04020 container_const_reference<self_type>::assign (&it ());
04021 it2_ = it.it2_;
04022 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
04023 e1_begin_ = it.e1_begin_;
04024 e1_end_ = it.e1_end_;
04025 #endif
04026 return *this;
04027 }
04028
04029
04030 BOOST_UBLAS_INLINE
04031 bool operator == (const const_iterator &it) const {
04032 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
04033 return it2_ == it.it2_;
04034 }
04035 BOOST_UBLAS_INLINE
04036 bool operator < (const const_iterator &it) const {
04037 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
04038 return it2_ < it.it2_;
04039 }
04040
04041 private:
04042 const_subiterator2_type it2_;
04043 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
04044
04045 const_subiterator1_type e1_begin_;
04046 const_subiterator1_type e1_end_;
04047 #endif
04048 };
04049 #endif
04050
04051 BOOST_UBLAS_INLINE
04052 const_iterator begin () const {
04053 return find (0);
04054 }
04055 BOOST_UBLAS_INLINE
04056 const_iterator end () const {
04057 return find (size ());
04058 }
04059
04060
04061 typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
04062
04063 BOOST_UBLAS_INLINE
04064 const_reverse_iterator rbegin () const {
04065 return const_reverse_iterator (end ());
04066 }
04067 BOOST_UBLAS_INLINE
04068 const_reverse_iterator rend () const {
04069 return const_reverse_iterator (begin ());
04070 }
04071
04072 private:
04073 expression1_closure_type e1_;
04074 expression2_closure_type e2_;
04075 };
04076
04077 template<class T1, class E1, class T2, class E2>
04078 struct matrix_vector_binary2_traits {
04079 typedef unknown_storage_tag storage_category;
04080 typedef column_major_tag orientation_category;
04081 typedef typename promote_traits<T1, T2>::promote_type promote_type;
04082 typedef matrix_vector_binary2<E1, E2, matrix_vector_prod2<E1, E2, promote_type> > expression_type;
04083 #ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
04084 typedef expression_type result_type;
04085 #else
04086 typedef typename E2::vector_temporary_type result_type;
04087 #endif
04088 };
04089
04090 template<class E1, class E2>
04091 BOOST_UBLAS_INLINE
04092 typename matrix_vector_binary2_traits<typename E1::value_type, E1,
04093 typename E2::value_type, E2>::result_type
04094 prod (const vector_expression<E1> &e1,
04095 const matrix_expression<E2> &e2,
04096 unknown_storage_tag,
04097 column_major_tag) {
04098 typedef typename matrix_vector_binary2_traits<typename E1::value_type, E1,
04099 typename E2::value_type, E2>::expression_type expression_type;
04100 return expression_type (e1 (), e2 ());
04101 }
04102
04103
04104 template<class E1, class E2>
04105 BOOST_UBLAS_INLINE
04106 typename matrix_vector_binary2_traits<typename E1::value_type, E1,
04107 typename E2::value_type, E2>::result_type
04108 prod (const vector_expression<E1> &e1,
04109 const matrix_expression<E2> &e2) {
04110 BOOST_STATIC_ASSERT (E1::complexity == 0);
04111 typedef typename matrix_vector_binary2_traits<typename E1::value_type, E1,
04112 typename E2::value_type, E2>::storage_category storage_category;
04113 typedef typename matrix_vector_binary2_traits<typename E1::value_type, E1,
04114 typename E2::value_type, E2>::orientation_category orientation_category;
04115 return prod (e1, e2, storage_category (), orientation_category ());
04116 }
04117
04118 template<class E1, class E2>
04119 BOOST_UBLAS_INLINE
04120 typename matrix_vector_binary2_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
04121 typename type_traits<typename E2::value_type>::precision_type, E2>::result_type
04122 prec_prod (const vector_expression<E1> &e1,
04123 const matrix_expression<E2> &e2,
04124 unknown_storage_tag,
04125 column_major_tag) {
04126 typedef typename matrix_vector_binary2_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
04127 typename type_traits<typename E2::value_type>::precision_type, E2>::expression_type expression_type;
04128 return expression_type (e1 (), e2 ());
04129 }
04130
04131
04132 template<class E1, class E2>
04133 BOOST_UBLAS_INLINE
04134 typename matrix_vector_binary2_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
04135 typename type_traits<typename E2::value_type>::precision_type, E2>::result_type
04136 prec_prod (const vector_expression<E1> &e1,
04137 const matrix_expression<E2> &e2) {
04138 BOOST_STATIC_ASSERT (E1::complexity == 0);
04139 typedef typename matrix_vector_binary2_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
04140 typename type_traits<typename E2::value_type>::precision_type, E2>::storage_category storage_category;
04141 typedef typename matrix_vector_binary2_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
04142 typename type_traits<typename E2::value_type>::precision_type, E2>::orientation_category orientation_category;
04143 return prec_prod (e1, e2, storage_category (), orientation_category ());
04144 }
04145
04146 template<class V, class E1, class E2>
04147 BOOST_UBLAS_INLINE
04148 V &
04149 prod (const vector_expression<E1> &e1,
04150 const matrix_expression<E2> &e2,
04151 V &v) {
04152 return v.assign (prod (e1, e2));
04153 }
04154
04155 template<class V, class E1, class E2>
04156 BOOST_UBLAS_INLINE
04157 V &
04158 prec_prod (const vector_expression<E1> &e1,
04159 const matrix_expression<E2> &e2,
04160 V &v) {
04161 return v.assign (prec_prod (e1, e2));
04162 }
04163
04164 template<class V, class E1, class E2>
04165 BOOST_UBLAS_INLINE
04166 V
04167 prod (const vector_expression<E1> &e1,
04168 const matrix_expression<E2> &e2) {
04169 return V (prod (e1, e2));
04170 }
04171
04172 template<class V, class E1, class E2>
04173 BOOST_UBLAS_INLINE
04174 V
04175 prec_prod (const vector_expression<E1> &e1,
04176 const matrix_expression<E2> &e2) {
04177 return V (prec_prod (e1, e2));
04178 }
04179
04180 template<class E1, class E2, class F>
04181 class matrix_matrix_binary:
04182 public matrix_expression<matrix_matrix_binary<E1, E2, F> > {
04183
04184 public:
04185 typedef E1 expression1_type;
04186 typedef E2 expression2_type;
04187 private:
04188 typedef F functor_type;
04189 public:
04190 typedef typename E1::const_closure_type expression1_closure_type;
04191 typedef typename E2::const_closure_type expression2_closure_type;
04192 private:
04193 typedef matrix_matrix_binary<E1, E2, F> self_type;
04194 public:
04195 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
04196 using matrix_expression<self_type>::operator ();
04197 #endif
04198 static const unsigned complexity = 1;
04199 typedef typename promote_traits<typename E1::size_type, typename E2::size_type>::promote_type size_type;
04200 typedef typename promote_traits<typename E1::difference_type, typename E2::difference_type>::promote_type difference_type;
04201 typedef typename F::result_type value_type;
04202 typedef value_type const_reference;
04203 typedef const_reference reference;
04204 typedef const self_type const_closure_type;
04205 typedef const_closure_type closure_type;
04206 typedef unknown_orientation_tag orientation_category;
04207 typedef unknown_storage_tag storage_category;
04208
04209
04210 BOOST_UBLAS_INLINE
04211 matrix_matrix_binary (const expression1_type &e1, const expression2_type &e2):
04212 e1_ (e1), e2_ (e2) {}
04213
04214
04215 BOOST_UBLAS_INLINE
04216 size_type size1 () const {
04217 return e1_.size1 ();
04218 }
04219 BOOST_UBLAS_INLINE
04220 size_type size2 () const {
04221 return e2_.size2 ();
04222 }
04223
04224 public:
04225
04226 BOOST_UBLAS_INLINE
04227 const expression1_closure_type &expression1 () const {
04228 return e1_;
04229 }
04230 BOOST_UBLAS_INLINE
04231 const expression2_closure_type &expression2 () const {
04232 return e2_;
04233 }
04234
04235 public:
04236
04237 BOOST_UBLAS_INLINE
04238 const_reference operator () (size_type i, size_type j) const {
04239 return functor_type::apply (e1_, e2_, i, j);
04240 }
04241
04242
04243 BOOST_UBLAS_INLINE
04244 bool same_closure (const matrix_matrix_binary &mmb) const {
04245 return (*this).expression1 ().same_closure (mmb.expression1 ()) &&
04246 (*this).expression2 ().same_closure (mmb.expression2 ());
04247 }
04248
04249
04250 private:
04251 typedef typename E1::const_iterator1 const_iterator11_type;
04252 typedef typename E1::const_iterator2 const_iterator12_type;
04253 typedef typename E2::const_iterator1 const_iterator21_type;
04254 typedef typename E2::const_iterator2 const_iterator22_type;
04255 typedef const value_type *const_pointer;
04256
04257 public:
04258 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
04259 typedef typename iterator_restrict_traits<typename const_iterator11_type::iterator_category,
04260 typename const_iterator22_type::iterator_category>::iterator_category iterator_category;
04261 typedef indexed_const_iterator1<const_closure_type, iterator_category> const_iterator1;
04262 typedef const_iterator1 iterator1;
04263 typedef indexed_const_iterator2<const_closure_type, iterator_category> const_iterator2;
04264 typedef const_iterator2 iterator2;
04265 #else
04266 class const_iterator1;
04267 typedef const_iterator1 iterator1;
04268 class const_iterator2;
04269 typedef const_iterator2 iterator2;
04270 #endif
04271 typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
04272 typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
04273
04274
04275 BOOST_UBLAS_INLINE
04276 const_iterator1 find1 (int , size_type i, size_type j) const {
04277
04278
04279 const_iterator11_type it11 (e1_.find1 (0, i, 0));
04280 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
04281 return const_iterator1 (*this, it11.index1 (), j);
04282 #else
04283
04284
04285 const_iterator22_type it22 (e2_.find2 (0, 0, j));
04286 return const_iterator1 (*this, it11, it22);
04287 #endif
04288 }
04289 BOOST_UBLAS_INLINE
04290 const_iterator2 find2 (int , size_type i, size_type j) const {
04291
04292
04293 const_iterator22_type it22 (e2_.find2 (0, 0, j));
04294 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
04295 return const_iterator2 (*this, i, it22.index2 ());
04296 #else
04297
04298
04299 const_iterator11_type it11 (e1_.find1 (0, i, 0));
04300 return const_iterator2 (*this, it11, it22);
04301 #endif
04302 }
04303
04304
04305 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
04306 class const_iterator1:
04307 public container_const_reference<matrix_matrix_binary>,
04308 public iterator_base_traits<typename iterator_restrict_traits<typename E1::const_iterator1::iterator_category,
04309 typename E2::const_iterator2::iterator_category>::iterator_category>::template
04310 iterator_base<const_iterator1, value_type>::type {
04311 public:
04312 typedef typename iterator_restrict_traits<typename E1::const_iterator1::iterator_category,
04313 typename E2::const_iterator2::iterator_category>::iterator_category iterator_category;
04314 typedef typename matrix_matrix_binary::difference_type difference_type;
04315 typedef typename matrix_matrix_binary::value_type value_type;
04316 typedef typename matrix_matrix_binary::const_reference reference;
04317 typedef typename matrix_matrix_binary::const_pointer pointer;
04318
04319 typedef const_iterator2 dual_iterator_type;
04320 typedef const_reverse_iterator2 dual_reverse_iterator_type;
04321
04322
04323 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
04324 BOOST_UBLAS_INLINE
04325 const_iterator1 ():
04326 container_const_reference<self_type> (), it1_ (), it2_ (), it2_begin_ (), it2_end_ () {}
04327 BOOST_UBLAS_INLINE
04328 const_iterator1 (const self_type &mmb, const const_iterator11_type &it1, const const_iterator22_type &it2):
04329 container_const_reference<self_type> (mmb), it1_ (it1), it2_ (it2), it2_begin_ (it2.begin ()), it2_end_ (it2.end ()) {}
04330 #else
04331 BOOST_UBLAS_INLINE
04332 const_iterator1 ():
04333 container_const_reference<self_type> (), it1_ (), it2_ () {}
04334 BOOST_UBLAS_INLINE
04335 const_iterator1 (const self_type &mmb, const const_iterator11_type &it1, const const_iterator22_type &it2):
04336 container_const_reference<self_type> (mmb), it1_ (it1), it2_ (it2) {}
04337 #endif
04338
04339 private:
04340
04341 BOOST_UBLAS_INLINE
04342 value_type dereference (dense_random_access_iterator_tag) const {
04343 const self_type &mmb = (*this) ();
04344 #ifdef BOOST_UBLAS_USE_INDEXING
04345 return mmb (index1 (), index2 ());
04346 #elif BOOST_UBLAS_USE_ITERATING
04347 difference_type size = BOOST_UBLAS_SAME (mmb.expression1 ().size2 (), mmb.expression2 ().size1 ());
04348 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
04349 return functor_type::apply (size, it1_.begin (), it2_begin_);
04350 #else
04351 return functor_type::apply (size, it1_.begin (), it2_.begin ());
04352 #endif
04353 #else
04354 difference_type size = BOOST_UBLAS_SAME (mmb.expression1 ().size2 (), mmb.expression2 ().size1 ());
04355 if (size >= BOOST_UBLAS_ITERATOR_THRESHOLD)
04356 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
04357 return functor_type::apply (size, it1_.begin (), it2_begin_);
04358 #else
04359 return functor_type::apply (size, it1_.begin (), it2_.begin ());
04360 #endif
04361 else
04362 return mmb (index1 (), index2 ());
04363 #endif
04364 }
04365
04366
04367 BOOST_UBLAS_INLINE
04368 value_type dereference (packed_random_access_iterator_tag) const {
04369 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
04370 return functor_type::apply (it1_.begin (), it1_.end (),
04371 it2_begin_, it2_end_, packed_random_access_iterator_tag ());
04372 #else
04373 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
04374 return functor_type::apply (it1_.begin (), it1_.end (),
04375 it2_.begin (), it2_.end (), packed_random_access_iterator_tag ());
04376 #else
04377 return functor_type::apply (boost::numeric::ublas::begin (it1_, iterator1_tag ()),
04378 boost::numeric::ublas::end (it1_, iterator1_tag ()),
04379 boost::numeric::ublas::begin (it2_, iterator2_tag ()),
04380 boost::numeric::ublas::end (it2_, iterator2_tag ()), packed_random_access_iterator_tag ());
04381 #endif
04382 #endif
04383 }
04384
04385
04386 BOOST_UBLAS_INLINE
04387 value_type dereference (sparse_bidirectional_iterator_tag) const {
04388 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
04389 return functor_type::apply (it1_.begin (), it1_.end (),
04390 it2_begin_, it2_end_, sparse_bidirectional_iterator_tag ());
04391 #else
04392 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
04393 return functor_type::apply (it1_.begin (), it1_.end (),
04394 it2_.begin (), it2_.end (), sparse_bidirectional_iterator_tag ());
04395 #else
04396 return functor_type::apply (boost::numeric::ublas::begin (it1_, iterator1_tag ()),
04397 boost::numeric::ublas::end (it1_, iterator1_tag ()),
04398 boost::numeric::ublas::begin (it2_, iterator2_tag ()),
04399 boost::numeric::ublas::end (it2_, iterator2_tag ()), sparse_bidirectional_iterator_tag ());
04400 #endif
04401 #endif
04402 }
04403
04404 public:
04405
04406 BOOST_UBLAS_INLINE
04407 const_iterator1 &operator ++ () {
04408 ++ it1_;
04409 return *this;
04410 }
04411 BOOST_UBLAS_INLINE
04412 const_iterator1 &operator -- () {
04413 -- it1_;
04414 return *this;
04415 }
04416 BOOST_UBLAS_INLINE
04417 const_iterator1 &operator += (difference_type n) {
04418 it1_ += n;
04419 return *this;
04420 }
04421 BOOST_UBLAS_INLINE
04422 const_iterator1 &operator -= (difference_type n) {
04423 it1_ -= n;
04424 return *this;
04425 }
04426 BOOST_UBLAS_INLINE
04427 difference_type operator - (const const_iterator1 &it) const {
04428 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
04429 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
04430 return it1_ - it.it1_;
04431 }
04432
04433
04434 BOOST_UBLAS_INLINE
04435 const_reference operator * () const {
04436 return dereference (iterator_category ());
04437 }
04438 BOOST_UBLAS_INLINE
04439 const_reference operator [] (difference_type n) const {
04440 return *(*this + n);
04441 }
04442
04443 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
04444 BOOST_UBLAS_INLINE
04445 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
04446 typename self_type::
04447 #endif
04448 const_iterator2 begin () const {
04449 return (*this) ().find2 (1, index1 (), 0);
04450 }
04451 BOOST_UBLAS_INLINE
04452 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
04453 typename self_type::
04454 #endif
04455 const_iterator2 end () const {
04456 return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
04457 }
04458 BOOST_UBLAS_INLINE
04459 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
04460 typename self_type::
04461 #endif
04462 const_reverse_iterator2 rbegin () const {
04463 return const_reverse_iterator2 (end ());
04464 }
04465 BOOST_UBLAS_INLINE
04466 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
04467 typename self_type::
04468 #endif
04469 const_reverse_iterator2 rend () const {
04470 return const_reverse_iterator2 (begin ());
04471 }
04472 #endif
04473
04474
04475 BOOST_UBLAS_INLINE
04476 size_type index1 () const {
04477 return it1_.index1 ();
04478 }
04479 BOOST_UBLAS_INLINE
04480 size_type index2 () const {
04481 return it2_.index2 ();
04482 }
04483
04484
04485 BOOST_UBLAS_INLINE
04486 const_iterator1 &operator = (const const_iterator1 &it) {
04487 container_const_reference<self_type>::assign (&it ());
04488 it1_ = it.it1_;
04489 it2_ = it.it2_;
04490 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
04491 it2_begin_ = it.it2_begin_;
04492 it2_end_ = it.it2_end_;
04493 #endif
04494 return *this;
04495 }
04496
04497
04498 BOOST_UBLAS_INLINE
04499 bool operator == (const const_iterator1 &it) const {
04500 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
04501 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
04502 return it1_ == it.it1_;
04503 }
04504 BOOST_UBLAS_INLINE
04505 bool operator < (const const_iterator1 &it) const {
04506 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
04507 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
04508 return it1_ < it.it1_;
04509 }
04510
04511 private:
04512 const_iterator11_type it1_;
04513
04514 const_iterator22_type it2_;
04515 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
04516 const_iterator21_type it2_begin_;
04517 const_iterator21_type it2_end_;
04518 #endif
04519 };
04520 #endif
04521
04522 BOOST_UBLAS_INLINE
04523 const_iterator1 begin1 () const {
04524 return find1 (0, 0, 0);
04525 }
04526 BOOST_UBLAS_INLINE
04527 const_iterator1 end1 () const {
04528 return find1 (0, size1 (), 0);
04529 }
04530
04531 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
04532 class const_iterator2:
04533 public container_const_reference<matrix_matrix_binary>,
04534 public iterator_base_traits<typename iterator_restrict_traits<typename E1::const_iterator1::iterator_category,
04535 typename E2::const_iterator2::iterator_category>::iterator_category>::template
04536 iterator_base<const_iterator2, value_type>::type {
04537 public:
04538 typedef typename iterator_restrict_traits<typename E1::const_iterator1::iterator_category,
04539 typename E2::const_iterator2::iterator_category>::iterator_category iterator_category;
04540 typedef typename matrix_matrix_binary::difference_type difference_type;
04541 typedef typename matrix_matrix_binary::value_type value_type;
04542 typedef typename matrix_matrix_binary::const_reference reference;
04543 typedef typename matrix_matrix_binary::const_pointer pointer;
04544
04545 typedef const_iterator1 dual_iterator_type;
04546 typedef const_reverse_iterator1 dual_reverse_iterator_type;
04547
04548
04549 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
04550 BOOST_UBLAS_INLINE
04551 const_iterator2 ():
04552 container_const_reference<self_type> (), it1_ (), it2_ (), it1_begin_ (), it1_end_ () {}
04553 BOOST_UBLAS_INLINE
04554 const_iterator2 (const self_type &mmb, const const_iterator11_type &it1, const const_iterator22_type &it2):
04555 container_const_reference<self_type> (mmb), it1_ (it1), it2_ (it2), it1_begin_ (it1.begin ()), it1_end_ (it1.end ()) {}
04556 #else
04557 BOOST_UBLAS_INLINE
04558 const_iterator2 ():
04559 container_const_reference<self_type> (), it1_ (), it2_ () {}
04560 BOOST_UBLAS_INLINE
04561 const_iterator2 (const self_type &mmb, const const_iterator11_type &it1, const const_iterator22_type &it2):
04562 container_const_reference<self_type> (mmb), it1_ (it1), it2_ (it2) {}
04563 #endif
04564
04565 private:
04566
04567 BOOST_UBLAS_INLINE
04568 value_type dereference (dense_random_access_iterator_tag) const {
04569 const self_type &mmb = (*this) ();
04570 #ifdef BOOST_UBLAS_USE_INDEXING
04571 return mmb (index1 (), index2 ());
04572 #elif BOOST_UBLAS_USE_ITERATING
04573 difference_type size = BOOST_UBLAS_SAME (mmb.expression1 ().size2 (), mmb.expression2 ().size1 ());
04574 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
04575 return functor_type::apply (size, it1_begin_, it2_.begin ());
04576 #else
04577 return functor_type::apply (size, it1_.begin (), it2_.begin ());
04578 #endif
04579 #else
04580 difference_type size = BOOST_UBLAS_SAME (mmb.expression1 ().size2 (), mmb.expression2 ().size1 ());
04581 if (size >= BOOST_UBLAS_ITERATOR_THRESHOLD)
04582 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
04583 return functor_type::apply (size, it1_begin_, it2_.begin ());
04584 #else
04585 return functor_type::apply (size, it1_.begin (), it2_.begin ());
04586 #endif
04587 else
04588 return mmb (index1 (), index2 ());
04589 #endif
04590 }
04591
04592
04593 BOOST_UBLAS_INLINE
04594 value_type dereference (packed_random_access_iterator_tag) const {
04595 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
04596 return functor_type::apply (it1_begin_, it1_end_,
04597 it2_.begin (), it2_.end (), packed_random_access_iterator_tag ());
04598 #else
04599 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
04600 return functor_type::apply (it1_.begin (), it1_.end (),
04601 it2_.begin (), it2_.end (), packed_random_access_iterator_tag ());
04602 #else
04603 return functor_type::apply (boost::numeric::ublas::begin (it1_, iterator1_tag ()),
04604 boost::numeric::ublas::end (it1_, iterator1_tag ()),
04605 boost::numeric::ublas::begin (it2_, iterator2_tag ()),
04606 boost::numeric::ublas::end (it2_, iterator2_tag ()), packed_random_access_iterator_tag ());
04607 #endif
04608 #endif
04609 }
04610
04611
04612 BOOST_UBLAS_INLINE
04613 value_type dereference (sparse_bidirectional_iterator_tag) const {
04614 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
04615 return functor_type::apply (it1_begin_, it1_end_,
04616 it2_.begin (), it2_.end (), sparse_bidirectional_iterator_tag ());
04617 #else
04618 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
04619 return functor_type::apply (it1_.begin (), it1_.end (),
04620 it2_.begin (), it2_.end (), sparse_bidirectional_iterator_tag ());
04621 #else
04622 return functor_type::apply (boost::numeric::ublas::begin (it1_, iterator1_tag ()),
04623 boost::numeric::ublas::end (it1_, iterator1_tag ()),
04624 boost::numeric::ublas::begin (it2_, iterator2_tag ()),
04625 boost::numeric::ublas::end (it2_, iterator2_tag ()), sparse_bidirectional_iterator_tag ());
04626 #endif
04627 #endif
04628 }
04629
04630 public:
04631
04632 BOOST_UBLAS_INLINE
04633 const_iterator2 &operator ++ () {
04634 ++ it2_;
04635 return *this;
04636 }
04637 BOOST_UBLAS_INLINE
04638 const_iterator2 &operator -- () {
04639 -- it2_;
04640 return *this;
04641 }
04642 BOOST_UBLAS_INLINE
04643 const_iterator2 &operator += (difference_type n) {
04644 it2_ += n;
04645 return *this;
04646 }
04647 BOOST_UBLAS_INLINE
04648 const_iterator2 &operator -= (difference_type n) {
04649 it2_ -= n;
04650 return *this;
04651 }
04652 BOOST_UBLAS_INLINE
04653 difference_type operator - (const const_iterator2 &it) const {
04654 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
04655 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
04656 return it2_ - it.it2_;
04657 }
04658
04659
04660 BOOST_UBLAS_INLINE
04661 const_reference operator * () const {
04662 return dereference (iterator_category ());
04663 }
04664 BOOST_UBLAS_INLINE
04665 const_reference operator [] (difference_type n) const {
04666 return *(*this + n);
04667 }
04668
04669 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
04670 BOOST_UBLAS_INLINE
04671 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
04672 typename self_type::
04673 #endif
04674 const_iterator1 begin () const {
04675 return (*this) ().find1 (1, 0, index2 ());
04676 }
04677 BOOST_UBLAS_INLINE
04678 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
04679 typename self_type::
04680 #endif
04681 const_iterator1 end () const {
04682 return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
04683 }
04684 BOOST_UBLAS_INLINE
04685 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
04686 typename self_type::
04687 #endif
04688 const_reverse_iterator1 rbegin () const {
04689 return const_reverse_iterator1 (end ());
04690 }
04691 BOOST_UBLAS_INLINE
04692 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
04693 typename self_type::
04694 #endif
04695 const_reverse_iterator1 rend () const {
04696 return const_reverse_iterator1 (begin ());
04697 }
04698 #endif
04699
04700
04701 BOOST_UBLAS_INLINE
04702 size_type index1 () const {
04703 return it1_.index1 ();
04704 }
04705 BOOST_UBLAS_INLINE
04706 size_type index2 () const {
04707 return it2_.index2 ();
04708 }
04709
04710
04711 BOOST_UBLAS_INLINE
04712 const_iterator2 &operator = (const const_iterator2 &it) {
04713 container_const_reference<self_type>::assign (&it ());
04714 it1_ = it.it1_;
04715 it2_ = it.it2_;
04716 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
04717 it1_begin_ = it.it1_begin_;
04718 it1_end_ = it.it1_end_;
04719 #endif
04720 return *this;
04721 }
04722
04723
04724 BOOST_UBLAS_INLINE
04725 bool operator == (const const_iterator2 &it) const {
04726 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
04727 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
04728 return it2_ == it.it2_;
04729 }
04730 BOOST_UBLAS_INLINE
04731 bool operator < (const const_iterator2 &it) const {
04732 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
04733 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
04734 return it2_ < it.it2_;
04735 }
04736
04737 private:
04738
04739 const_iterator11_type it1_;
04740 const_iterator22_type it2_;
04741 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
04742 const_iterator12_type it1_begin_;
04743 const_iterator12_type it1_end_;
04744 #endif
04745 };
04746 #endif
04747
04748 BOOST_UBLAS_INLINE
04749 const_iterator2 begin2 () const {
04750 return find2 (0, 0, 0);
04751 }
04752 BOOST_UBLAS_INLINE
04753 const_iterator2 end2 () const {
04754 return find2 (0, 0, size2 ());
04755 }
04756
04757
04758
04759 BOOST_UBLAS_INLINE
04760 const_reverse_iterator1 rbegin1 () const {
04761 return const_reverse_iterator1 (end1 ());
04762 }
04763 BOOST_UBLAS_INLINE
04764 const_reverse_iterator1 rend1 () const {
04765 return const_reverse_iterator1 (begin1 ());
04766 }
04767
04768 BOOST_UBLAS_INLINE
04769 const_reverse_iterator2 rbegin2 () const {
04770 return const_reverse_iterator2 (end2 ());
04771 }
04772 BOOST_UBLAS_INLINE
04773 const_reverse_iterator2 rend2 () const {
04774 return const_reverse_iterator2 (begin2 ());
04775 }
04776
04777 private:
04778 expression1_closure_type e1_;
04779 expression2_closure_type e2_;
04780 };
04781
04782 template<class T1, class E1, class T2, class E2>
04783 struct matrix_matrix_binary_traits {
04784 typedef unknown_storage_tag storage_category;
04785 typedef unknown_orientation_tag orientation_category;
04786 typedef typename promote_traits<T1, T2>::promote_type promote_type;
04787 typedef matrix_matrix_binary<E1, E2, matrix_matrix_prod<E1, E2, promote_type> > expression_type;
04788 #ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
04789 typedef expression_type result_type;
04790 #else
04791 typedef typename E1::matrix_temporary_type result_type;
04792 #endif
04793 };
04794
04795 template<class E1, class E2>
04796 BOOST_UBLAS_INLINE
04797 typename matrix_matrix_binary_traits<typename E1::value_type, E1,
04798 typename E2::value_type, E2>::result_type
04799 prod (const matrix_expression<E1> &e1,
04800 const matrix_expression<E2> &e2,
04801 unknown_storage_tag,
04802 unknown_orientation_tag) {
04803 typedef typename matrix_matrix_binary_traits<typename E1::value_type, E1,
04804 typename E2::value_type, E2>::expression_type expression_type;
04805 return expression_type (e1 (), e2 ());
04806 }
04807
04808
04809 template<class E1, class E2>
04810 BOOST_UBLAS_INLINE
04811 typename matrix_matrix_binary_traits<typename E1::value_type, E1,
04812 typename E2::value_type, E2>::result_type
04813 prod (const matrix_expression<E1> &e1,
04814 const matrix_expression<E2> &e2) {
04815 BOOST_STATIC_ASSERT (E1::complexity == 0 && E2::complexity == 0);
04816 typedef typename matrix_matrix_binary_traits<typename E1::value_type, E1,
04817 typename E2::value_type, E2>::storage_category storage_category;
04818 typedef typename matrix_matrix_binary_traits<typename E1::value_type, E1,
04819 typename E2::value_type, E2>::orientation_category orientation_category;
04820 return prod (e1, e2, storage_category (), orientation_category ());
04821 }
04822
04823 template<class E1, class E2>
04824 BOOST_UBLAS_INLINE
04825 typename matrix_matrix_binary_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
04826 typename type_traits<typename E2::value_type>::precision_type, E2>::result_type
04827 prec_prod (const matrix_expression<E1> &e1,
04828 const matrix_expression<E2> &e2,
04829 unknown_storage_tag,
04830 unknown_orientation_tag) {
04831 typedef typename matrix_matrix_binary_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
04832 typename type_traits<typename E2::value_type>::precision_type, E2>::expression_type expression_type;
04833 return expression_type (e1 (), e2 ());
04834 }
04835
04836
04837 template<class E1, class E2>
04838 BOOST_UBLAS_INLINE
04839 typename matrix_matrix_binary_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
04840 typename type_traits<typename E2::value_type>::precision_type, E2>::result_type
04841 prec_prod (const matrix_expression<E1> &e1,
04842 const matrix_expression<E2> &e2) {
04843 BOOST_STATIC_ASSERT (E1::complexity == 0 && E2::complexity == 0);
04844 typedef typename matrix_matrix_binary_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
04845 typename type_traits<typename E2::value_type>::precision_type, E2>::storage_category storage_category;
04846 typedef typename matrix_matrix_binary_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
04847 typename type_traits<typename E2::value_type>::precision_type, E2>::orientation_category orientation_category;
04848 return prec_prod (e1, e2, storage_category (), orientation_category ());
04849 }
04850
04851 template<class M, class E1, class E2>
04852 BOOST_UBLAS_INLINE
04853 M &
04854 prod (const matrix_expression<E1> &e1,
04855 const matrix_expression<E2> &e2,
04856 M &m) {
04857 return m.assign (prod (e1, e2));
04858 }
04859
04860 template<class M, class E1, class E2>
04861 BOOST_UBLAS_INLINE
04862 M &
04863 prec_prod (const matrix_expression<E1> &e1,
04864 const matrix_expression<E2> &e2,
04865 M &m) {
04866 return m.assign (prec_prod (e1, e2));
04867 }
04868
04869 template<class M, class E1, class E2>
04870 BOOST_UBLAS_INLINE
04871 M
04872 prod (const matrix_expression<E1> &e1,
04873 const matrix_expression<E2> &e2) {
04874 return M (prod (e1, e2));
04875 }
04876
04877 template<class M, class E1, class E2>
04878 BOOST_UBLAS_INLINE
04879 M
04880 prec_prod (const matrix_expression<E1> &e1,
04881 const matrix_expression<E2> &e2) {
04882 return M (prec_prod (e1, e2));
04883 }
04884
04885 template<class E, class F>
04886 class matrix_scalar_unary:
04887 public scalar_expression<matrix_scalar_unary<E, F> > {
04888 public:
04889 typedef E expression_type;
04890 typedef F functor_type;
04891 typedef typename F::result_type value_type;
04892 typedef typename E::const_closure_type expression_closure_type;
04893
04894
04895 BOOST_UBLAS_INLINE
04896 explicit matrix_scalar_unary (const expression_type &e):
04897 e_ (e) {}
04898
04899 private:
04900
04901 BOOST_UBLAS_INLINE
04902 const expression_closure_type &expression () const {
04903 return e_;
04904 }
04905
04906 public:
04907 BOOST_UBLAS_INLINE
04908 operator value_type () const {
04909 return functor_type::apply (e_);
04910 }
04911
04912 private:
04913 expression_closure_type e_;
04914 };
04915
04916 template<class E, class F>
04917 struct matrix_scalar_unary_traits {
04918 typedef matrix_scalar_unary<E, F> expression_type;
04919 #ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
04920 typedef expression_type result_type;
04921 #else
04922 typedef typename F::result_type result_type;
04923 #endif
04924 };
04925
04926 template<class E>
04927 BOOST_UBLAS_INLINE
04928 typename matrix_scalar_unary_traits<E, matrix_norm_1<E> >::result_type
04929 norm_1 (const matrix_expression<E> &e) {
04930 typedef typename matrix_scalar_unary_traits<E, matrix_norm_1<E> >::expression_type expression_type;
04931 return expression_type (e ());
04932 }
04933
04934 template<class E>
04935 BOOST_UBLAS_INLINE
04936 typename matrix_scalar_unary_traits<E, matrix_norm_frobenius<E> >::result_type
04937 norm_frobenius (const matrix_expression<E> &e) {
04938 typedef typename matrix_scalar_unary_traits<E, matrix_norm_frobenius<E> >::expression_type expression_type;
04939 return expression_type (e ());
04940 }
04941
04942 template<class E>
04943 BOOST_UBLAS_INLINE
04944 typename matrix_scalar_unary_traits<E, matrix_norm_inf<E> >::result_type
04945 norm_inf (const matrix_expression<E> &e) {
04946 typedef typename matrix_scalar_unary_traits<E, matrix_norm_inf<E> >::expression_type expression_type;
04947 return expression_type (e ());
04948 }
04949
04950 }}}
04951
04952 #endif