Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:43:04

0001 //
0002 //  Copyright (c) 2000-2013
0003 //  Joerg Walter, Mathias Koch, Athanasios Iliopoulos
0004 //
0005 //  Distributed under the Boost Software License, Version 1.0. (See
0006 //  accompanying file LICENSE_1_0.txt or copy at
0007 //  http://www.boost.org/LICENSE_1_0.txt)
0008 //
0009 //  The authors gratefully acknowledge the support of
0010 //  GeNeSys mbH & Co. KG in producing this work.
0011 //
0012 
0013 #ifndef _BOOST_UBLAS_BANDED_
0014 #define _BOOST_UBLAS_BANDED_
0015 
0016 #include <boost/numeric/ublas/matrix.hpp>
0017 #include <boost/numeric/ublas/detail/temporary.hpp>
0018 
0019 // Iterators based on ideas of Jeremy Siek
0020 
0021 namespace boost { namespace numeric { namespace ublas {
0022 
0023 
0024 namespace hidden {
0025 
0026 
0027 
0028 /** \brief A helper for band_matrix indexing.
0029  *
0030  * The indexing happens as per the netlib description: http://www.netlib.org/lapack/lug/node124.html.
0031  * In the case of a row_major matrix a different approach is followed;
0032  */
0033 template <class LayoutType>
0034 class banded_indexing { };
0035 
0036 /** \brief A helper for indexing column major banded matrices.
0037  *
0038  */
0039 template <>
0040 class banded_indexing<column_major_tag> {
0041 public:
0042 
0043     template <class T>
0044     BOOST_UBLAS_INLINE static T size(T /*size1*/, T size2) {
0045         return size2;
0046     }
0047 
0048 //    template <class T>
0049 //    BOOST_UBLAS_INLINE static bool valid_index(T size1, T /*size2*/, T lower, T upper, T i, T j) {
0050 //        return (upper+i >= j) && i <= std::min(size1 - 1, j + lower); // upper + i is used by get_index. Maybe find a way to consolidate the operations to increase performance
0051 //    }
0052 
0053     template <class T>
0054     BOOST_UBLAS_INLINE static T get_index(T /*size1*/, T size2, T lower, T upper, T i, T j) {
0055         return column_major::element (upper + i - j, lower + 1 + upper, j, size2);
0056     }
0057 };
0058 
0059 /** \brief A helper for indexing row major banded matrices.
0060  *
0061  */
0062 template <>
0063 class banded_indexing<row_major_tag> {
0064 public:
0065 
0066     template <class T>
0067     BOOST_UBLAS_INLINE static T size(T size1, T /*size2*/) {
0068         return size1;
0069     }
0070 
0071   //  template <class T>
0072   //  BOOST_UBLAS_INLINE static bool valid_index(T /*size1*/, T  size2, T lower, T upper, T i, T j) {
0073   //      return (lower+j >= i) && j <= std::min(size2 - 1, i + upper); // lower + j is used by get_index. Maybe find a way to consolidate the operations to increase performance
0074   //  }
0075 
0076     template <class T>
0077     BOOST_UBLAS_INLINE static T get_index(T size1, T /*size2*/, T lower, T upper, T i, T j) {
0078         return row_major::element (i, size1, lower + j - i, lower + 1 + upper);
0079     }
0080 };
0081 
0082 }
0083 
0084     /** \brief A banded matrix of values of type \c T.
0085      *
0086      * For a \f$(mxn)\f$-dimensional banded matrix with \f$l\f$ lower and \f$u\f$ upper diagonals and 
0087      * \f$0 \leq i < m\f$ and \f$0 \leq j < n\f$, if \f$i>j+l\f$ or \f$i<j-u\f$ then \f$b_{i,j}=0\f$. 
0088      * The default storage for banded matrices is packed. Orientation and storage can also be specified. 
0089      * Default is \c row_major and and unbounded_array. It is \b not required by the storage to initialize 
0090      * elements of the matrix.
0091      *
0092      * \tparam T the type of object stored in the matrix (like double, float, complex, etc...)
0093      * \tparam L the storage organization. It can be either \c row_major or \c column_major. Default is \c row_major
0094      * \tparam A the type of Storage array. Default is \c unbounded_array
0095      */
0096     template<class T, class L, class A>
0097     class banded_matrix:
0098         public matrix_container<banded_matrix<T, L, A> > {
0099 
0100         typedef T *pointer;
0101         typedef L layout_type;
0102         typedef banded_matrix<T, L, A> self_type;
0103 
0104 
0105 
0106     public:
0107 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
0108         using matrix_container<self_type>::operator ();
0109 #endif
0110         typedef typename A::size_type size_type;
0111         typedef typename A::difference_type difference_type;
0112         typedef T value_type;
0113         typedef const T &const_reference;
0114         typedef T &reference;
0115         typedef A array_type;
0116         typedef const matrix_reference<const self_type> const_closure_type;
0117         typedef matrix_reference<self_type> closure_type;
0118         typedef vector<T, A> vector_temporary_type;
0119         typedef matrix<T, L, A> matrix_temporary_type;  // general sub-matrix
0120         typedef packed_tag storage_category;
0121         typedef typename L::orientation_category orientation_category;
0122 
0123     private:
0124     public:
0125 
0126         // Construction and destruction
0127         BOOST_UBLAS_INLINE
0128         banded_matrix ():
0129             matrix_container<self_type> (),
0130             size1_ (0), size2_ (0),
0131             lower_ (0), upper_ (0), data_ (0) {}
0132         BOOST_UBLAS_INLINE
0133         banded_matrix (size_type size1, size_type size2, size_type lower = 0, size_type upper = 0):
0134             matrix_container<self_type> (),
0135             size1_ (size1), size2_ (size2),
0136             lower_ (lower), upper_ (upper),
0137 #if defined(BOOST_UBLAS_OWN_BANDED) || (BOOST_UBLAS_LEGACY_BANDED)
0138             data_ ((std::max) (size1, size2) * (lower + 1 + upper))
0139 #else
0140             data_ ( hidden::banded_indexing<orientation_category>::size(size1, size2) * (lower + 1 + upper)) // This is the netlib layout as described here: http://www.netlib.org/lapack/lug/node124.html
0141 #endif
0142         {
0143         }
0144         BOOST_UBLAS_INLINE
0145         banded_matrix (size_type size1, size_type size2, size_type lower, size_type upper, const array_type &data):
0146             matrix_container<self_type> (),
0147             size1_ (size1), size2_ (size2),
0148             lower_ (lower), upper_ (upper), data_ (data) {}
0149         BOOST_UBLAS_INLINE
0150         banded_matrix (const banded_matrix &m):
0151             matrix_container<self_type> (),
0152             size1_ (m.size1_), size2_ (m.size2_),
0153             lower_ (m.lower_), upper_ (m.upper_), data_ (m.data_) {}
0154         template<class AE>
0155         BOOST_UBLAS_INLINE
0156         banded_matrix (const matrix_expression<AE> &ae, size_type lower = 0, size_type upper = 0):
0157             matrix_container<self_type> (),
0158             size1_ (ae ().size1 ()), size2_ (ae ().size2 ()),
0159             lower_ (lower), upper_ (upper),
0160 #if defined(BOOST_UBLAS_OWN_BANDED) || (BOOST_UBLAS_LEGACY_BANDED)
0161             data_ ((std::max) (size1_, size2_) * (lower_ + 1 + upper_))
0162 #else
0163             data_ ( hidden::banded_indexing<orientation_category>::size(size1_, size2_) * (lower_ + 1 + upper_)) // This is the netlib layout as described here: http://www.netlib.org/lapack/lug/node124.html
0164 #endif
0165         {
0166             matrix_assign<scalar_assign> (*this, ae);
0167         }
0168 
0169         // Accessors
0170         BOOST_UBLAS_INLINE
0171         size_type size1 () const {
0172             return size1_;
0173         }
0174         BOOST_UBLAS_INLINE
0175         size_type size2 () const {
0176             return size2_;
0177         }
0178         BOOST_UBLAS_INLINE
0179         size_type lower () const {
0180             return lower_;
0181         }
0182         BOOST_UBLAS_INLINE
0183         size_type upper () const {
0184             return upper_;
0185         }
0186 
0187         // Storage accessors
0188         BOOST_UBLAS_INLINE
0189         const array_type &data () const {
0190             return data_;
0191         }
0192         BOOST_UBLAS_INLINE
0193         array_type &data () {
0194             return data_;
0195         }
0196 
0197 #if !defined (BOOST_UBLAS_OWN_BANDED)||(BOOST_UBLAS_LEGACY_BANDED)
0198         BOOST_UBLAS_INLINE
0199         bool is_element_in_band(size_type i, size_type j) const{
0200             //return (upper_+i >= j) && i <= std::min(size1() - 1, j + lower_); // We don't need to check if i is outside because it is checked anyway in the accessors.
0201             return (upper_+i >= j) && i <= ( j + lower_); // Essentially this band has "infinite" positive dimensions
0202         }
0203 #endif
0204         // Resizing
0205         BOOST_UBLAS_INLINE
0206         void resize (size_type size1, size_type size2, size_type lower = 0, size_type upper = 0, bool preserve = true) {
0207             if (preserve) {
0208                 self_type temporary (size1, size2, lower, upper);
0209                 detail::matrix_resize_preserve<layout_type> (*this, temporary);
0210             }
0211             else {
0212                 data ().resize ((std::max) (size1, size2) * (lower + 1 + upper));
0213                 size1_ = size1;
0214                 size2_ = size2;
0215                 lower_ = lower;
0216                 upper_ = upper;
0217             }
0218         }
0219 
0220         BOOST_UBLAS_INLINE
0221         void resize_packed_preserve (size_type size1, size_type size2, size_type lower = 0, size_type upper = 0) {
0222             size1_ = size1;
0223             size2_ = size2;
0224             lower_ = lower;
0225             upper_ = upper;
0226             data ().resize ((std::max) (size1, size2) * (lower + 1 + upper), value_type ());
0227         }
0228 
0229         // Element access
0230         BOOST_UBLAS_INLINE
0231         const_reference operator () (size_type i, size_type j) const {
0232             BOOST_UBLAS_CHECK (i < size1_, bad_index ());
0233             BOOST_UBLAS_CHECK (j < size2_, bad_index ());
0234 #ifdef BOOST_UBLAS_OWN_BANDED
0235             const size_type k = (std::max) (i, j);
0236             const size_type l = lower_ + j - i;
0237             if (k < (std::max) (size1_, size2_) && // TODO: probably use BOOST_UBLAS_CHECK here instead of if
0238                 l < lower_ + 1 + upper_)
0239                 return data () [layout_type::element (k, (std::max) (size1_, size2_),
0240                                                        l, lower_ + 1 + upper_)];
0241 #elif BOOST_UBLAS_LEGACY_BANDED // Prior to version: TODO: add version this is actually incorporated in
0242             const size_type k = j;
0243             const size_type l = upper_ + i - j;
0244             if (k < size2_ &&
0245                 l < lower_ + 1 + upper_)
0246                 return data () [layout_type::element (k, size2_,
0247                                                        l, lower_ + 1 + upper_)];
0248 #else  // New default
0249             // This is the netlib layout as described here: http://www.netlib.org/lapack/lug/node124.html
0250             if ( is_element_in_band( i, j) ) {
0251                 return data () [hidden::banded_indexing<orientation_category>::get_index(size1_, size2_, lower_, upper_, i, j)];
0252             }
0253 #endif
0254             return zero_;
0255         }
0256 
0257         BOOST_UBLAS_INLINE
0258         reference at_element (size_type i, size_type j) {
0259             BOOST_UBLAS_CHECK (i < size1_, bad_index ());
0260             BOOST_UBLAS_CHECK (j < size2_, bad_index ());
0261 #ifdef BOOST_UBLAS_OWN_BANDED
0262             const size_type k = (std::max) (i, j);
0263             const size_type l = lower_ + j - i; // TODO: Don't we need an if or BOOST_UBLAS_CHECK HERE?
0264             return data () [layout_type::element (k, (std::max) (size1_, size2_),
0265                                                    l, lower_ + 1 + upper_)];
0266 #elif BOOST_UBLAS_LEGACY_BANDED // Prior to version: TODO: add version this is actually incorporated in
0267             const size_type k = j;
0268             const size_type l = upper_ + i - j;
0269             if (! (k < size2_ &&
0270                    l < lower_ + 1 + upper_) ) {
0271                 bad_index ().raise ();
0272                 // NEVER reached
0273             }
0274             return data () [layout_type::element (k, size2_,
0275                                                        l, lower_ + 1 + upper_)];
0276 #else
0277             // This is the netlib layout as described here: http://www.netlib.org/lapack/lug/node124.html
0278             BOOST_UBLAS_CHECK(is_element_in_band( i, j) , bad_index());
0279             return data () [hidden::banded_indexing<orientation_category>::get_index(size1_, size2_, lower_, upper_, i, j)];
0280 #endif
0281         }
0282         BOOST_UBLAS_INLINE
0283         reference operator () (size_type i, size_type j) {
0284             BOOST_UBLAS_CHECK (i < size1_, bad_index ());
0285             BOOST_UBLAS_CHECK (j < size2_, bad_index ());
0286 #ifdef BOOST_UBLAS_OWN_BANDED
0287             const size_type k = (std::max) (i, j);
0288             const size_type l = lower_ + j - i;
0289             if (! (k < (std::max) (size1_, size2_) && // TODO: probably use BOOST_UBLAS_CHECK here instead of if
0290                   l < lower_ + 1 + upper_) ) {
0291                 bad_index ().raise ();
0292                 // NEVER reached
0293             }
0294             return data () [layout_type::element (k, (std::max) (size1_, size2_),
0295                                                        l, lower_ + 1 + upper_)];
0296 #elif BOOST_UBLAS_LEGACY_BANDED // Prior to version: TODO: add version this is actually incorporated in
0297             const size_type k = j;
0298             const size_type l = upper_ + i - j;
0299             if (! (k < size2_ &&
0300                    l < lower_ + 1 + upper_) ) {
0301                 bad_index ().raise ();
0302                 // NEVER reached
0303             }
0304             return data () [layout_type::element (k, size2_,
0305                                                        l, lower_ + 1 + upper_)];
0306 #else
0307             // This is the netlib layout as described here: http://www.netlib.org/lapack/lug/node124.html
0308             BOOST_UBLAS_CHECK( is_element_in_band( i, j) , bad_index());
0309             return data () [hidden::banded_indexing<orientation_category>::get_index(size1_, size2_, lower_, upper_, i, j)];
0310 #endif
0311 
0312         }
0313 
0314         // Element assignment
0315         BOOST_UBLAS_INLINE
0316         reference insert_element (size_type i, size_type j, const_reference t) {
0317             return (operator () (i, j) = t);
0318         }
0319         BOOST_UBLAS_INLINE
0320         void erase_element (size_type i, size_type j) {
0321             operator () (i, j) = value_type/*zero*/();
0322         }
0323 
0324         // Zeroing
0325         BOOST_UBLAS_INLINE
0326         void clear () {
0327             std::fill (data ().begin (), data ().end (), value_type/*zero*/());
0328         }
0329 
0330         // Assignment
0331         BOOST_UBLAS_INLINE
0332         banded_matrix &operator = (const banded_matrix &m) {
0333             size1_ = m.size1_;
0334             size2_ = m.size2_;
0335             lower_ = m.lower_;
0336             upper_ = m.upper_;
0337             data () = m.data ();
0338             return *this;
0339         }
0340         BOOST_UBLAS_INLINE
0341         banded_matrix &assign_temporary (banded_matrix &m) {
0342             swap (m);
0343             return *this;
0344         }
0345         template<class AE>
0346         BOOST_UBLAS_INLINE
0347         banded_matrix &operator = (const matrix_expression<AE> &ae) {
0348             self_type temporary (ae, lower_, upper_);
0349             return assign_temporary (temporary);
0350         }
0351         template<class AE>
0352         BOOST_UBLAS_INLINE
0353         banded_matrix &assign (const matrix_expression<AE> &ae) {
0354             matrix_assign<scalar_assign> (*this, ae);
0355             return *this;
0356         }
0357         template<class AE>
0358         BOOST_UBLAS_INLINE
0359         banded_matrix& operator += (const matrix_expression<AE> &ae) {
0360             self_type temporary (*this + ae, lower_, upper_);
0361             return assign_temporary (temporary);
0362         }
0363         template<class AE>
0364         BOOST_UBLAS_INLINE
0365         banded_matrix &plus_assign (const matrix_expression<AE> &ae) {
0366             matrix_assign<scalar_plus_assign> (*this, ae);
0367             return *this;
0368         }
0369         template<class AE>
0370         BOOST_UBLAS_INLINE
0371         banded_matrix& operator -= (const matrix_expression<AE> &ae) {
0372             self_type temporary (*this - ae, lower_, upper_);
0373             return assign_temporary (temporary);
0374         }
0375         template<class AE>
0376         BOOST_UBLAS_INLINE
0377         banded_matrix &minus_assign (const matrix_expression<AE> &ae) {
0378             matrix_assign<scalar_minus_assign> (*this, ae);
0379             return *this;
0380         }
0381         template<class AT>
0382         BOOST_UBLAS_INLINE
0383         banded_matrix& operator *= (const AT &at) {
0384             matrix_assign_scalar<scalar_multiplies_assign> (*this, at);
0385             return *this;
0386         }
0387         template<class AT>
0388         BOOST_UBLAS_INLINE
0389         banded_matrix& operator /= (const AT &at) {
0390             matrix_assign_scalar<scalar_divides_assign> (*this, at);
0391             return *this;
0392         }
0393 
0394         // Swapping
0395         BOOST_UBLAS_INLINE
0396         void swap (banded_matrix &m) {
0397             if (this != &m) {
0398                 std::swap (size1_, m.size1_);
0399                 std::swap (size2_, m.size2_);
0400                 std::swap (lower_, m.lower_);
0401                 std::swap (upper_, m.upper_);
0402                 data ().swap (m.data ());
0403             }
0404         }
0405         BOOST_UBLAS_INLINE
0406         friend void swap (banded_matrix &m1, banded_matrix &m2) {
0407             m1.swap (m2);
0408         }
0409 
0410         // Iterator types
0411 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
0412         typedef indexed_iterator1<self_type, packed_random_access_iterator_tag> iterator1;
0413         typedef indexed_iterator2<self_type, packed_random_access_iterator_tag> iterator2;
0414         typedef indexed_const_iterator1<self_type, packed_random_access_iterator_tag> const_iterator1;
0415         typedef indexed_const_iterator2<self_type, packed_random_access_iterator_tag> const_iterator2;
0416 #else
0417         class const_iterator1;
0418         class iterator1;
0419         class const_iterator2;
0420         class iterator2;
0421 #endif
0422         typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
0423         typedef reverse_iterator_base1<iterator1> reverse_iterator1;
0424         typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
0425         typedef reverse_iterator_base2<iterator2> reverse_iterator2;
0426 
0427         // Element lookup
0428         BOOST_UBLAS_INLINE
0429         const_iterator1 find1 (int rank, size_type i, size_type j) const {
0430             if (rank == 1) {
0431                 size_type lower_i = (std::max) (difference_type (j - upper_), difference_type (0));
0432                 i = (std::max) (i, lower_i);
0433                 size_type upper_i = (std::min) (j + 1 + lower_, size1_);
0434                 i = (std::min) (i, upper_i);
0435             }
0436             return const_iterator1 (*this, i, j);
0437         }
0438         BOOST_UBLAS_INLINE
0439         iterator1 find1 (int rank, size_type i, size_type j) {
0440             if (rank == 1) {
0441                 size_type lower_i = (std::max) (difference_type (j - upper_), difference_type (0));
0442                 i = (std::max) (i, lower_i);
0443                 size_type upper_i = (std::min) (j + 1 + lower_, size1_);
0444                 i = (std::min) (i, upper_i);
0445             }
0446             return iterator1 (*this, i, j);
0447         }
0448         BOOST_UBLAS_INLINE
0449         const_iterator2 find2 (int rank, size_type i, size_type j) const {
0450             if (rank == 1) {
0451                 size_type lower_j = (std::max) (difference_type (i - lower_), difference_type (0));
0452                 j = (std::max) (j, lower_j);
0453                 size_type upper_j = (std::min) (i + 1 + upper_, size2_);
0454                 j = (std::min) (j, upper_j);
0455             }
0456             return const_iterator2 (*this, i, j);
0457         }
0458         BOOST_UBLAS_INLINE
0459         iterator2 find2 (int rank, size_type i, size_type j) {
0460             if (rank == 1) {
0461                 size_type lower_j = (std::max) (difference_type (i - lower_), difference_type (0));
0462                 j = (std::max) (j, lower_j);
0463                 size_type upper_j = (std::min) (i + 1 + upper_, size2_);
0464                 j = (std::min) (j, upper_j);
0465             }
0466             return iterator2 (*this, i, j);
0467         }
0468 
0469         // Iterators simply are indices.
0470 
0471 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
0472         class const_iterator1:
0473             public container_const_reference<banded_matrix>,
0474             public random_access_iterator_base<packed_random_access_iterator_tag,
0475                                                const_iterator1, value_type> {
0476         public:
0477             typedef typename banded_matrix::value_type value_type;
0478             typedef typename banded_matrix::difference_type difference_type;
0479             typedef typename banded_matrix::const_reference reference;
0480             typedef const typename banded_matrix::pointer pointer;
0481 
0482             typedef const_iterator2 dual_iterator_type;
0483             typedef const_reverse_iterator2 dual_reverse_iterator_type;
0484 
0485             // Construction and destruction
0486             BOOST_UBLAS_INLINE
0487             const_iterator1 ():
0488                 container_const_reference<self_type> (), it1_ (), it2_ () {}
0489             BOOST_UBLAS_INLINE
0490             const_iterator1 (const self_type &m, size_type it1, size_type it2):
0491                 container_const_reference<self_type> (m), it1_ (it1), it2_ (it2) {}
0492             BOOST_UBLAS_INLINE
0493             const_iterator1 (const iterator1 &it):
0494                 container_const_reference<self_type> (it ()), it1_ (it.it1_), it2_ (it.it2_) {}
0495 
0496             // Arithmetic
0497             BOOST_UBLAS_INLINE
0498             const_iterator1 &operator ++ () {
0499                 ++ it1_;
0500                 return *this;
0501             }
0502             BOOST_UBLAS_INLINE
0503             const_iterator1 &operator -- () {
0504                 -- it1_;
0505                 return *this;
0506             }
0507             BOOST_UBLAS_INLINE
0508             const_iterator1 &operator += (difference_type n) {
0509                 it1_ += n;
0510                 return *this;
0511             }
0512             BOOST_UBLAS_INLINE
0513             const_iterator1 &operator -= (difference_type n) {
0514                 it1_ -= n;
0515                 return *this;
0516             }
0517             BOOST_UBLAS_INLINE
0518             difference_type operator - (const const_iterator1 &it) const {
0519                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
0520                 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
0521                 return it1_ - it.it1_;
0522             }
0523 
0524             // Dereference
0525             BOOST_UBLAS_INLINE
0526             const_reference operator * () const {
0527                 return (*this) () (it1_, it2_);
0528             }
0529             BOOST_UBLAS_INLINE
0530             const_reference operator [] (difference_type n) const {
0531                 return *(*this + n);
0532             }
0533 
0534 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
0535             BOOST_UBLAS_INLINE
0536 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
0537             typename self_type::
0538 #endif
0539             const_iterator2 begin () const {
0540                 return (*this) ().find2 (1, it1_, 0);
0541             }
0542             BOOST_UBLAS_INLINE
0543 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
0544             typename self_type::
0545 #endif
0546             const_iterator2 cbegin () const {
0547                 return begin ();
0548             }
0549             BOOST_UBLAS_INLINE
0550 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
0551             typename self_type::
0552 #endif
0553             const_iterator2 end () const {
0554                 return (*this) ().find2 (1, it1_, (*this) ().size2 ());
0555             }
0556             BOOST_UBLAS_INLINE
0557 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
0558             typename self_type::
0559 #endif
0560             const_iterator2 cend () const {
0561                 return end ();
0562             }
0563             BOOST_UBLAS_INLINE
0564 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
0565             typename self_type::
0566 #endif
0567             const_reverse_iterator2 rbegin () const {
0568                 return const_reverse_iterator2 (end ());
0569             }
0570             BOOST_UBLAS_INLINE
0571 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
0572             typename self_type::
0573 #endif
0574             const_reverse_iterator2 crbegin () const {
0575                 return rbegin ();
0576             }
0577             BOOST_UBLAS_INLINE
0578 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
0579             typename self_type::
0580 #endif
0581             const_reverse_iterator2 rend () const {
0582                 return const_reverse_iterator2 (begin ());
0583             }
0584             BOOST_UBLAS_INLINE
0585 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
0586             typename self_type::
0587 #endif
0588             const_reverse_iterator2 crend () const {
0589                 return rend ();
0590             }
0591 #endif
0592 
0593             // Indices
0594             BOOST_UBLAS_INLINE
0595             size_type index1 () const {
0596                 return it1_;
0597             }
0598             BOOST_UBLAS_INLINE
0599             size_type index2 () const {
0600                 return it2_;
0601             }
0602 
0603             // Assignment
0604             BOOST_UBLAS_INLINE
0605             const_iterator1 &operator = (const const_iterator1 &it) {
0606                 container_const_reference<self_type>::assign (&it ());
0607                 it1_ = it.it1_;
0608                 it2_ = it.it2_;
0609                 return *this;
0610             }
0611 
0612             // Comparison
0613             BOOST_UBLAS_INLINE
0614             bool operator == (const const_iterator1 &it) const {
0615                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
0616                 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
0617                 return it1_ == it.it1_;
0618             }
0619             BOOST_UBLAS_INLINE
0620             bool operator < (const const_iterator1 &it) const {
0621                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
0622                 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
0623                 return it1_ < it.it1_;
0624             }
0625 
0626         private:
0627             size_type it1_;
0628             size_type it2_;
0629         };
0630 #endif
0631 
0632         BOOST_UBLAS_INLINE
0633         const_iterator1 begin1 () const {
0634             return find1 (0, 0, 0);
0635         }
0636         BOOST_UBLAS_INLINE
0637         const_iterator1 cbegin1 () const {
0638             return begin1 ();
0639         }
0640         BOOST_UBLAS_INLINE
0641         const_iterator1 end1 () const {
0642             return find1 (0, size1_, 0);
0643         }
0644         BOOST_UBLAS_INLINE
0645         const_iterator1 cend1 () const {
0646             return end1 ();
0647         }
0648 
0649 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
0650         class iterator1:
0651             public container_reference<banded_matrix>,
0652             public random_access_iterator_base<packed_random_access_iterator_tag,
0653                                                iterator1, value_type> {
0654         public:
0655             typedef typename banded_matrix::value_type value_type;
0656             typedef typename banded_matrix::difference_type difference_type;
0657             typedef typename banded_matrix::reference reference;
0658             typedef typename banded_matrix::pointer pointer;
0659 
0660             typedef iterator2 dual_iterator_type;
0661             typedef reverse_iterator2 dual_reverse_iterator_type;
0662 
0663             // Construction and destruction
0664             BOOST_UBLAS_INLINE
0665             iterator1 ():
0666                 container_reference<self_type> (), it1_ (), it2_ () {}
0667             BOOST_UBLAS_INLINE
0668             iterator1 (self_type &m, size_type it1, size_type it2):
0669                 container_reference<self_type> (m), it1_ (it1), it2_ (it2) {}
0670 
0671             // Arithmetic
0672             BOOST_UBLAS_INLINE
0673             iterator1 &operator ++ () {
0674                 ++ it1_;
0675                 return *this;
0676             }
0677             BOOST_UBLAS_INLINE
0678             iterator1 &operator -- () {
0679                 -- it1_;
0680                 return *this;
0681             }
0682             BOOST_UBLAS_INLINE
0683             iterator1 &operator += (difference_type n) {
0684                 it1_ += n;
0685                 return *this;
0686             }
0687             BOOST_UBLAS_INLINE
0688             iterator1 &operator -= (difference_type n) {
0689                 it1_ -= n;
0690                 return *this;
0691             }
0692             BOOST_UBLAS_INLINE
0693             difference_type operator - (const iterator1 &it) const {
0694                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
0695                 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
0696                 return it1_ - it.it1_;
0697             }
0698 
0699             // Dereference
0700             BOOST_UBLAS_INLINE
0701             reference operator * () const {
0702                 return (*this) ().at_element (it1_, it2_);
0703             }
0704             BOOST_UBLAS_INLINE
0705             reference operator [] (difference_type n) const {
0706                 return *(*this + n);
0707             }
0708 
0709 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
0710             BOOST_UBLAS_INLINE
0711 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
0712             typename self_type::
0713 #endif
0714             iterator2 begin () const {
0715                 return (*this) ().find2 (1, it1_, 0);
0716             }
0717             BOOST_UBLAS_INLINE
0718 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
0719             typename self_type::
0720 #endif
0721             iterator2 end () const {
0722                 return (*this) ().find2 (1, it1_, (*this) ().size2 ());
0723             }
0724 
0725             BOOST_UBLAS_INLINE
0726 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
0727             typename self_type::
0728 #endif
0729             reverse_iterator2 rbegin () const {
0730                 return reverse_iterator2 (end ());
0731             }
0732             BOOST_UBLAS_INLINE
0733 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
0734             typename self_type::
0735 #endif
0736             reverse_iterator2 rend () const {
0737                 return reverse_iterator2 (begin ());
0738             }
0739 #endif
0740 
0741             // Indices
0742             BOOST_UBLAS_INLINE
0743             size_type index1 () const {
0744                 return it1_;
0745             }
0746             BOOST_UBLAS_INLINE
0747             size_type index2 () const {
0748                 return it2_;
0749             }
0750 
0751             // Assignment
0752             BOOST_UBLAS_INLINE
0753             iterator1 &operator = (const iterator1 &it) {
0754                 container_reference<self_type>::assign (&it ());
0755                 it1_ = it.it1_;
0756                 it2_ = it.it2_;
0757                 return *this;
0758             }
0759 
0760             // Comparison
0761             BOOST_UBLAS_INLINE
0762             bool operator == (const iterator1 &it) const {
0763                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
0764                 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
0765                 return it1_ == it.it1_;
0766             }
0767             BOOST_UBLAS_INLINE
0768             bool operator < (const iterator1 &it) const {
0769                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
0770                 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
0771                 return it1_ < it.it1_;
0772             }
0773 
0774         private:
0775             size_type it1_;
0776             size_type it2_;
0777 
0778             friend class const_iterator1;
0779         };
0780 #endif
0781 
0782         BOOST_UBLAS_INLINE
0783         iterator1 begin1 () {
0784             return find1 (0, 0, 0);
0785         }
0786         BOOST_UBLAS_INLINE
0787         iterator1 end1 () {
0788             return find1 (0, size1_, 0);
0789         }
0790 
0791 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
0792         class const_iterator2:
0793             public container_const_reference<banded_matrix>,
0794             public random_access_iterator_base<packed_random_access_iterator_tag,
0795                                                const_iterator2, value_type> {
0796         public:
0797             typedef typename banded_matrix::value_type value_type;
0798             typedef typename banded_matrix::difference_type difference_type;
0799             typedef typename banded_matrix::const_reference reference;
0800             typedef const typename banded_matrix::pointer pointer;
0801 
0802             typedef const_iterator1 dual_iterator_type;
0803             typedef const_reverse_iterator1 dual_reverse_iterator_type;
0804 
0805             // Construction and destruction
0806             BOOST_UBLAS_INLINE
0807             const_iterator2 ():
0808                 container_const_reference<self_type> (), it1_ (), it2_ () {}
0809             BOOST_UBLAS_INLINE
0810             const_iterator2 (const self_type &m, size_type it1, size_type it2):
0811                 container_const_reference<self_type> (m), it1_ (it1), it2_ (it2) {}
0812             BOOST_UBLAS_INLINE
0813             const_iterator2 (const iterator2 &it):
0814                 container_const_reference<self_type> (it ()), it1_ (it.it1_), it2_ (it.it2_) {}
0815 
0816             // Arithmetic
0817             BOOST_UBLAS_INLINE
0818             const_iterator2 &operator ++ () {
0819                 ++ it2_;
0820                 return *this;
0821             }
0822             BOOST_UBLAS_INLINE
0823             const_iterator2 &operator -- () {
0824                 -- it2_;
0825                 return *this;
0826             }
0827             BOOST_UBLAS_INLINE
0828             const_iterator2 &operator += (difference_type n) {
0829                 it2_ += n;
0830                 return *this;
0831             }
0832             BOOST_UBLAS_INLINE
0833             const_iterator2 &operator -= (difference_type n) {
0834                 it2_ -= n;
0835                 return *this;
0836             }
0837             BOOST_UBLAS_INLINE
0838             difference_type operator - (const const_iterator2 &it) const {
0839                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
0840                 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
0841                 return it2_ - it.it2_;
0842             }
0843 
0844             // Dereference
0845             BOOST_UBLAS_INLINE
0846             const_reference operator * () const {
0847                 return (*this) () (it1_, it2_);
0848             }
0849             BOOST_UBLAS_INLINE
0850             const_reference operator [] (difference_type n) const {
0851                 return *(*this + n);
0852             }
0853 
0854 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
0855             BOOST_UBLAS_INLINE
0856 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
0857             typename self_type::
0858 #endif
0859             const_iterator1 begin () const {
0860                 return (*this) ().find1 (1, 0, it2_);
0861             }
0862             BOOST_UBLAS_INLINE
0863 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
0864             typename self_type::
0865 #endif
0866             const_iterator1 cbegin () const {
0867                 return begin ();
0868             }
0869             BOOST_UBLAS_INLINE
0870 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
0871             typename self_type::
0872 #endif
0873             const_iterator1 end () const {
0874                 return (*this) ().find1 (1, (*this) ().size1 (), it2_);
0875             }
0876             BOOST_UBLAS_INLINE
0877 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
0878             typename self_type::
0879 #endif
0880             const_iterator1 cend () const {
0881                 return end();
0882             }
0883 
0884             BOOST_UBLAS_INLINE
0885 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
0886             typename self_type::
0887 #endif
0888             const_reverse_iterator1 rbegin () const {
0889                 return const_reverse_iterator1 (end ());
0890             }
0891             BOOST_UBLAS_INLINE
0892 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
0893             typename self_type::
0894 #endif
0895             const_reverse_iterator1 crbegin () const {
0896                 return rbegin ();
0897             }
0898             BOOST_UBLAS_INLINE
0899 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
0900             typename self_type::
0901 #endif
0902             const_reverse_iterator1 rend () const {
0903                 return const_reverse_iterator1 (begin ());
0904             }
0905             BOOST_UBLAS_INLINE
0906 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
0907             typename self_type::
0908 #endif
0909             const_reverse_iterator1 crend () const {
0910                 return rend ();
0911             }
0912 #endif
0913 
0914             // Indices
0915             BOOST_UBLAS_INLINE
0916             size_type index1 () const {
0917                 return it1_;
0918             }
0919             BOOST_UBLAS_INLINE
0920             size_type index2 () const {
0921                 return it2_;
0922             }
0923 
0924             // Assignment
0925             BOOST_UBLAS_INLINE
0926             const_iterator2 &operator = (const const_iterator2 &it) {
0927                 container_const_reference<self_type>::assign (&it ());
0928                 it1_ = it.it1_;
0929                 it2_ = it.it2_;
0930                 return *this;
0931             }
0932 
0933             // Comparison
0934             BOOST_UBLAS_INLINE
0935             bool operator == (const const_iterator2 &it) const {
0936                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
0937                 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
0938                 return it2_ == it.it2_;
0939             }
0940             BOOST_UBLAS_INLINE
0941             bool operator < (const const_iterator2 &it) const {
0942                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
0943                 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
0944                 return it2_ < it.it2_;
0945             }
0946 
0947         private:
0948             size_type it1_;
0949             size_type it2_;
0950         };
0951 #endif
0952 
0953         BOOST_UBLAS_INLINE
0954         const_iterator2 begin2 () const {
0955             return find2 (0, 0, 0);
0956         }
0957         BOOST_UBLAS_INLINE
0958         const_iterator2 cbegin2 () const {
0959             return begin2 ();
0960         }
0961         BOOST_UBLAS_INLINE
0962         const_iterator2 end2 () const {
0963             return find2 (0, 0, size2_);
0964         }
0965         BOOST_UBLAS_INLINE
0966         const_iterator2 cend2 () const {
0967             return end2 ();
0968         }
0969 
0970 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
0971         class iterator2:
0972             public container_reference<banded_matrix>,
0973             public random_access_iterator_base<packed_random_access_iterator_tag,
0974                                                iterator2, value_type> {
0975         public:
0976             typedef typename banded_matrix::value_type value_type;
0977             typedef typename banded_matrix::difference_type difference_type;
0978             typedef typename banded_matrix::reference reference;
0979             typedef typename banded_matrix::pointer pointer;
0980 
0981             typedef iterator1 dual_iterator_type;
0982             typedef reverse_iterator1 dual_reverse_iterator_type;
0983 
0984             // Construction and destruction
0985             BOOST_UBLAS_INLINE
0986             iterator2 ():
0987                 container_reference<self_type> (), it1_ (), it2_ () {}
0988             BOOST_UBLAS_INLINE
0989             iterator2 (self_type &m, size_type it1, size_type it2):
0990                 container_reference<self_type> (m), it1_ (it1), it2_ (it2) {}
0991 
0992             // Arithmetic
0993             BOOST_UBLAS_INLINE
0994             iterator2 &operator ++ () {
0995                 ++ it2_;
0996                 return *this;
0997             }
0998             BOOST_UBLAS_INLINE
0999             iterator2 &operator -- () {
1000                 -- it2_;
1001                 return *this;
1002             }
1003             BOOST_UBLAS_INLINE
1004             iterator2 &operator += (difference_type n) {
1005                 it2_ += n;
1006                 return *this;
1007             }
1008             BOOST_UBLAS_INLINE
1009             iterator2 &operator -= (difference_type n) {
1010                 it2_ -= n;
1011                 return *this;
1012             }
1013             BOOST_UBLAS_INLINE
1014             difference_type operator - (const iterator2 &it) const {
1015                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1016                 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
1017                 return it2_ - it.it2_;
1018             }
1019 
1020             // Dereference
1021             BOOST_UBLAS_INLINE
1022             reference operator * () const {
1023                 return (*this) ().at_element (it1_, it2_);
1024             }
1025             BOOST_UBLAS_INLINE
1026             reference operator [] (difference_type n) const {
1027                 return *(*this + n);
1028             }
1029 
1030 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1031             BOOST_UBLAS_INLINE
1032 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1033             typename self_type::
1034 #endif
1035             iterator1 begin () const {
1036                 return (*this) ().find1 (1, 0, it2_);
1037             }
1038             BOOST_UBLAS_INLINE
1039 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1040             typename self_type::
1041 #endif
1042             iterator1 end () const {
1043                 return (*this) ().find1 (1, (*this) ().size1 (), it2_);
1044             }
1045             BOOST_UBLAS_INLINE
1046 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1047             typename self_type::
1048 #endif
1049             reverse_iterator1 rbegin () const {
1050                 return reverse_iterator1 (end ());
1051             }
1052             BOOST_UBLAS_INLINE
1053 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1054             typename self_type::
1055 #endif
1056             reverse_iterator1 rend () const {
1057                 return reverse_iterator1 (begin ());
1058             }
1059 #endif
1060 
1061             // Indices
1062             BOOST_UBLAS_INLINE
1063             size_type index1 () const {
1064                 return it1_;
1065             }
1066             BOOST_UBLAS_INLINE
1067             size_type index2 () const {
1068                 return it2_;
1069             }
1070 
1071             // Assignment
1072             BOOST_UBLAS_INLINE
1073             iterator2 &operator = (const iterator2 &it) {
1074                 container_reference<self_type>::assign (&it ());
1075                 it1_ = it.it1_;
1076                 it2_ = it.it2_;
1077                 return *this;
1078             }
1079 
1080             // Comparison
1081             BOOST_UBLAS_INLINE
1082             bool operator == (const iterator2 &it) const {
1083                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1084                 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
1085                 return it2_ == it.it2_;
1086             }
1087             BOOST_UBLAS_INLINE
1088             bool operator < (const iterator2 &it) const {
1089                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1090                 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
1091                 return it2_ < it.it2_;
1092             }
1093 
1094         private:
1095             size_type it1_;
1096             size_type it2_;
1097 
1098             friend class const_iterator2;
1099         };
1100 #endif
1101 
1102         BOOST_UBLAS_INLINE
1103         iterator2 begin2 () {
1104             return find2 (0, 0, 0);
1105         }
1106         BOOST_UBLAS_INLINE
1107         iterator2 end2 () {
1108             return find2 (0, 0, size2_);
1109         }
1110 
1111         // Reverse iterators
1112 
1113         BOOST_UBLAS_INLINE
1114         const_reverse_iterator1 rbegin1 () const {
1115             return const_reverse_iterator1 (end1 ());
1116         }
1117         BOOST_UBLAS_INLINE
1118         const_reverse_iterator1 crbegin1 () const {
1119             return rbegin1 ();
1120         }
1121         BOOST_UBLAS_INLINE
1122         const_reverse_iterator1 rend1 () const {
1123             return const_reverse_iterator1 (begin1 ());
1124         }
1125         BOOST_UBLAS_INLINE
1126         const_reverse_iterator1 crend1 () const {
1127             return rend1 ();
1128         }
1129 
1130         BOOST_UBLAS_INLINE
1131         reverse_iterator1 rbegin1 () {
1132             return reverse_iterator1 (end1 ());
1133         }
1134         BOOST_UBLAS_INLINE
1135         reverse_iterator1 rend1 () {
1136             return reverse_iterator1 (begin1 ());
1137         }
1138 
1139         BOOST_UBLAS_INLINE
1140         const_reverse_iterator2 rbegin2 () const {
1141             return const_reverse_iterator2 (end2 ());
1142         }
1143         BOOST_UBLAS_INLINE
1144         const_reverse_iterator2 crbegin2 () const {
1145             return rbegin2 ();
1146         }
1147         BOOST_UBLAS_INLINE
1148         const_reverse_iterator2 rend2 () const {
1149             return const_reverse_iterator2 (begin2 ());
1150         }
1151         BOOST_UBLAS_INLINE
1152         const_reverse_iterator2 crend2 () const {
1153             return rend2 ();
1154         }
1155 
1156         BOOST_UBLAS_INLINE
1157         reverse_iterator2 rbegin2 () {
1158             return reverse_iterator2 (end2 ());
1159         }
1160         BOOST_UBLAS_INLINE
1161         reverse_iterator2 rend2 () {
1162             return reverse_iterator2 (begin2 ());
1163         }
1164 
1165     private:
1166         size_type size1_;
1167         size_type size2_;
1168         size_type lower_;
1169         size_type upper_;
1170         array_type data_;
1171         typedef const value_type const_value_type;
1172         static const_value_type zero_;
1173     };
1174 
1175     template<class T, class L, class A>
1176     typename banded_matrix<T, L, A>::const_value_type banded_matrix<T, L, A>::zero_ = value_type/*zero*/();
1177 
1178 
1179     /** \brief A diagonal matrix of values of type \c T, which is a specialization of a banded matrix
1180      *
1181      * For a \f$(m\times m)\f$-dimensional diagonal matrix, \f$0 \leq i < m\f$ and \f$0 \leq j < m\f$, 
1182      * if \f$i\neq j\f$ then \f$b_{i,j}=0\f$. The default storage for diagonal matrices is packed. 
1183      * Orientation and storage can also be specified. Default is \c row major \c unbounded_array. 
1184      *
1185      * As a specialization of a banded matrix, the constructor of the diagonal matrix creates 
1186      * a banded matrix with 0 upper and lower diagonals around the main diagonal and the matrix is 
1187      * obviously a square matrix. Operations are optimized based on these 2 assumptions. It is 
1188      * \b not required by the storage to initialize elements of the matrix.  
1189      *
1190      * \tparam T the type of object stored in the matrix (like double, float, complex, etc...)
1191      * \tparam L the storage organization. It can be either \c row_major or \c column_major. Default is \c row_major
1192      * \tparam A the type of Storage array. Default is \c unbounded_array
1193      */
1194     template<class T, class L, class A>
1195     class diagonal_matrix:
1196         public banded_matrix<T, L, A> {
1197     public:
1198         typedef typename A::size_type size_type;
1199         typedef banded_matrix<T, L, A> matrix_type;
1200         typedef A array_type;
1201 
1202         // Construction and destruction
1203         BOOST_UBLAS_INLINE
1204         diagonal_matrix ():
1205             matrix_type () {}
1206         BOOST_UBLAS_INLINE
1207         diagonal_matrix (size_type size):
1208             matrix_type (size, size) {}
1209         BOOST_UBLAS_INLINE
1210         diagonal_matrix (size_type size, const array_type& data):
1211             matrix_type (size, size, 0, 0, data) {}
1212         BOOST_UBLAS_INLINE
1213         diagonal_matrix (size_type size1, size_type size2):
1214             matrix_type (size1, size2) {}
1215         template<class AE>
1216         BOOST_UBLAS_INLINE
1217         diagonal_matrix (const matrix_expression<AE> &ae):
1218             matrix_type (ae) {}
1219         BOOST_UBLAS_INLINE
1220         ~diagonal_matrix () {}
1221 
1222         // Assignment
1223         BOOST_UBLAS_INLINE
1224         diagonal_matrix &operator = (const diagonal_matrix &m) {
1225             matrix_type::operator = (m);
1226             return *this;
1227         }
1228         template<class AE>
1229         BOOST_UBLAS_INLINE
1230         diagonal_matrix &operator = (const matrix_expression<AE> &ae) {
1231             matrix_type::operator = (ae);
1232             return *this;
1233         }
1234     };
1235 
1236     /** \brief A banded matrix adaptator: convert a any matrix into a banded matrix expression
1237      *
1238      * For a \f$(m\times n)\f$-dimensional matrix, the \c banded_adaptor will provide a banded matrix
1239      * with \f$l\f$ lower and \f$u\f$ upper diagonals and \f$0 \leq i < m\f$ and \f$0 \leq j < n\f$,
1240      * if \f$i>j+l\f$ or \f$i<j-u\f$ then \f$b_{i,j}=0\f$. 
1241      *
1242      * Storage and location are based on those of the underlying matrix. This is important because
1243      * a \c banded_adaptor does not copy the matrix data to a new place. Therefore, modifying values
1244      * in a \c banded_adaptor matrix will also modify the underlying matrix too.
1245      *
1246      * \tparam M the type of matrix used to generate a banded matrix
1247      */
1248     template<class M>
1249     class banded_adaptor:
1250         public matrix_expression<banded_adaptor<M> > {
1251 
1252         typedef banded_adaptor<M> self_type;
1253 
1254     public:
1255 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
1256         using matrix_expression<self_type>::operator ();
1257 #endif
1258         typedef const M const_matrix_type;
1259         typedef M matrix_type;
1260         typedef typename M::size_type size_type;
1261         typedef typename M::difference_type difference_type;
1262         typedef typename M::value_type value_type;
1263         typedef typename M::const_reference const_reference;
1264         typedef typename boost::mpl::if_<boost::is_const<M>,
1265                                           typename M::const_reference,
1266                                           typename M::reference>::type reference;
1267         typedef typename boost::mpl::if_<boost::is_const<M>,
1268                                           typename M::const_closure_type,
1269                                           typename M::closure_type>::type matrix_closure_type;
1270         typedef const self_type const_closure_type;
1271         typedef self_type closure_type;
1272         // Replaced by _temporary_traits to avoid type requirements on M
1273         //typedef typename M::vector_temporary_type vector_temporary_type;
1274         //typedef typename M::matrix_temporary_type matrix_temporary_type;
1275         typedef typename storage_restrict_traits<typename M::storage_category,
1276                                                  packed_proxy_tag>::storage_category storage_category;
1277         typedef typename M::orientation_category orientation_category;
1278 
1279         // Construction and destruction
1280         BOOST_UBLAS_INLINE
1281         banded_adaptor (matrix_type &data, size_type lower = 0, size_type upper = 0):
1282             matrix_expression<self_type> (),
1283             data_ (data), lower_ (lower), upper_ (upper) {}
1284         BOOST_UBLAS_INLINE
1285         banded_adaptor (const banded_adaptor &m):
1286             matrix_expression<self_type> (),
1287             data_ (m.data_), lower_ (m.lower_), upper_ (m.upper_) {}
1288 
1289         // Accessors
1290         BOOST_UBLAS_INLINE
1291         size_type size1 () const {
1292             return data_.size1 ();
1293         }
1294         BOOST_UBLAS_INLINE
1295         size_type size2 () const {
1296             return data_.size2 ();
1297         }
1298         BOOST_UBLAS_INLINE
1299         size_type lower () const {
1300             return lower_;
1301         }
1302         BOOST_UBLAS_INLINE
1303         size_type upper () const {
1304             return upper_;
1305         }
1306 
1307         // Storage accessors
1308         BOOST_UBLAS_INLINE
1309         const matrix_closure_type &data () const {
1310             return data_;
1311         }
1312         BOOST_UBLAS_INLINE
1313         matrix_closure_type &data () {
1314             return data_;
1315         }
1316 
1317 #if !defined (BOOST_UBLAS_OWN_BANDED)||(BOOST_UBLAS_LEGACY_BANDED)
1318         BOOST_UBLAS_INLINE
1319         bool is_element_in_band(size_type i, size_type j) const{
1320             //return (upper_+i >= j) && i <= std::min(size1() - 1, j + lower_); // We don't need to check if i is outside because it is checked anyway in the accessors.
1321             return (upper_+i >= j) && i <= ( j + lower_); // Essentially this band has "infinite" positive dimensions
1322         }
1323 #endif
1324 
1325         // Element access
1326 #ifndef BOOST_UBLAS_PROXY_CONST_MEMBER
1327         BOOST_UBLAS_INLINE
1328         const_reference operator () (size_type i, size_type j) const {
1329             BOOST_UBLAS_CHECK (i < size1 (), bad_index ());
1330             BOOST_UBLAS_CHECK (j < size2 (), bad_index ());
1331 #ifdef BOOST_UBLAS_OWN_BANDED
1332             size_type k = (std::max) (i, j);
1333             size_type l = lower_ + j - i;
1334             if (k < (std::max) (size1 (), size2 ()) &&
1335                 l < lower_ + 1 + upper_)
1336                 return data () (i, j);
1337 #elif BOOST_UBLAS_LEGACY_BANDED
1338             size_type k = j;
1339             size_type l = upper_ + i - j;
1340             if (k < size2 () &&
1341                 l < lower_ + 1 + upper_)
1342                 return data () (i, j);
1343 #else
1344             if (is_element_in_band( i, j))
1345                 return data () (i, j);
1346 #endif
1347             return zero_;
1348         }
1349         BOOST_UBLAS_INLINE
1350         reference operator () (size_type i, size_type j) {
1351             BOOST_UBLAS_CHECK (i < size1 (), bad_index ());
1352             BOOST_UBLAS_CHECK (j < size2 (), bad_index ());
1353 #ifdef BOOST_UBLAS_OWN_BANDED
1354             size_type k = (std::max) (i, j);
1355             size_type l = lower_ + j - i;
1356             if (k < (std::max) (size1 (), size2 ()) &&
1357                 l < lower_ + 1 + upper_)
1358                 return data () (i, j);
1359 #elif BOOST_UBLAS_LEGACY_BANDED
1360             size_type k = j;
1361             size_type l = upper_ + i - j;
1362             if (k < size2 () &&
1363                 l < lower_ + 1 + upper_)
1364                 return data () (i, j);
1365 #else
1366             if (is_element_in_band( i, j))
1367                 return data () (i, j);
1368 #endif
1369 #ifndef BOOST_UBLAS_REFERENCE_CONST_MEMBER
1370             bad_index ().raise ();
1371 #endif
1372             return const_cast<reference>(zero_);
1373         }
1374 #else
1375         BOOST_UBLAS_INLINE
1376         reference operator () (size_type i, size_type j) const {
1377             BOOST_UBLAS_CHECK (i < size1 (), bad_index ());
1378             BOOST_UBLAS_CHECK (j < size2 (), bad_index ());
1379 #ifdef BOOST_UBLAS_OWN_BANDED
1380             size_type k = (std::max) (i, j);
1381             size_type l = lower_ + j - i;
1382             if (k < (std::max) (size1 (), size2 ()) &&
1383                 l < lower_ + 1 + upper_)
1384                 return data () (i, j);
1385 #elif BOOST_UBLAS_LEGACY_BANDED
1386             size_type k = j;
1387             size_type l = upper_ + i - j;
1388             if (k < size2 () &&
1389                 l < lower_ + 1 + upper_)
1390                 return data () (i, j);
1391 #else
1392             if (is_element_in_band( i, j))
1393                 return data () (i, j);
1394 #endif
1395 #ifndef BOOST_UBLAS_REFERENCE_CONST_MEMBER
1396             bad_index ().raise ();
1397 #endif
1398             return const_cast<reference>(zero_);
1399         }
1400 #endif
1401 
1402         // Assignment
1403         BOOST_UBLAS_INLINE
1404         banded_adaptor &operator = (const banded_adaptor &m) {
1405             matrix_assign<scalar_assign> (*this, m);
1406             return *this;
1407         }
1408         BOOST_UBLAS_INLINE
1409         banded_adaptor &assign_temporary (banded_adaptor &m) {
1410             *this = m;
1411             return *this;
1412         }
1413         template<class AE>
1414         BOOST_UBLAS_INLINE
1415         banded_adaptor &operator = (const matrix_expression<AE> &ae) {
1416             matrix_assign<scalar_assign> (*this, matrix<value_type> (ae));
1417             return *this;
1418         }
1419         template<class AE>
1420         BOOST_UBLAS_INLINE
1421         banded_adaptor &assign (const matrix_expression<AE> &ae) {
1422             matrix_assign<scalar_assign> (*this, ae);
1423             return *this;
1424         }
1425         template<class AE>
1426         BOOST_UBLAS_INLINE
1427         banded_adaptor& operator += (const matrix_expression<AE> &ae) {
1428             matrix_assign<scalar_assign> (*this, matrix<value_type> (*this + ae));
1429             return *this;
1430         }
1431         template<class AE>
1432         BOOST_UBLAS_INLINE
1433         banded_adaptor &plus_assign (const matrix_expression<AE> &ae) {
1434             matrix_assign<scalar_plus_assign> (*this, ae);
1435             return *this;
1436         }
1437         template<class AE>
1438         BOOST_UBLAS_INLINE
1439         banded_adaptor& operator -= (const matrix_expression<AE> &ae) {
1440             matrix_assign<scalar_assign> (*this, matrix<value_type> (*this - ae));
1441             return *this;
1442         }
1443         template<class AE>
1444         BOOST_UBLAS_INLINE
1445         banded_adaptor &minus_assign (const matrix_expression<AE> &ae) {
1446             matrix_assign<scalar_minus_assign> (*this, ae);
1447             return *this;
1448         }
1449         template<class AT>
1450         BOOST_UBLAS_INLINE
1451         banded_adaptor& operator *= (const AT &at) {
1452             matrix_assign_scalar<scalar_multiplies_assign> (*this, at);
1453             return *this;
1454         }
1455         template<class AT>
1456         BOOST_UBLAS_INLINE
1457         banded_adaptor& operator /= (const AT &at) {
1458             matrix_assign_scalar<scalar_divides_assign> (*this, at);
1459             return *this;
1460         }
1461 
1462         // Closure comparison
1463         BOOST_UBLAS_INLINE
1464         bool same_closure (const banded_adaptor &ba) const {
1465             return (*this).data ().same_closure (ba.data ());
1466         }
1467 
1468         // Swapping
1469         BOOST_UBLAS_INLINE
1470         void swap (banded_adaptor &m) {
1471             if (this != &m) {
1472                 BOOST_UBLAS_CHECK (lower_ == m.lower_, bad_size ());
1473                 BOOST_UBLAS_CHECK (upper_ == m.upper_, bad_size ());
1474                 matrix_swap<scalar_swap> (*this, m);
1475             }
1476         }
1477         BOOST_UBLAS_INLINE
1478         friend void swap (banded_adaptor &m1, banded_adaptor &m2) {
1479             m1.swap (m2);
1480         }
1481 
1482         // Iterator types
1483     private:
1484         // Use the matrix iterator
1485         typedef typename M::const_iterator1 const_subiterator1_type;
1486         typedef typename boost::mpl::if_<boost::is_const<M>,
1487                                           typename M::const_iterator1,
1488                                           typename M::iterator1>::type subiterator1_type;
1489         typedef typename M::const_iterator2 const_subiterator2_type;
1490         typedef typename boost::mpl::if_<boost::is_const<M>,
1491                                           typename M::const_iterator2,
1492                                           typename M::iterator2>::type subiterator2_type;
1493 
1494     public:
1495 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
1496         typedef indexed_iterator1<self_type, packed_random_access_iterator_tag> iterator1;
1497         typedef indexed_iterator2<self_type, packed_random_access_iterator_tag> iterator2;
1498         typedef indexed_const_iterator1<self_type, packed_random_access_iterator_tag> const_iterator1;
1499         typedef indexed_const_iterator2<self_type, packed_random_access_iterator_tag> const_iterator2;
1500 #else
1501         class const_iterator1;
1502         class iterator1;
1503         class const_iterator2;
1504         class iterator2;
1505 #endif
1506         typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
1507         typedef reverse_iterator_base1<iterator1> reverse_iterator1;
1508         typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
1509         typedef reverse_iterator_base2<iterator2> reverse_iterator2;
1510 
1511         // Element lookup
1512         BOOST_UBLAS_INLINE
1513         const_iterator1 find1 (int rank, size_type i, size_type j) const {
1514             if (rank == 1) {
1515                 size_type lower_i = (std::max) (difference_type (j - upper_), difference_type (0));
1516                 i = (std::max) (i, lower_i);
1517                 size_type upper_i = (std::min) (j + 1 + lower_, size1 ());
1518                 i = (std::min) (i, upper_i);
1519             }
1520             return const_iterator1 (*this, data ().find1 (rank, i, j));
1521         }
1522         BOOST_UBLAS_INLINE
1523         iterator1 find1 (int rank, size_type i, size_type j) {
1524             if (rank == 1) {
1525                 size_type lower_i = (std::max) (difference_type (j - upper_), difference_type (0));
1526                 i = (std::max) (i, lower_i);
1527                 size_type upper_i = (std::min) (j + 1 + lower_, size1 ());
1528                 i = (std::min) (i, upper_i);
1529             }
1530             return iterator1 (*this, data ().find1 (rank, i, j));
1531         }
1532         BOOST_UBLAS_INLINE
1533         const_iterator2 find2 (int rank, size_type i, size_type j) const {
1534             if (rank == 1) {
1535                 size_type lower_j = (std::max) (difference_type (i - lower_), difference_type (0));
1536                 j = (std::max) (j, lower_j);
1537                 size_type upper_j = (std::min) (i + 1 + upper_, size2 ());
1538                 j = (std::min) (j, upper_j);
1539             }
1540             return const_iterator2 (*this, data ().find2 (rank, i, j));
1541         }
1542         BOOST_UBLAS_INLINE
1543         iterator2 find2 (int rank, size_type i, size_type j) {
1544             if (rank == 1) {
1545                 size_type lower_j = (std::max) (difference_type (i - lower_), difference_type (0));
1546                 j = (std::max) (j, lower_j);
1547                 size_type upper_j = (std::min) (i + 1 + upper_, size2 ());
1548                 j = (std::min) (j, upper_j);
1549             }
1550             return iterator2 (*this, data ().find2 (rank, i, j));
1551         }
1552 
1553         // Iterators simply are indices.
1554 
1555 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
1556         class const_iterator1:
1557             public container_const_reference<banded_adaptor>,
1558             public random_access_iterator_base<typename iterator_restrict_traits<
1559                                                    typename const_subiterator1_type::iterator_category, packed_random_access_iterator_tag>::iterator_category,
1560                                                const_iterator1, value_type> {
1561         public:
1562             typedef typename const_subiterator1_type::value_type value_type;
1563             typedef typename const_subiterator1_type::difference_type difference_type;
1564             typedef typename const_subiterator1_type::reference reference;
1565             typedef typename const_subiterator1_type::pointer pointer;
1566 
1567             typedef const_iterator2 dual_iterator_type;
1568             typedef const_reverse_iterator2 dual_reverse_iterator_type;
1569 
1570             // Construction and destruction
1571             BOOST_UBLAS_INLINE
1572             const_iterator1 ():
1573                 container_const_reference<self_type> (), it1_ () {}
1574             BOOST_UBLAS_INLINE
1575             const_iterator1 (const self_type &m, const const_subiterator1_type &it1):
1576                 container_const_reference<self_type> (m), it1_ (it1) {}
1577             BOOST_UBLAS_INLINE
1578             const_iterator1 (const iterator1 &it):
1579                 container_const_reference<self_type> (it ()), it1_ (it.it1_) {}
1580 
1581             // Arithmetic
1582             BOOST_UBLAS_INLINE
1583             const_iterator1 &operator ++ () {
1584                 ++ it1_;
1585                 return *this;
1586             }
1587             BOOST_UBLAS_INLINE
1588             const_iterator1 &operator -- () {
1589                 -- it1_;
1590                 return *this;
1591             }
1592             BOOST_UBLAS_INLINE
1593             const_iterator1 &operator += (difference_type n) {
1594                 it1_ += n;
1595                 return *this;
1596             }
1597             BOOST_UBLAS_INLINE
1598             const_iterator1 &operator -= (difference_type n) {
1599                 it1_ -= n;
1600                 return *this;
1601             }
1602             BOOST_UBLAS_INLINE
1603             difference_type operator - (const const_iterator1 &it) const {
1604                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1605                 return it1_ - it.it1_;
1606             }
1607 
1608             // Dereference
1609             BOOST_UBLAS_INLINE
1610             const_reference operator * () const {
1611                 size_type i = index1 ();
1612                 size_type j = index2 ();
1613                 BOOST_UBLAS_CHECK (i < (*this) ().size1 (), bad_index ());
1614                 BOOST_UBLAS_CHECK (j < (*this) ().size2 (), bad_index ());
1615 #ifdef BOOST_UBLAS_OWN_BANDED
1616                 size_type k = (std::max) (i, j);
1617                 size_type l = (*this) ().lower () + j - i;
1618                 if (k < (std::max) ((*this) ().size1 (), (*this) ().size2 ()) &&
1619                     l < (*this) ().lower () + 1 + (*this) ().upper ())
1620                     return *it1_;
1621 #else
1622                 size_type k = j;
1623                 size_type l = (*this) ().upper () + i - j;
1624                 if (k < (*this) ().size2 () &&
1625                     l < (*this) ().lower () + 1 + (*this) ().upper ())
1626                     return *it1_;
1627 #endif
1628                 return (*this) () (i, j);
1629             }
1630             BOOST_UBLAS_INLINE
1631             const_reference operator [] (difference_type n) const {
1632                 return *(*this + n);
1633             }
1634 
1635 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1636             BOOST_UBLAS_INLINE
1637 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1638             typename self_type::
1639 #endif
1640             const_iterator2 begin () const {
1641                 return (*this) ().find2 (1, index1 (), 0);
1642             }
1643             BOOST_UBLAS_INLINE
1644 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1645             typename self_type::
1646 #endif
1647             const_iterator2 cbegin () const {
1648                 return begin ();
1649             }
1650             BOOST_UBLAS_INLINE
1651 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1652             typename self_type::
1653 #endif
1654             const_iterator2 end () const {
1655                 return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
1656             }
1657             BOOST_UBLAS_INLINE
1658 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1659             typename self_type::
1660 #endif
1661             const_iterator2 cend () const {
1662                 return end ();
1663             }
1664             BOOST_UBLAS_INLINE
1665 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1666             typename self_type::
1667 #endif
1668             const_reverse_iterator2 rbegin () const {
1669                 return const_reverse_iterator2 (end ());
1670             }
1671             BOOST_UBLAS_INLINE
1672 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1673             typename self_type::
1674 #endif
1675             const_reverse_iterator2 crbegin () const {
1676                 return rbegin ();
1677             }
1678             BOOST_UBLAS_INLINE
1679 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1680             typename self_type::
1681 #endif
1682             const_reverse_iterator2 rend () const {
1683                 return const_reverse_iterator2 (begin ());
1684             }
1685             BOOST_UBLAS_INLINE
1686 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1687             typename self_type::
1688 #endif
1689             const_reverse_iterator2 crend () const {
1690                 return rend ();
1691             }
1692 #endif
1693 
1694             // Indices
1695             BOOST_UBLAS_INLINE
1696             size_type index1 () const {
1697                 return it1_.index1 ();
1698             }
1699             BOOST_UBLAS_INLINE
1700             size_type index2 () const {
1701                 return it1_.index2 ();
1702             }
1703 
1704             // Assignment
1705             BOOST_UBLAS_INLINE
1706             const_iterator1 &operator = (const const_iterator1 &it) {
1707                 container_const_reference<self_type>::assign (&it ());
1708                 it1_ = it.it1_;
1709                 return *this;
1710             }
1711 
1712             // Comparison
1713             BOOST_UBLAS_INLINE
1714             bool operator == (const const_iterator1 &it) const {
1715                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1716                 return it1_ == it.it1_;
1717             }
1718             BOOST_UBLAS_INLINE
1719             bool operator < (const const_iterator1 &it) const {
1720                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1721                 return it1_ < it.it1_;
1722             }
1723 
1724         private:
1725             const_subiterator1_type it1_;
1726         };
1727 #endif
1728 
1729         BOOST_UBLAS_INLINE
1730         const_iterator1 begin1 () const {
1731             return find1 (0, 0, 0);
1732         }
1733         BOOST_UBLAS_INLINE
1734         const_iterator1 cbegin1 () const {
1735             return begin1 ();
1736         }
1737         BOOST_UBLAS_INLINE
1738         const_iterator1 end1 () const {
1739             return find1 (0, size1 (), 0);
1740         }
1741         BOOST_UBLAS_INLINE
1742         const_iterator1 cend1 () const {
1743             return end1 ();
1744         }
1745 
1746 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
1747         class iterator1:
1748             public container_reference<banded_adaptor>,
1749             public random_access_iterator_base<typename iterator_restrict_traits<
1750                                                    typename subiterator1_type::iterator_category, packed_random_access_iterator_tag>::iterator_category,
1751                                                iterator1, value_type> {
1752         public:
1753             typedef typename subiterator1_type::value_type value_type;
1754             typedef typename subiterator1_type::difference_type difference_type;
1755             typedef typename subiterator1_type::reference reference;
1756             typedef typename subiterator1_type::pointer pointer;
1757 
1758             typedef iterator2 dual_iterator_type;
1759             typedef reverse_iterator2 dual_reverse_iterator_type;
1760 
1761             // Construction and destruction
1762             BOOST_UBLAS_INLINE
1763             iterator1 ():
1764                 container_reference<self_type> (), it1_ () {}
1765             BOOST_UBLAS_INLINE
1766             iterator1 (self_type &m, const subiterator1_type &it1):
1767                 container_reference<self_type> (m), it1_ (it1) {}
1768 
1769             // Arithmetic
1770             BOOST_UBLAS_INLINE
1771             iterator1 &operator ++ () {
1772                 ++ it1_;
1773                 return *this;
1774             }
1775             BOOST_UBLAS_INLINE
1776             iterator1 &operator -- () {
1777                 -- it1_;
1778                 return *this;
1779             }
1780             BOOST_UBLAS_INLINE
1781             iterator1 &operator += (difference_type n) {
1782                 it1_ += n;
1783                 return *this;
1784             }
1785             BOOST_UBLAS_INLINE
1786             iterator1 &operator -= (difference_type n) {
1787                 it1_ -= n;
1788                 return *this;
1789             }
1790             BOOST_UBLAS_INLINE
1791             difference_type operator - (const iterator1 &it) const {
1792                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1793                 return it1_ - it.it1_;
1794             }
1795 
1796             // Dereference
1797             BOOST_UBLAS_INLINE
1798             reference operator * () const {
1799                 size_type i = index1 ();
1800                 size_type j = index2 ();
1801                 BOOST_UBLAS_CHECK (i < (*this) ().size1 (), bad_index ());
1802                 BOOST_UBLAS_CHECK (j < (*this) ().size2 (), bad_index ());
1803 #ifdef BOOST_UBLAS_OWN_BANDED
1804                 size_type k = (std::max) (i, j);
1805                 size_type l = (*this) ().lower () + j - i;
1806                 if (k < (std::max) ((*this) ().size1 (), (*this) ().size2 ()) &&
1807                     l < (*this) ().lower () + 1 + (*this) ().upper ())
1808                     return *it1_;
1809 #else
1810                 size_type k = j;
1811                 size_type l = (*this) ().upper () + i - j;
1812                 if (k < (*this) ().size2 () &&
1813                     l < (*this) ().lower () + 1 + (*this) ().upper ())
1814                     return *it1_;
1815 #endif
1816                 return (*this) () (i, j);
1817             }
1818             BOOST_UBLAS_INLINE
1819             reference operator [] (difference_type n) const {
1820                 return *(*this + n);
1821             }
1822 
1823 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1824             BOOST_UBLAS_INLINE
1825 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1826             typename self_type::
1827 #endif
1828             iterator2 begin () const {
1829                 return (*this) ().find2 (1, index1 (), 0);
1830             }
1831             BOOST_UBLAS_INLINE
1832 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1833             typename self_type::
1834 #endif
1835             iterator2 end () const {
1836                 return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
1837             }
1838             BOOST_UBLAS_INLINE
1839 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1840             typename self_type::
1841 #endif
1842             reverse_iterator2 rbegin () const {
1843                 return reverse_iterator2 (end ());
1844             }
1845             BOOST_UBLAS_INLINE
1846 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1847             typename self_type::
1848 #endif
1849             reverse_iterator2 rend () const {
1850                 return reverse_iterator2 (begin ());
1851             }
1852 #endif
1853 
1854             // Indices
1855             BOOST_UBLAS_INLINE
1856             size_type index1 () const {
1857                 return it1_.index1 ();
1858             }
1859             BOOST_UBLAS_INLINE
1860             size_type index2 () const {
1861                 return it1_.index2 ();
1862             }
1863 
1864             // Assignment
1865             BOOST_UBLAS_INLINE
1866             iterator1 &operator = (const iterator1 &it) {
1867                 container_reference<self_type>::assign (&it ());
1868                 it1_ = it.it1_;
1869                 return *this;
1870             }
1871 
1872             // Comparison
1873             BOOST_UBLAS_INLINE
1874             bool operator == (const iterator1 &it) const {
1875                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1876                 return it1_ == it.it1_;
1877             }
1878             BOOST_UBLAS_INLINE
1879             bool operator < (const iterator1 &it) const {
1880                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1881                 return it1_ < it.it1_;
1882             }
1883 
1884         private:
1885             subiterator1_type it1_;
1886 
1887             friend class const_iterator1;
1888         };
1889 #endif
1890 
1891         BOOST_UBLAS_INLINE
1892         iterator1 begin1 () {
1893             return find1 (0, 0, 0);
1894         }
1895         BOOST_UBLAS_INLINE
1896         iterator1 end1 () {
1897             return find1 (0, size1 (), 0);
1898         }
1899 
1900 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
1901         class const_iterator2:
1902             public container_const_reference<banded_adaptor>,
1903             public random_access_iterator_base<packed_random_access_iterator_tag,
1904                                                const_iterator2, value_type> {
1905         public:
1906             typedef typename iterator_restrict_traits<typename const_subiterator2_type::iterator_category,
1907                                                       packed_random_access_iterator_tag>::iterator_category iterator_category;
1908             typedef typename const_subiterator2_type::value_type value_type;
1909             typedef typename const_subiterator2_type::difference_type difference_type;
1910             typedef typename const_subiterator2_type::reference reference;
1911             typedef typename const_subiterator2_type::pointer pointer;
1912 
1913             typedef const_iterator1 dual_iterator_type;
1914             typedef const_reverse_iterator1 dual_reverse_iterator_type;
1915 
1916             // Construction and destruction
1917             BOOST_UBLAS_INLINE
1918             const_iterator2 ():
1919                 container_const_reference<self_type> (), it2_ () {}
1920             BOOST_UBLAS_INLINE
1921             const_iterator2 (const self_type &m, const const_subiterator2_type &it2):
1922                 container_const_reference<self_type> (m), it2_ (it2) {}
1923             BOOST_UBLAS_INLINE
1924             const_iterator2 (const iterator2 &it):
1925                 container_const_reference<self_type> (it ()), it2_ (it.it2_) {}
1926 
1927             // Arithmetic
1928             BOOST_UBLAS_INLINE
1929             const_iterator2 &operator ++ () {
1930                 ++ it2_;
1931                 return *this;
1932             }
1933             BOOST_UBLAS_INLINE
1934             const_iterator2 &operator -- () {
1935                 -- it2_;
1936                 return *this;
1937             }
1938             BOOST_UBLAS_INLINE
1939             const_iterator2 &operator += (difference_type n) {
1940                 it2_ += n;
1941                 return *this;
1942             }
1943             BOOST_UBLAS_INLINE
1944             const_iterator2 &operator -= (difference_type n) {
1945                 it2_ -= n;
1946                 return *this;
1947             }
1948             BOOST_UBLAS_INLINE
1949             difference_type operator - (const const_iterator2 &it) const {
1950                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1951                 return it2_ - it.it2_;
1952             }
1953 
1954             // Dereference
1955             BOOST_UBLAS_INLINE
1956             const_reference operator * () const {
1957                 size_type i = index1 ();
1958                 size_type j = index2 ();
1959                 BOOST_UBLAS_CHECK (i < (*this) ().size1 (), bad_index ());
1960                 BOOST_UBLAS_CHECK (j < (*this) ().size2 (), bad_index ());
1961 #ifdef BOOST_UBLAS_OWN_BANDED
1962                 size_type k = (std::max) (i, j);
1963                 size_type l = (*this) ().lower () + j - i;
1964                 if (k < (std::max) ((*this) ().size1 (), (*this) ().size2 ()) &&
1965                     l < (*this) ().lower () + 1 + (*this) ().upper ())
1966                     return *it2_;
1967 #else
1968                 size_type k = j;
1969                 size_type l = (*this) ().upper () + i - j;
1970                 if (k < (*this) ().size2 () &&
1971                     l < (*this) ().lower () + 1 + (*this) ().upper ())
1972                     return *it2_;
1973 #endif
1974                 return (*this) () (i, j);
1975             }
1976             BOOST_UBLAS_INLINE
1977             const_reference operator [] (difference_type n) const {
1978                 return *(*this + n);
1979             }
1980 
1981 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1982             BOOST_UBLAS_INLINE
1983 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1984             typename self_type::
1985 #endif
1986             const_iterator1 begin () const {
1987                 return (*this) ().find1 (1, 0, index2 ());
1988             }
1989             BOOST_UBLAS_INLINE
1990 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1991             typename self_type::
1992 #endif
1993             const_iterator1 cbegin () const {
1994                 return begin ();
1995             }
1996             BOOST_UBLAS_INLINE
1997 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1998             typename self_type::
1999 #endif
2000             const_iterator1 end () const {
2001                 return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
2002             }
2003             BOOST_UBLAS_INLINE
2004 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2005             typename self_type::
2006 #endif
2007             const_iterator1 cend () const {
2008                 return end ();
2009             }
2010             BOOST_UBLAS_INLINE
2011 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2012             typename self_type::
2013 #endif
2014             const_reverse_iterator1 rbegin () const {
2015                 return const_reverse_iterator1 (end ());
2016             }
2017             BOOST_UBLAS_INLINE
2018 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2019             typename self_type::
2020 #endif
2021             const_reverse_iterator1 crbegin () const {
2022                 return rbegin ();
2023             }
2024             BOOST_UBLAS_INLINE
2025 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2026             typename self_type::
2027 #endif
2028             const_reverse_iterator1 rend () const {
2029                 return const_reverse_iterator1 (begin ());
2030             }
2031             BOOST_UBLAS_INLINE
2032 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2033             typename self_type::
2034 #endif
2035             const_reverse_iterator1 crend () const {
2036                 return rend ();
2037             }
2038 #endif
2039 
2040             // Indices
2041             BOOST_UBLAS_INLINE
2042             size_type index1 () const {
2043                 return it2_.index1 ();
2044             }
2045             BOOST_UBLAS_INLINE
2046             size_type index2 () const {
2047                 return it2_.index2 ();
2048             }
2049 
2050             // Assignment
2051             BOOST_UBLAS_INLINE
2052             const_iterator2 &operator = (const const_iterator2 &it) {
2053                 container_const_reference<self_type>::assign (&it ());
2054                 it2_ = it.it2_;
2055                 return *this;
2056             }
2057 
2058             // Comparison
2059             BOOST_UBLAS_INLINE
2060             bool operator == (const const_iterator2 &it) const {
2061                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
2062                 return it2_ == it.it2_;
2063             }
2064             BOOST_UBLAS_INLINE
2065             bool operator < (const const_iterator2 &it) const {
2066                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
2067                 return it2_ < it.it2_;
2068             }
2069 
2070         private:
2071             const_subiterator2_type it2_;
2072         };
2073 #endif
2074 
2075         BOOST_UBLAS_INLINE
2076         const_iterator2 begin2 () const {
2077             return find2 (0, 0, 0);
2078         }
2079         BOOST_UBLAS_INLINE
2080         const_iterator2 cbegin2 () const {
2081             return begin2 ();
2082         }
2083         BOOST_UBLAS_INLINE
2084         const_iterator2 end2 () const {
2085             return find2 (0, 0, size2 ());
2086         }
2087         BOOST_UBLAS_INLINE
2088         const_iterator2 cend2 () const {
2089             return end2 ();
2090         }
2091 
2092 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
2093         class iterator2:
2094             public container_reference<banded_adaptor>,
2095             public random_access_iterator_base<typename iterator_restrict_traits<
2096                                                    typename subiterator2_type::iterator_category, packed_random_access_iterator_tag>::iterator_category,
2097                                                iterator2, value_type> {
2098         public:
2099             typedef typename subiterator2_type::value_type value_type;
2100             typedef typename subiterator2_type::difference_type difference_type;
2101             typedef typename subiterator2_type::reference reference;
2102             typedef typename subiterator2_type::pointer pointer;
2103 
2104             typedef iterator1 dual_iterator_type;
2105             typedef reverse_iterator1 dual_reverse_iterator_type;
2106 
2107             // Construction and destruction
2108             BOOST_UBLAS_INLINE
2109             iterator2 ():
2110                 container_reference<self_type> (), it2_ () {}
2111             BOOST_UBLAS_INLINE
2112             iterator2 (self_type &m, const subiterator2_type &it2):
2113                 container_reference<self_type> (m), it2_ (it2) {}
2114 
2115             // Arithmetic
2116             BOOST_UBLAS_INLINE
2117             iterator2 &operator ++ () {
2118                 ++ it2_;
2119                 return *this;
2120             }
2121             BOOST_UBLAS_INLINE
2122             iterator2 &operator -- () {
2123                 -- it2_;
2124                 return *this;
2125             }
2126             BOOST_UBLAS_INLINE
2127             iterator2 &operator += (difference_type n) {
2128                 it2_ += n;
2129                 return *this;
2130             }
2131             BOOST_UBLAS_INLINE
2132             iterator2 &operator -= (difference_type n) {
2133                 it2_ -= n;
2134                 return *this;
2135             }
2136             BOOST_UBLAS_INLINE
2137             difference_type operator - (const iterator2 &it) const {
2138                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
2139                 return it2_ - it.it2_;
2140             }
2141 
2142             // Dereference
2143             BOOST_UBLAS_INLINE
2144             reference operator * () const {
2145                 size_type i = index1 ();
2146                 size_type j = index2 ();
2147                 BOOST_UBLAS_CHECK (i < (*this) ().size1 (), bad_index ());
2148                 BOOST_UBLAS_CHECK (j < (*this) ().size2 (), bad_index ());
2149 #ifdef BOOST_UBLAS_OWN_BANDED
2150                 size_type k = (std::max) (i, j);
2151                 size_type l = (*this) ().lower () + j - i;
2152                 if (k < (std::max) ((*this) ().size1 (), (*this) ().size2 ()) &&
2153                     l < (*this) ().lower () + 1 + (*this) ().upper ())
2154                     return *it2_;
2155 #else
2156                 size_type k = j;
2157                 size_type l = (*this) ().upper () + i - j;
2158                 if (k < (*this) ().size2 () &&
2159                     l < (*this) ().lower () + 1 + (*this) ().upper ())
2160                     return *it2_;
2161 #endif
2162                 return (*this) () (i, j);
2163             }
2164             BOOST_UBLAS_INLINE
2165             reference operator [] (difference_type n) const {
2166                 return *(*this + n);
2167             }
2168 
2169 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
2170             BOOST_UBLAS_INLINE
2171 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2172             typename self_type::
2173 #endif
2174             iterator1 begin () const {
2175                 return (*this) ().find1 (1, 0, index2 ());
2176             }
2177             BOOST_UBLAS_INLINE
2178 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2179             typename self_type::
2180 #endif
2181             iterator1 end () const {
2182                 return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
2183             }
2184             BOOST_UBLAS_INLINE
2185 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2186             typename self_type::
2187 #endif
2188             reverse_iterator1 rbegin () const {
2189                 return reverse_iterator1 (end ());
2190             }
2191             BOOST_UBLAS_INLINE
2192 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2193             typename self_type::
2194 #endif
2195             reverse_iterator1 rend () const {
2196                 return reverse_iterator1 (begin ());
2197             }
2198 #endif
2199 
2200             // Indices
2201             BOOST_UBLAS_INLINE
2202             size_type index1 () const {
2203                 return it2_.index1 ();
2204             }
2205             BOOST_UBLAS_INLINE
2206             size_type index2 () const {
2207                 return it2_.index2 ();
2208             }
2209 
2210             // Assignment
2211             BOOST_UBLAS_INLINE
2212             iterator2 &operator = (const iterator2 &it) {
2213                 container_reference<self_type>::assign (&it ());
2214                 it2_ = it.it2_;
2215                 return *this;
2216             }
2217 
2218             // Comparison
2219             BOOST_UBLAS_INLINE
2220             bool operator == (const iterator2 &it) const {
2221                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
2222                 return it2_ == it.it2_;
2223             }
2224             BOOST_UBLAS_INLINE
2225             bool operator < (const iterator2 &it) const {
2226                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
2227                 return it2_ < it.it2_;
2228             }
2229 
2230         private:
2231             subiterator2_type it2_;
2232 
2233             friend class const_iterator2;
2234         };
2235 #endif
2236 
2237         BOOST_UBLAS_INLINE
2238         iterator2 begin2 () {
2239             return find2 (0, 0, 0);
2240         }
2241         BOOST_UBLAS_INLINE
2242         iterator2 end2 () {
2243             return find2 (0, 0, size2 ());
2244         }
2245 
2246         // Reverse iterators
2247 
2248         BOOST_UBLAS_INLINE
2249         const_reverse_iterator1 rbegin1 () const {
2250             return const_reverse_iterator1 (end1 ());
2251         }
2252         BOOST_UBLAS_INLINE
2253         const_reverse_iterator1 crbegin1 () const {
2254             return rbegin1 ();
2255         }
2256         BOOST_UBLAS_INLINE
2257         const_reverse_iterator1 rend1 () const {
2258             return const_reverse_iterator1 (begin1 ());
2259         }
2260         BOOST_UBLAS_INLINE
2261         const_reverse_iterator1 crend1 () const {
2262             return rend1 ();
2263         }
2264 
2265         BOOST_UBLAS_INLINE
2266         reverse_iterator1 rbegin1 () {
2267             return reverse_iterator1 (end1 ());
2268         }
2269         BOOST_UBLAS_INLINE
2270         reverse_iterator1 rend1 () {
2271             return reverse_iterator1 (begin1 ());
2272         }
2273 
2274         BOOST_UBLAS_INLINE
2275         const_reverse_iterator2 rbegin2 () const {
2276             return const_reverse_iterator2 (end2 ());
2277         }
2278         BOOST_UBLAS_INLINE
2279         const_reverse_iterator2 crbegin2 () const {
2280             return rbegin2 ();
2281         }
2282         BOOST_UBLAS_INLINE
2283         const_reverse_iterator2 rend2 () const {
2284             return const_reverse_iterator2 (begin2 ());
2285         }
2286         BOOST_UBLAS_INLINE
2287         const_reverse_iterator2 crend2 () const {
2288             return rend2 ();
2289         }
2290 
2291         BOOST_UBLAS_INLINE
2292         reverse_iterator2 rbegin2 () {
2293             return reverse_iterator2 (end2 ());
2294         }
2295         BOOST_UBLAS_INLINE
2296         reverse_iterator2 rend2 () {
2297             return reverse_iterator2 (begin2 ());
2298         }
2299 
2300     private:
2301         matrix_closure_type data_;
2302         size_type lower_;
2303         size_type upper_;
2304         typedef const value_type const_value_type;
2305         static const_value_type zero_;
2306     };
2307 
2308     // Specialization for temporary_traits
2309     template <class M>
2310     struct vector_temporary_traits< banded_adaptor<M> >
2311     : vector_temporary_traits< M > {} ;
2312     template <class M>
2313     struct vector_temporary_traits< const banded_adaptor<M> >
2314     : vector_temporary_traits< M > {} ;
2315 
2316     template <class M>
2317     struct matrix_temporary_traits< banded_adaptor<M> >
2318     : matrix_temporary_traits< M > {} ;
2319     template <class M>
2320     struct matrix_temporary_traits< const banded_adaptor<M> >
2321     : matrix_temporary_traits< M > {} ;
2322 
2323 
2324     template<class M>
2325     typename banded_adaptor<M>::const_value_type banded_adaptor<M>::zero_ = value_type/*zero*/();
2326 
2327     /** \brief A diagonal matrix adaptator: convert a any matrix into a diagonal matrix expression
2328      *
2329      * For a \f$(m\times m)\f$-dimensional matrix, the \c diagonal_adaptor will provide a diagonal matrix
2330      * with \f$0 \leq i < m\f$ and \f$0 \leq j < m\f$, if \f$i\neq j\f$ then \f$b_{i,j}=0\f$. 
2331      *
2332      * Storage and location are based on those of the underlying matrix. This is important because
2333      * a \c diagonal_adaptor does not copy the matrix data to a new place. Therefore, modifying values
2334      * in a \c diagonal_adaptor matrix will also modify the underlying matrix too.
2335      *
2336      * \tparam M the type of matrix used to generate the diagonal matrix
2337      */
2338 
2339     template<class M>
2340     class diagonal_adaptor:
2341         public banded_adaptor<M> {
2342     public:
2343         typedef M matrix_type;
2344         typedef banded_adaptor<M> adaptor_type;
2345 
2346         // Construction and destruction
2347         BOOST_UBLAS_INLINE
2348         diagonal_adaptor ():
2349             adaptor_type () {}
2350         BOOST_UBLAS_INLINE
2351         diagonal_adaptor (matrix_type &data):
2352             adaptor_type (data) {}
2353         BOOST_UBLAS_INLINE
2354         ~diagonal_adaptor () {}
2355 
2356         // Assignment
2357         BOOST_UBLAS_INLINE
2358         diagonal_adaptor &operator = (const diagonal_adaptor &m) {
2359             adaptor_type::operator = (m);
2360             return *this;
2361         }
2362         template<class AE>
2363         BOOST_UBLAS_INLINE
2364         diagonal_adaptor &operator = (const matrix_expression<AE> &ae) {
2365             adaptor_type::operator = (ae);
2366             return *this;
2367         }
2368     };
2369 
2370 }}}
2371 
2372 #endif