// // $Id$ // Copyright (C) 2009 Matwey V. Kornilov // // The file is based on files numeric/ublas/matrix_proxy.hpp // and numeric/ublas/vector_proxy.hpp from Boost uBLAS library (www.boost.org) // // Copyright (c) 2000-2002 // Joerg Walter, Mathias Koch // // Distributed under the Boost Software License, Version 1.0. // // Boost Software License - Version 1.0 - August 17th, 2003 // // Permission is hereby granted, free of charge, to any person or organization // obtaining a copy of the software and accompanying documentation covered by // this license (the "Software") to use, reproduce, display, distribute, // execute, and transmit the Software, and to prepare derivative works of the // Software, and to permit third-parties to whom the Software is furnished to // do so, all subject to the following: // // The copyright notices in the Software and this entire statement, including // the above license grant, this restriction and the following disclaimer, // must be included in all copies of the Software, in whole or in part, and // all derivative works of the Software, unless such copies or derivative // works are solely in the form of machine-executable object code generated by // a source language processor. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT // SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE // FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. // // The authors gratefully acknowledge the support of // GeNeSys mbH & Co. KG in producing this work. // #ifndef _PERMUTATION_H_ #define _PERMUTATION_H_ #include #include #include #include #include #include // for permutation_matrix // Iterators based on ideas of Jeremy Siek namespace boost { namespace numeric { namespace ublas { // Vector based permutation class template class vector_permutation: public vector_expression > { typedef vector_permutation self_type; public: #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS using vector_expression::operator (); #endif typedef const V const_vector_type; typedef V vector_type; typedef typename V::size_type size_type; typedef typename V::difference_type difference_type; typedef typename V::value_type value_type; typedef typename V::const_reference const_reference; typedef typename boost::mpl::if_, typename V::const_reference, typename V::reference>::type reference; typedef typename boost::mpl::if_, typename V::const_closure_type, typename V::closure_type>::type vector_closure_type; typedef basic_range range_type; typedef const self_type const_closure_type; typedef self_type closure_type; typedef typename storage_restrict_traits::storage_category storage_category; typedef permutation_matrix< size_type > permutation_matrix_type; // Construction and destruction BOOST_UBLAS_INLINE vector_permutation (vector_type &data, const permutation_matrix_type &permutation): data_ (data), p_ (permutation) { } BOOST_UBLAS_INLINE vector_permutation (const vector_closure_type &data, const permutation_matrix_type &permutation, bool): data_ (data), p_ (permutation) { } // Accessors BOOST_UBLAS_INLINE size_type size () const { return p_.size (); } // Storage accessors BOOST_UBLAS_INLINE const vector_closure_type &data () const { return data_; } BOOST_UBLAS_INLINE vector_closure_type &data () { return data_; } // Element access #ifndef BOOST_UBLAS_PROXY_CONST_MEMBER BOOST_UBLAS_INLINE const_reference operator () (size_type i) const { return data_ (p_ (i)); } BOOST_UBLAS_INLINE reference operator () (size_type i) { return data_ (p_ (i)); } BOOST_UBLAS_INLINE const_reference operator [] (size_type i) const { return (*this) (i); } BOOST_UBLAS_INLINE reference operator [] (size_type i) { return (*this) (i); } #else BOOST_UBLAS_INLINE reference operator () (size_type i) const { return data_ (p_ (i)); } BOOST_UBLAS_INLINE reference operator [] (size_type i) const { return (*this) (i); } #endif // Assignment BOOST_UBLAS_INLINE vector_permutation &operator = (const vector_permutation &vp) { // ISSUE need a temporary, proxy can be overlaping alias vector_assign (*this, typename vector_temporary_traits::type (vp)); return *this; } BOOST_UBLAS_INLINE vector_permutation &assign_temporary (vector_permutation &vp) { // assign elements, proxied container remains the same vector_assign (*this, vp); return *this; } template BOOST_UBLAS_INLINE vector_permutation &operator = (const vector_expression &ae) { vector_assign (*this, typename vector_temporary_traits::type (ae)); return *this; } template BOOST_UBLAS_INLINE vector_permutation &assign (const vector_expression &ae) { vector_assign (*this, ae); return *this; } template BOOST_UBLAS_INLINE vector_permutation &operator += (const vector_expression &ae) { vector_assign (*this, typename vector_temporary_traits::type (*this + ae)); return *this; } template BOOST_UBLAS_INLINE vector_permutation &plus_assign (const vector_expression &ae) { vector_assign (*this, ae); return *this; } template BOOST_UBLAS_INLINE vector_permutation &operator -= (const vector_expression &ae) { vector_assign (*this, typename vector_temporary_traits::type (*this - ae)); return *this; } template BOOST_UBLAS_INLINE vector_permutation &minus_assign (const vector_expression &ae) { vector_assign (*this, ae); return *this; } template BOOST_UBLAS_INLINE vector_permutation &operator *= (const AT &at) { vector_assign_scalar (*this, at); return *this; } template BOOST_UBLAS_INLINE vector_permutation &operator /= (const AT &at) { vector_assign_scalar (*this, at); return *this; } // Closure comparison BOOST_UBLAS_INLINE bool same_closure (const vector_permutation &vp) const { return (*this).data_.same_closure (vp.data_); } // Comparison BOOST_UBLAS_INLINE bool operator == (const vector_permutation &vp) const { return (*this).data_ == vp.data_ && p_ == vp.p_; } // Swapping BOOST_UBLAS_INLINE void swap (vector_permutation vp) { if (this != &vp) { BOOST_UBLAS_CHECK (size () == vp.size (), bad_size ()); vector_swap (*this, vp); } } BOOST_UBLAS_INLINE friend void swap (vector_permutation vp1, vector_permutation vp2) { vp1.swap (vp2); } // Iterator types private: typedef typename permutation_matrix_type::const_iterator const_subiterator_type; typedef typename permutation_matrix_type::const_iterator subiterator_type; typedef typename V::const_iterator const_dataiterator_type; typedef typename boost::mpl::if_, typename V::const_iterator, typename V::iterator>::type dataiterator_type; public: #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR typedef indexed_iterator, typename subiterator_type::iterator_category> iterator; typedef indexed_const_iterator, typename const_subiterator_type::iterator_category> const_iterator; #else class const_iterator; class iterator; #endif // Element lookup BOOST_UBLAS_INLINE const_iterator find (size_type i) const { const_subiterator_type it (p_.find ( i )); #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR return const_iterator (*this, it.index ()); #else return const_iterator (*this, it); #endif } BOOST_UBLAS_INLINE iterator find (size_type i) { subiterator_type it (p_.find ( i )); #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR return iterator (*this, it.index ()); #else return iterator (*this, it); #endif } #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR class const_iterator: public container_const_reference, public iterator_base_traits::template iterator_base::type { public: typedef typename const_subiterator_type::difference_type difference_type; typedef typename const_dataiterator_type::value_type value_type; typedef typename const_dataiterator_type::reference reference; typedef typename const_dataiterator_type::pointer pointer; // Construction and destruction BOOST_UBLAS_INLINE const_iterator (): container_const_reference (), it_ () {} BOOST_UBLAS_INLINE const_iterator (const self_type &vp, const const_subiterator_type &it): container_const_reference (vp), it_ (it) {} BOOST_UBLAS_INLINE const_iterator (const typename self_type::iterator &it): // ISSUE self_type:: stops VC8 using std::iterator here container_const_reference (it ()), it_ (it.it_) {} // Arithmetic BOOST_UBLAS_INLINE const_iterator &operator ++ () { ++ it_; return *this; } BOOST_UBLAS_INLINE const_iterator &operator -- () { -- it_; return *this; } BOOST_UBLAS_INLINE const_iterator &operator += (difference_type n) { it_ += n; return *this; } BOOST_UBLAS_INLINE const_iterator &operator -= (difference_type n) { it_ -= n; return *this; } BOOST_UBLAS_INLINE difference_type operator - (const const_iterator &it) const { BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); return it_ - it.it_; } // Dereference BOOST_UBLAS_INLINE const_reference operator * () const { BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ()); return *( (*this)().data_.find( *it_ ) ); } BOOST_UBLAS_INLINE const_reference operator [] (difference_type n) const { return *(*this + n); } // Index BOOST_UBLAS_INLINE size_type index () const { return it_.index (); } // Assignment BOOST_UBLAS_INLINE const_iterator &operator = (const const_iterator &it) { container_const_reference::assign (&it ()); it_ = it.it_; return *this; } // Comparison BOOST_UBLAS_INLINE bool operator == (const const_iterator &it) const { BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); return it_ == it.it_; } BOOST_UBLAS_INLINE bool operator < (const const_iterator &it) const { BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); return it_ < it.it_; } private: const_subiterator_type it_; }; #endif BOOST_UBLAS_INLINE const_iterator begin () const { return find (0); } BOOST_UBLAS_INLINE const_iterator end () const { return find (size ()); } #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR class iterator: public container_reference, public iterator_base_traits::template iterator_base::type { public: typedef typename subiterator_type::difference_type difference_type; typedef typename dataiterator_type::value_type value_type; typedef typename dataiterator_type::reference reference; typedef typename dataiterator_type::pointer pointer; // Construction and destruction BOOST_UBLAS_INLINE iterator (): container_reference (), it_ () {} BOOST_UBLAS_INLINE iterator (self_type &vp, const subiterator_type &it): container_reference (vp), it_ (it) {} // Arithmetic BOOST_UBLAS_INLINE iterator &operator ++ () { ++ it_; return *this; } BOOST_UBLAS_INLINE iterator &operator -- () { -- it_; return *this; } BOOST_UBLAS_INLINE iterator &operator += (difference_type n) { it_ += n; return *this; } BOOST_UBLAS_INLINE iterator &operator -= (difference_type n) { it_ -= n; return *this; } BOOST_UBLAS_INLINE difference_type operator - (const iterator &it) const { BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); return it_ - it.it_; } // Dereference BOOST_UBLAS_INLINE reference operator * () const { BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ()); return *( (*this)().data_.find( *it_ ) ); } BOOST_UBLAS_INLINE reference operator [] (difference_type n) const { return *(*this + n); } // Index BOOST_UBLAS_INLINE size_type index () const { return it_.index (); } // Assignment BOOST_UBLAS_INLINE iterator &operator = (const iterator &it) { container_reference::assign (&it ()); it_ = it.it_; return *this; } // Comparison BOOST_UBLAS_INLINE bool operator == (const iterator &it) const { BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); return it_ == it.it_; } BOOST_UBLAS_INLINE bool operator < (const iterator &it) const { BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); return it_ < it.it_; } private: subiterator_type it_; friend class const_iterator; }; #endif BOOST_UBLAS_INLINE iterator begin () { return find (0); } BOOST_UBLAS_INLINE iterator end () { return find (size ()); } // Reverse iterator typedef reverse_iterator_base const_reverse_iterator; typedef reverse_iterator_base reverse_iterator; BOOST_UBLAS_INLINE const_reverse_iterator rbegin () const { return const_reverse_iterator (end ()); } BOOST_UBLAS_INLINE const_reverse_iterator rend () const { return const_reverse_iterator (begin ()); } BOOST_UBLAS_INLINE reverse_iterator rbegin () { return reverse_iterator (end ()); } BOOST_UBLAS_INLINE reverse_iterator rend () { return reverse_iterator (begin ()); } private: vector_closure_type data_; const permutation_matrix_type& p_; }; // Matrix based permutation class template class matrix_permutation: public matrix_expression > { typedef matrix_permutation self_type; public: #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS using matrix_expression::operator (); #endif typedef M matrix_type; typedef typename M::size_type size_type; typedef typename M::difference_type difference_type; typedef typename M::value_type value_type; typedef typename M::const_reference const_reference; typedef typename boost::mpl::if_, typename M::const_reference, typename M::reference>::type reference; typedef typename boost::mpl::if_, typename M::const_closure_type, typename M::closure_type>::type matrix_closure_type; typedef basic_range range_type; typedef const self_type const_closure_type; typedef self_type closure_type; typedef typename storage_restrict_traits::storage_category storage_category; typedef typename M::orientation_category orientation_category; typedef permutation_matrix< size_type > permutation_matrix_type; // Construction and destruction BOOST_UBLAS_INLINE matrix_permutation (matrix_type &data, const permutation_matrix_type &permutation1, const permutation_matrix_type &permutation2): data_ (data), p1_ (permutation1), p2_ (permutation2) { } BOOST_UBLAS_INLINE matrix_permutation (const matrix_closure_type &data, const permutation_matrix_type &permutation1, const permutation_matrix_type &permutation2, int): data_ (data), p1_ (permutation1), p2_ (permutation2) { } // Accessors BOOST_UBLAS_INLINE size_type size1 () const { return p1_.size (); } BOOST_UBLAS_INLINE size_type size2 () const { return p2_.size (); } // Storage accessors BOOST_UBLAS_INLINE const matrix_closure_type &data () const { return data_; } BOOST_UBLAS_INLINE matrix_closure_type &data () { return data_; } // Element access #ifndef BOOST_UBLAS_PROXY_CONST_MEMBER BOOST_UBLAS_INLINE const_reference operator () (size_type i, size_type j) const { return data_ (p1_ (i), p2_ (j)); } BOOST_UBLAS_INLINE reference operator () (size_type i, size_type j) { return data_ (p1_ (i), p2_ (j)); } #else BOOST_UBLAS_INLINE reference operator () (size_type i, size_type j) const { return data_ (p1_ (i), p2_ (j)); } #endif // Assignment BOOST_UBLAS_INLINE matrix_permutation &operator = (const matrix_permutation &mp) { matrix_assign (*this, mp); return *this; } BOOST_UBLAS_INLINE matrix_permutation &assign_temporary (matrix_permutation &mp) { return *this = mp; } template BOOST_UBLAS_INLINE matrix_permutation &operator = (const matrix_expression &ae) { matrix_assign (*this, typename matrix_temporary_traits::type (ae)); return *this; } template BOOST_UBLAS_INLINE matrix_permutation &assign (const matrix_expression &ae) { matrix_assign (*this, ae); return *this; } template BOOST_UBLAS_INLINE matrix_permutation& operator += (const matrix_expression &ae) { matrix_assign (*this, typename matrix_temporary_traits::type (*this + ae)); return *this; } template BOOST_UBLAS_INLINE matrix_permutation &plus_assign (const matrix_expression &ae) { matrix_assign (*this, ae); return *this; } template BOOST_UBLAS_INLINE matrix_permutation& operator -= (const matrix_expression &ae) { matrix_assign (*this, typename matrix_temporary_traits::type (*this - ae)); return *this; } template BOOST_UBLAS_INLINE matrix_permutation &minus_assign (const matrix_expression &ae) { matrix_assign (*this, ae); return *this; } template BOOST_UBLAS_INLINE matrix_permutation& operator *= (const AT &at) { matrix_assign_scalar (*this, at); return *this; } template BOOST_UBLAS_INLINE matrix_permutation& operator /= (const AT &at) { matrix_assign_scalar (*this, at); return *this; } // Closure comparison BOOST_UBLAS_INLINE bool same_closure (const matrix_permutation &mp) const { return (*this).data_.same_closure (mp.data_); } // Comparison BOOST_UBLAS_INLINE bool operator == (const matrix_permutation &mp) const { return (*this).data_ == (mp.data_) && p1_ == mp.p1_ && p2_ == mp.p2_; } // Swapping BOOST_UBLAS_INLINE void swap (matrix_permutation mp) { if (this != &mp) { BOOST_UBLAS_CHECK (size1 () == mp.size1 (), bad_size ()); BOOST_UBLAS_CHECK (size2 () == mp.size2 (), bad_size ()); matrix_swap (*this, mp); } } BOOST_UBLAS_INLINE friend void swap (matrix_permutation mp1, matrix_permutation mp2) { mp1.swap (mp2); } // Iterator types private: typedef typename permutation_matrix_type::const_iterator const_subiterator1_type; typedef typename permutation_matrix_type::const_iterator subiterator1_type; typedef typename permutation_matrix_type::const_iterator const_subiterator2_type; typedef typename permutation_matrix_type::const_iterator subiterator2_type; typedef typename M::const_iterator1 const_dataiterator1_type; typedef typename boost::mpl::if_, typename M::const_iterator1, typename M::iterator1>::type dataiterator1_type; typedef typename M::const_iterator2 const_dataiterator2_type; typedef typename boost::mpl::if_, typename M::const_iterator2, typename M::iterator2>::type dataiterator2_type; public: #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR typedef indexed_iterator1, typename subiterator1_type::iterator_category> iterator1; typedef indexed_iterator2, typename subiterator2_type::iterator_category> iterator2; typedef indexed_const_iterator1, typename const_subiterator1_type::iterator_category> const_iterator1; typedef indexed_const_iterator2, typename const_subiterator2_type::iterator_category> const_iterator2; #else class const_iterator1; class iterator1; class const_iterator2; class iterator2; #endif typedef reverse_iterator_base1 const_reverse_iterator1; typedef reverse_iterator_base1 reverse_iterator1; typedef reverse_iterator_base2 const_reverse_iterator2; typedef reverse_iterator_base2 reverse_iterator2; // Element lookup BOOST_UBLAS_INLINE const_iterator1 find1 (int rank, size_type i, size_type j) const { const_subiterator1_type it1 ( p1_.find(i) ); const_subiterator2_type it2 ( p2_.find(j) ); #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR return const_iterator1 (*this, it1.index (), it2.index ()); #else return const_iterator1 (*this, it1, it2); #endif } BOOST_UBLAS_INLINE iterator1 find1 (int rank, size_type i, size_type j) { subiterator1_type it1 ( p1_.find(i) ); subiterator2_type it2 ( p2_.find(j) ); #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR return iterator1 (*this, it1.index (), it2.index ()); #else return iterator1 (*this, it1, it2); #endif } BOOST_UBLAS_INLINE const_iterator2 find2 (int rank, size_type i, size_type j) const { const_subiterator1_type it1 ( p1_.find(i) ); const_subiterator2_type it2 ( p2_.find(j) ); #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR return const_iterator2 (*this, it1.index (), it2.index ()); #else return const_iterator2 (*this, it1, it2); #endif } BOOST_UBLAS_INLINE iterator2 find2 (int rank, size_type i, size_type j) { subiterator1_type it1 ( p1_.find(i) ); subiterator2_type it2 ( p2_.find(j) ); #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR return iterator2 (*this, it1.index (), it2.index ()); #else return iterator2 (*this, it1, it2); #endif } #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR class const_iterator1: public container_const_reference, public iterator_base_traits::template iterator_base::type { public: typedef typename const_dataiterator1_type::value_type value_type; typedef typename const_subiterator1_type::difference_type difference_type; typedef typename const_dataiterator1_type::reference reference; typedef typename const_dataiterator1_type::pointer pointer; typedef const_iterator2 dual_iterator_type; typedef const_reverse_iterator2 dual_reverse_iterator_type; // Construction and destruction BOOST_UBLAS_INLINE const_iterator1 (): container_const_reference (), it1_ (), it2_() {} BOOST_UBLAS_INLINE const_iterator1 (const self_type &mp, const const_subiterator1_type &it1, const const_subiterator2_type &it2 ): container_const_reference (mp), it1_ (it1), it2_ (it2) {} BOOST_UBLAS_INLINE const_iterator1 (const iterator1 &it): container_const_reference (it ()), it1_ (it.it1_), it2_(it.it2_) {} // Arithmetic BOOST_UBLAS_INLINE const_iterator1 &operator ++ () { ++ it1_; return *this; } BOOST_UBLAS_INLINE const_iterator1 &operator -- () { -- it1_; return *this; } BOOST_UBLAS_INLINE const_iterator1 &operator += (difference_type n) { it1_ += n; return *this; } BOOST_UBLAS_INLINE const_iterator1 &operator -= (difference_type n) { it1_ -= n; return *this; } BOOST_UBLAS_INLINE difference_type operator - (const const_iterator1 &it) const { BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); return it1_ - it.it1_; } // Dereference BOOST_UBLAS_INLINE const_reference operator * () const { return *( (*this)().data_.find1( 0, *it1_, *it2_ ) ); } BOOST_UBLAS_INLINE const_reference operator [] (difference_type n) const { return *(*this + n); } #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_iterator2 begin () const { const self_type &mp = (*this) (); return mp.find2 (1, index1 (), 0); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_iterator2 end () const { const self_type &mp = (*this) (); return mp.find2 (1, index1 (), mp.size2 ()); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator2 rbegin () const { return const_reverse_iterator2 (end ()); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator2 rend () const { return const_reverse_iterator2 (begin ()); } #endif // Indices BOOST_UBLAS_INLINE size_type index1 () const { return it1_.index (); } BOOST_UBLAS_INLINE size_type index2 () const { return it2_.index (); } // Assignment BOOST_UBLAS_INLINE const_iterator1 &operator = (const const_iterator1 &it) { container_const_reference::assign (&it ()); it1_ = it.it1_; return *this; } // Comparison BOOST_UBLAS_INLINE bool operator == (const const_iterator1 &it) const { BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); return it1_ == it.it1_; } BOOST_UBLAS_INLINE bool operator < (const const_iterator1 &it) const { BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); return it1_ < it.it1_; } private: const_subiterator1_type it1_; const_subiterator2_type it2_; }; #endif BOOST_UBLAS_INLINE const_iterator1 begin1 () const { return find1 (0, 0, 0); } BOOST_UBLAS_INLINE const_iterator1 end1 () const { return find1 (0, size1 (), 0); } #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR class iterator1: public container_reference, public iterator_base_traits::template iterator_base::type { public: typedef typename dataiterator1_type::value_type value_type; typedef typename subiterator1_type::difference_type difference_type; typedef typename dataiterator1_type::reference reference; typedef typename dataiterator1_type::pointer pointer; typedef iterator2 dual_iterator_type; typedef reverse_iterator2 dual_reverse_iterator_type; // Construction and destruction BOOST_UBLAS_INLINE iterator1 (): container_reference (), it1_ (), it2_() {} BOOST_UBLAS_INLINE iterator1 (self_type &mp, const subiterator1_type &it1, const subiterator2_type &it2): container_reference (mp), it1_ (it1), it2_ (it2) {} // Arithmetic BOOST_UBLAS_INLINE iterator1 &operator ++ () { ++ it1_; return *this; } BOOST_UBLAS_INLINE iterator1 &operator -- () { -- it1_; return *this; } BOOST_UBLAS_INLINE iterator1 &operator += (difference_type n) { it1_ += n; return *this; } BOOST_UBLAS_INLINE iterator1 &operator -= (difference_type n) { it1_ -= n; return *this; } BOOST_UBLAS_INLINE difference_type operator - (const iterator1 &it) const { BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); return it1_ - it.it1_; } // Dereference BOOST_UBLAS_INLINE reference operator * () const { return *( (*this()).data_.find2(0, *it1_, *it2_ ) ); } BOOST_UBLAS_INLINE reference operator [] (difference_type n) const { return *(*this + n); } #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif iterator2 begin () const { self_type &mp = (*this) (); return mp.find2 (1, index1 (), 0); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif iterator2 end () const { self_type &mp = (*this) (); return mp.find2 (1, index1 (), mp.size2 ()); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif reverse_iterator2 rbegin () const { return reverse_iterator2 (end ()); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif reverse_iterator2 rend () const { return reverse_iterator2 (begin ()); } #endif // Indices BOOST_UBLAS_INLINE size_type index1 () const { return it1_.index (); } BOOST_UBLAS_INLINE size_type index2 () const { return it2_.index (); } // Assignment BOOST_UBLAS_INLINE iterator1 &operator = (const iterator1 &it) { container_reference::assign (&it ()); it1_ = it.it1_; return *this; } // Comparison BOOST_UBLAS_INLINE bool operator == (const iterator1 &it) const { BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); return it1_ == it.it1_; } BOOST_UBLAS_INLINE bool operator < (const iterator1 &it) const { BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); return it1_ < it.it1_; } private: subiterator1_type it1_; subiterator2_type it2_; friend class const_iterator1; friend class const_iterator2; }; #endif BOOST_UBLAS_INLINE iterator1 begin1 () { return find1 (0, 0, 0); } BOOST_UBLAS_INLINE iterator1 end1 () { return find1 (0, size1 (), 0); } #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR class const_iterator2: public container_const_reference, public iterator_base_traits::template iterator_base::type { public: typedef typename const_dataiterator2_type::value_type value_type; typedef typename const_subiterator2_type::difference_type difference_type; typedef typename const_dataiterator2_type::reference reference; typedef typename const_dataiterator2_type::pointer pointer; typedef const_iterator1 dual_iterator_type; typedef const_reverse_iterator1 dual_reverse_iterator_type; // Construction and destruction BOOST_UBLAS_INLINE const_iterator2 (): container_const_reference (), it1_ (), it2_ () {} BOOST_UBLAS_INLINE const_iterator2 (const self_type &mp, const const_subiterator1_type &it1, const const_subiterator2_type &it2): container_const_reference (mp), it1_ (it1), it2_ (it2) {} BOOST_UBLAS_INLINE const_iterator2 (const iterator2 &it): container_const_reference (it ()), it1_ (it.it1_), it2_ (it.it2_) {} // Arithmetic BOOST_UBLAS_INLINE const_iterator2 &operator ++ () { ++ it2_; return *this; } BOOST_UBLAS_INLINE const_iterator2 &operator -- () { -- it2_; return *this; } BOOST_UBLAS_INLINE const_iterator2 &operator += (difference_type n) { it2_ += n; return *this; } BOOST_UBLAS_INLINE const_iterator2 &operator -= (difference_type n) { it2_ -= n; return *this; } BOOST_UBLAS_INLINE difference_type operator - (const const_iterator2 &it) const { BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); return it2_ - it.it2_; } // Dereference BOOST_UBLAS_INLINE const_reference operator * () const { return *( (*this)().data_.find(0, *it1_, *it2_ )); } BOOST_UBLAS_INLINE const_reference operator [] (difference_type n) const { return *(*this + n); } #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_iterator1 begin () const { const self_type &mp = (*this) (); return mp.find1 (1, 0, index2 ()); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_iterator1 end () const { const self_type &mp = (*this) (); return mp.find1 (1, mp.size1 (), index2 ()); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator1 rbegin () const { return const_reverse_iterator1 (end ()); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator1 rend () const { return const_reverse_iterator1 (begin ()); } #endif // Indices BOOST_UBLAS_INLINE size_type index1 () const { return it1_.index (); } BOOST_UBLAS_INLINE size_type index2 () const { return it2_.index (); } // Assignment BOOST_UBLAS_INLINE const_iterator2 &operator = (const const_iterator2 &it) { container_const_reference::assign (&it ()); it2_ = it.it2_; return *this; } // Comparison BOOST_UBLAS_INLINE bool operator == (const const_iterator2 &it) const { BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); return it2_ == it.it2_; } BOOST_UBLAS_INLINE bool operator < (const const_iterator2 &it) const { BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); return it2_ < it.it2_; } private: const_subiterator1_type it1_; const_subiterator2_type it2_; }; #endif BOOST_UBLAS_INLINE const_iterator2 begin2 () const { return find2 (0, 0, 0); } BOOST_UBLAS_INLINE const_iterator2 end2 () const { return find2 (0, 0, size2 ()); } #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR class iterator2: public container_reference, public iterator_base_traits::template iterator_base::type { public: typedef typename dataiterator2_type::value_type value_type; typedef typename subiterator2_type::difference_type difference_type; typedef typename dataiterator2_type::reference reference; typedef typename dataiterator2_type::pointer pointer; typedef iterator1 dual_iterator_type; typedef reverse_iterator1 dual_reverse_iterator_type; // Construction and destruction BOOST_UBLAS_INLINE iterator2 (): container_reference (), it1_ (), it2_ () {} BOOST_UBLAS_INLINE iterator2 (self_type &mp, const subiterator1_type &it1, const subiterator2_type &it2): container_reference (mp), it1_ (it1), it2_ (it2) {} // Arithmetic BOOST_UBLAS_INLINE iterator2 &operator ++ () { ++ it2_; return *this; } BOOST_UBLAS_INLINE iterator2 &operator -- () { -- it2_; return *this; } BOOST_UBLAS_INLINE iterator2 &operator += (difference_type n) { it2_ += n; return *this; } BOOST_UBLAS_INLINE iterator2 &operator -= (difference_type n) { it2_ -= n; return *this; } BOOST_UBLAS_INLINE difference_type operator - (const iterator2 &it) const { BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); return it2_ - it.it2_; } // Dereference BOOST_UBLAS_INLINE reference operator * () const { return *( (*this)().data_.find(0, *it1_, *it2_ ) ); } BOOST_UBLAS_INLINE reference operator [] (difference_type n) const { return *(*this + n); } #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif iterator1 begin () const { self_type &mp = (*this) (); return mp.find1 (1, 0, index2 ()); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif iterator1 end () const { self_type &mp = (*this) (); return mp.find1 (1, mp.size1 (), index2 ()); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif reverse_iterator1 rbegin () const { return reverse_iterator1 (end ()); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif reverse_iterator1 rend () const { return reverse_iterator1 (begin ()); } #endif // Indices BOOST_UBLAS_INLINE size_type index1 () const { return it1_.index (); } BOOST_UBLAS_INLINE size_type index2 () const { return it2_.index (); } // Assignment BOOST_UBLAS_INLINE iterator2 &operator = (const iterator2 &it) { container_reference::assign (&it ()); it2_ = it.it2_; return *this; } // Comparison BOOST_UBLAS_INLINE bool operator == (const iterator2 &it) const { BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); return it2_ == it.it2_; } BOOST_UBLAS_INLINE bool operator < (const iterator2 &it) const { BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); return it2_ < it.it2_; } private: subiterator1_type it1_; subiterator2_type it2_; friend class const_iterator1; friend class const_iterator2; }; #endif BOOST_UBLAS_INLINE iterator2 begin2 () { return find2 (0, 0, 0); } BOOST_UBLAS_INLINE iterator2 end2 () { return find2 (0, 0, size2 ()); } // Reverse iterators BOOST_UBLAS_INLINE const_reverse_iterator1 rbegin1 () const { return const_reverse_iterator1 (end1 ()); } BOOST_UBLAS_INLINE const_reverse_iterator1 rend1 () const { return const_reverse_iterator1 (begin1 ()); } BOOST_UBLAS_INLINE reverse_iterator1 rbegin1 () { return reverse_iterator1 (end1 ()); } BOOST_UBLAS_INLINE reverse_iterator1 rend1 () { return reverse_iterator1 (begin1 ()); } BOOST_UBLAS_INLINE const_reverse_iterator2 rbegin2 () const { return const_reverse_iterator2 (end2 ()); } BOOST_UBLAS_INLINE const_reverse_iterator2 rend2 () const { return const_reverse_iterator2 (begin2 ()); } BOOST_UBLAS_INLINE reverse_iterator2 rbegin2 () { return reverse_iterator2 (end2 ()); } BOOST_UBLAS_INLINE reverse_iterator2 rend2 () { return reverse_iterator2 (begin2 ()); } private: matrix_closure_type data_; const permutation_matrix_type& p1_; const permutation_matrix_type& p2_; }; // Specialization of temporary_traits template struct vector_temporary_traits< vector_permutation > : vector_temporary_traits< V > {} ; template struct vector_temporary_traits< const vector_permutation > : vector_temporary_traits< V > {} ; // Specialize temporary template struct vector_temporary_traits< matrix_permutation > : vector_temporary_traits< M > {} ; template struct vector_temporary_traits< const matrix_permutation > : vector_temporary_traits< M > {} ; }}} #endif // _PERMUTATION_H_