...one of the most highly
regarded and expertly designed C++ library projects in the
world.
— Herb Sutter and Andrei
Alexandrescu, C++
Coding Standards
00001 // 00002 // Copyright (c) 2000-2002 00003 // Joerg Walter, Mathias Koch 00004 // 00005 // Distributed under the Boost Software License, Version 1.0. (See 00006 // accompanying file LICENSE_1_0.txt or copy at 00007 // http://www.boost.org/LICENSE_1_0.txt) 00008 // 00009 // The authors gratefully acknowledge the support of 00010 // GeNeSys mbH & Co. KG in producing this work. 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 // Expression templates based on ideas of Todd Veldhuizen and Geoffrey Furnish 00019 // Iterators based on ideas of Jeremy Siek 00020 // 00021 // Classes that model the Matrix Expression concept 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 // Construction and destruction 00048 BOOST_UBLAS_INLINE 00049 explicit matrix_reference (referred_type &e): 00050 e_ (e) {} 00051 00052 // Accessors 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 // Expression accessors - const correct 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 // Element access 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 // Assignment 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 // Swapping 00147 BOOST_UBLAS_INLINE 00148 void swap (matrix_reference &m) { 00149 expression ().swap (m.expression ()); 00150 } 00151 00152 // Closure comparison 00153 BOOST_UBLAS_INLINE 00154 bool same_closure (const matrix_reference &mr) const { 00155 return &(*this).e_ == &mr.e_; 00156 } 00157 00158 // Iterator types 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 // Element lookup 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 // Iterators are the iterators of the referenced expression. 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 // Reverse iterators 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 // Construction and destruction 00299 BOOST_UBLAS_INLINE 00300 vector_matrix_binary (const expression1_type &e1, const expression2_type &e2): 00301 e1_ (e1), e2_ (e2) {} 00302 00303 // Accessors 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 // Expression accessors 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 // Element access 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 // Closure comparison 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 // Iterator types 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 // Element lookup 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/*zero*/()))) { 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/*zero*/()); 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/*zero*/()))) { 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/*zero*/()); 00397 #else 00398 return const_iterator2 (*this, it1, it2); 00399 #endif 00400 #endif 00401 } 00402 00403 // Iterators enhance the iterators of the referenced expressions 00404 // with the binary functor. 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 // Construction and destruction 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 // Arithmetic 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 // Dereference 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 // Indices 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 // Assignment 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 // Comparison 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 // Mutable due to assignment 00553 /* const */ 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 // Construction and destruction 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 // Arithmetic 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 // Dereference 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 // Indices 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 // Assignment 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 // Comparison 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 // Mutable due to assignment 00717 /* const */ 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 // Reverse iterators 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 // ISSUE matrix is arbitary temporary type 00768 typedef matrix<typename F::value_type> result_type; 00769 #endif 00770 }; 00771 00772 // (outer_prod (v1, v2)) [i] [j] = v1 [i] * v2 [j] 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 // Construction and destruction 00808 BOOST_UBLAS_INLINE 00809 explicit matrix_unary1 (const expression_type &e): 00810 e_ (e) {} 00811 00812 // Accessors 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 // Expression accessors 00824 BOOST_UBLAS_INLINE 00825 const expression_closure_type &expression () const { 00826 return e_; 00827 } 00828 00829 public: 00830 // Element access 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 // Closure comparison 00837 BOOST_UBLAS_INLINE 00838 bool same_closure (const matrix_unary1 &mu1) const { 00839 return (*this).expression ().same_closure (mu1.expression ()); 00840 } 00841 00842 // Iterator types 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 // Element lookup 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 // Iterators enhance the iterators of the referenced expression 00884 // with the unary functor. 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 // Construction and destruction 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 // Arithmetic 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 // Dereference 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 // Indices 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 // Assignment 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 // Comparison 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 // Construction and destruction 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 // Arithmetic 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 // Dereference 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 // Indices 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 // Assignment 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 // Comparison 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 // Reverse iterators 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 // (- m) [i] [j] = - m [i] [j] 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 // (conj m) [i] [j] = conj (m [i] [j]) 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 // (real m) [i] [j] = real (m [i] [j]) 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 // (imag m) [i] [j] = imag (m [i] [j]) 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 // Construction and destruction 01264 BOOST_UBLAS_INLINE 01265 // matrix_unary2 may be used as mutable expression - 01266 // this is the only non const expression constructor 01267 explicit matrix_unary2 (expression_type &e): 01268 e_ (e) {} 01269 01270 // Accessors 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 // Expression accessors 01282 BOOST_UBLAS_INLINE 01283 const expression_closure_type &expression () const { 01284 return e_; 01285 } 01286 01287 public: 01288 // Element access 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 // Closure comparison 01300 BOOST_UBLAS_INLINE 01301 bool same_closure (const matrix_unary2 &mu2) const { 01302 return (*this).expression ().same_closure (mu2.expression ()); 01303 } 01304 01305 // Iterator types 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 // Element lookup 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 // Iterators enhance the iterators of the referenced expression 01347 // with the unary functor. 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 // Construction and destruction 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 // Arithmetic 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 // Dereference 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 // Indices 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 // Assignment 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 // Comparison 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 // Construction and destruction 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 // Arithmetic 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 // Dereference 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 // Indices 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 // Assignment 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 // Comparison 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 // Reverse iterators 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 // (trans m) [i] [j] = m [j] [i] 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 // (herm m) [i] [j] = conj (m [j] [i]) 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 // Construction and destruction 01705 BOOST_UBLAS_INLINE 01706 matrix_binary (const E1 &e1, const E2 &e2): 01707 e1_ (e1), e2_ (e2) {} 01708 01709 // Accessors 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 // Expression accessors 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 // Element access 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 // Closure comparison 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 // Iterator types 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 // Element lookup 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 // Iterators enhance the iterators of the referenced expression 01806 // with the binary functor. 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 // Construction and destruction 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 // Dense specializations 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 // Packed specializations 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/*zero*/(); 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/*zero*/(); 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 // Sparse specializations 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/*zero*/(); 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/*zero*/(); 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 // Arithmetic 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 // Dereference 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 // Indices 02065 BOOST_UBLAS_INLINE 02066 size_type index1 () const { 02067 return i_; 02068 } 02069 BOOST_UBLAS_INLINE 02070 size_type index2 () const { 02071 // if (it1_ != it1_end_ && it2_ != it2_end_) 02072 // return BOOST_UBLAS_SAME (it1_.index2 (), it2_.index2 ()); 02073 // else 02074 return j_; 02075 } 02076 02077 // Assignment 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 // Comparison 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 // Construction and destruction 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 // Dense access specializations 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 // Packed specializations 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/*zero*/(); 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/*zero*/(); 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 // Sparse specializations 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/*zero*/(); 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/*zero*/(); 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 // Arithmetic 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 // Dereference 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 // Indices 02380 BOOST_UBLAS_INLINE 02381 size_type index1 () const { 02382 // if (it1_ != it1_end_ && it2_ != it2_end_) 02383 // return BOOST_UBLAS_SAME (it1_.index1 (), it2_.index1 ()); 02384 // else 02385 return i_; 02386 } 02387 BOOST_UBLAS_INLINE 02388 size_type index2 () const { 02389 return j_; 02390 } 02391 02392 // Assignment 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 // Comparison 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 // Reverse iterators 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 // (m1 + m2) [i] [j] = m1 [i] [j] + m2 [i] [j] 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 // (m1 - m2) [i] [j] = m1 [i] [j] - m2 [i] [j] 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 // (m1 * m2) [i] [j] = m1 [i] [j] * m2 [i] [j] 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 // (m1 / m2) [i] [j] = m1 [i] [j] / m2 [i] [j] 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 // Construction and destruction 02546 BOOST_UBLAS_INLINE 02547 matrix_binary_scalar1 (const expression1_type &e1, const expression2_type &e2): 02548 e1_ (e1), e2_ (e2) {} 02549 02550 // Accessors 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 // Element access 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 // Closure comparison 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 // Iterator types 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 // Element lookup 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 // Iterators enhance the iterators of the referenced expression 02617 // with the binary functor. 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 // Construction and destruction 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 // Arithmetic 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 // FIXME we shouldn't compare floats 02667 // BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ()); 02668 return it2_ - it.it2_; 02669 } 02670 02671 // Dereference 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 // Indices 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 // Assignment 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 // Comparison 02732 BOOST_UBLAS_INLINE 02733 bool operator == (const const_iterator1 &it) const { 02734 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); 02735 // FIXME we shouldn't compare floats 02736 // BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ()); 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 // FIXME we shouldn't compare floats 02743 // BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ()); 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 // Construction and destruction 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 // Arithmetic 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 // FIXME we shouldn't compare floats 02810 // BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ()); 02811 return it2_ - it.it2_; 02812 } 02813 02814 // Dereference 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 // Indices 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 // Assignment 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 // Comparison 02875 BOOST_UBLAS_INLINE 02876 bool operator == (const const_iterator2 &it) const { 02877 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); 02878 // FIXME we shouldn't compare floats 02879 // BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ()); 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 // FIXME we shouldn't compare floats 02886 // BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ()); 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 // Reverse iterators 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; // allow E1 to be builtin 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 // (t * m) [i] [j] = t * m [i] [j] 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 // Construction and destruction 02981 BOOST_UBLAS_INLINE 02982 matrix_binary_scalar2 (const expression1_type &e1, const expression2_type &e2): 02983 e1_ (e1), e2_ (e2) {} 02984 02985 // Accessors 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 // Element access 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 // Closure comparison 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 // Iterator types 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 // Element lookup 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 // Iterators enhance the iterators of the referenced expression 03052 // with the binary functor. 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 // Construction and destruction 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 // Arithmetic 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 // FIXME we shouldn't compare floats 03102 // BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ()); 03103 return it1_ - it.it1_; 03104 } 03105 03106 // Dereference 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 // Indices 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 // Assignment 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 // Comparison 03167 BOOST_UBLAS_INLINE 03168 bool operator == (const const_iterator1 &it) const { 03169 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); 03170 // FIXME we shouldn't compare floats 03171 // BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ()); 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 // FIXME we shouldn't compare floats 03178 // BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ()); 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 // Construction and destruction 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 // Arithmetic 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 // FIXME we shouldn't compare floats 03245 // BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ()); 03246 return it1_ - it.it1_; 03247 } 03248 03249 // Dereference 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 // Indices 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 // Assignment 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 // Comparison 03310 BOOST_UBLAS_INLINE 03311 bool operator == (const const_iterator2 &it) const { 03312 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); 03313 // FIXME we shouldn't compare floats 03314 // BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ()); 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 // FIXME we shouldn't compare floats 03321 // BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ()); 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 // Reverse iterators 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; // allow E2 to be builtin 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 // (m * t) [i] [j] = m [i] [j] * t 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 // (m / t) [i] [j] = m [i] [j] / t 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 // Construction and destruction 03427 BOOST_UBLAS_INLINE 03428 matrix_vector_binary1 (const expression1_type &e1, const expression2_type &e2): 03429 e1_ (e1), e2_ (e2) {} 03430 03431 // Accessors 03432 BOOST_UBLAS_INLINE 03433 size_type size () const { 03434 return e1_.size1 (); 03435 } 03436 03437 public: 03438 // Expression accessors 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 // Element access 03450 BOOST_UBLAS_INLINE 03451 const_reference operator () (size_type i) const { 03452 return functor_type::apply (e1_, e2_, i); 03453 } 03454 03455 // Closure comparison 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 // Iterator types 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 // Element lookup 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 // Construction and destruction 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 // Dense random access specialization 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 // Packed bidirectional specialization 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 // Sparse bidirectional specialization 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 // Arithmetic 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 // Dereference 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 // Index 03622 BOOST_UBLAS_INLINE 03623 size_type index () const { 03624 return it1_.index1 (); 03625 } 03626 03627 // Assignment 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 // Comparison 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 // Mutable due to assignment 03655 /* const */ const_subiterator2_type e2_begin_; 03656 /* const */ 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 // Reverse iterator 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 // Dispatcher 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 // Dispatcher 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 // Construction and destruction 03817 BOOST_UBLAS_INLINE 03818 matrix_vector_binary2 (const expression1_type &e1, const expression2_type &e2): 03819 e1_ (e1), e2_ (e2) {} 03820 03821 // Accessors 03822 BOOST_UBLAS_INLINE 03823 size_type size () const { 03824 return e2_.size2 (); 03825 } 03826 03827 public: 03828 // Expression accessors 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 // Element access 03840 BOOST_UBLAS_INLINE 03841 const_reference operator () (size_type j) const { 03842 return functor_type::apply (e1_, e2_, j); 03843 } 03844 03845 // Closure comparison 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 // Iterator types 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 // Element lookup 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 // Construction and destruction 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 // Dense random access specialization 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 // Packed bidirectional specialization 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 // Sparse bidirectional specialization 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 // Arithmetic 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 // Dereference 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 // Index 04012 BOOST_UBLAS_INLINE 04013 size_type index () const { 04014 return it2_.index2 (); 04015 } 04016 04017 // Assignment 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 // Comparison 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 // Mutable due to assignment 04045 /* const */ const_subiterator1_type e1_begin_; 04046 /* const */ 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 // Reverse iterator 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 // Dispatcher 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 // Dispatcher 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 // Construction and destruction 04210 BOOST_UBLAS_INLINE 04211 matrix_matrix_binary (const expression1_type &e1, const expression2_type &e2): 04212 e1_ (e1), e2_ (e2) {} 04213 04214 // Accessors 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 // Expression accessors 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 // Element access 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 // Closure comparison 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 // Iterator types 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 // Element lookup 04275 BOOST_UBLAS_INLINE 04276 const_iterator1 find1 (int /* rank */, size_type i, size_type j) const { 04277 // FIXME sparse matrix tests fail! 04278 // const_iterator11_type it11 (e1_.find1 (rank, i, 0)); 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 // FIXME sparse matrix tests fail! 04284 // const_iterator22_type it22 (e2_.find2 (rank, 0, j)); 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 /* rank */, size_type i, size_type j) const { 04291 // FIXME sparse matrix tests fail! 04292 // const_iterator22_type it22 (e2_.find2 (rank, 0, j)); 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 // FIXME sparse matrix tests fail! 04298 // const_iterator11_type it11 (e1_.find1 (rank, i, 0)); 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 // Construction and destruction 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 // Random access specialization 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 // Packed bidirectional specialization 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 // Sparse bidirectional specialization 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 // Arithmetic 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 // Dereference 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 // Indices 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 // Assignment 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 // Comparison 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 // Mutable due to assignment 04514 /* const */ const_iterator22_type it2_; 04515 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING 04516 /* const */ const_iterator21_type it2_begin_; 04517 /* const */ 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 // Construction and destruction 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 // Random access specialization 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 // Packed bidirectional specialization 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 // Sparse bidirectional specialization 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 // Arithmetic 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 // Dereference 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 // Indices 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 // Assignment 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 // Comparison 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 // Mutable due to assignment 04739 /* const */ const_iterator11_type it1_; 04740 const_iterator22_type it2_; 04741 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING 04742 /* const */ const_iterator12_type it1_begin_; 04743 /* const */ 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 // Reverse iterators 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 // Dispatcher 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 // Dispatcher 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 // Construction and destruction 04895 BOOST_UBLAS_INLINE 04896 explicit matrix_scalar_unary (const expression_type &e): 04897 e_ (e) {} 04898 04899 private: 04900 // Expression accessors 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