os/ossrv/ossrv_pub/boost_apis/boost/numeric/ublas/banded.hpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 //
     2 //  Copyright (c) 2000-2002
     3 //  Joerg Walter, Mathias Koch
     4 //
     5 //  Permission to use, copy, modify, distribute and sell this software
     6 //  and its documentation for any purpose is hereby granted without fee,
     7 //  provided that the above copyright notice appear in all copies and
     8 //  that both that copyright notice and this permission notice appear
     9 //  in supporting documentation.  The authors make no representations
    10 //  about the suitability of this software for any purpose.
    11 //  It is provided "as is" without express or implied warranty.
    12 //
    13 //  The authors gratefully acknowledge the support of
    14 //  GeNeSys mbH & Co. KG in producing this work.
    15 //
    16 
    17 #ifndef _BOOST_UBLAS_BANDED_
    18 #define _BOOST_UBLAS_BANDED_
    19 
    20 #include <boost/numeric/ublas/matrix.hpp>
    21 #include <boost/numeric/ublas/detail/temporary.hpp>
    22 
    23 // Iterators based on ideas of Jeremy Siek
    24 
    25 namespace boost { namespace numeric { namespace ublas {
    26 
    27     // Array based banded matrix class
    28     template<class T, class L, class A>
    29     class banded_matrix:
    30         public matrix_container<banded_matrix<T, L, A> > {
    31 
    32         typedef T *pointer;
    33         typedef L layout_type;
    34         typedef banded_matrix<T, L, A> self_type;
    35     public:
    36 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
    37         using matrix_container<self_type>::operator ();
    38 #endif
    39         typedef typename A::size_type size_type;
    40         typedef typename A::difference_type difference_type;
    41         typedef T value_type;
    42         typedef const T &const_reference;
    43         typedef T &reference;
    44         typedef A array_type;
    45         typedef const matrix_reference<const self_type> const_closure_type;
    46         typedef matrix_reference<self_type> closure_type;
    47         typedef vector<T, A> vector_temporary_type;
    48         typedef matrix<T, L, A> matrix_temporary_type;  // general sub-matrix
    49         typedef packed_tag storage_category;
    50         typedef typename L::orientation_category orientation_category;
    51 
    52         // Construction and destruction
    53         BOOST_UBLAS_INLINE
    54         banded_matrix ():
    55             matrix_container<self_type> (),
    56             size1_ (0), size2_ (0),
    57             lower_ (0), upper_ (0), data_ (0) {}
    58         BOOST_UBLAS_INLINE
    59         banded_matrix (size_type size1, size_type size2, size_type lower = 0, size_type upper = 0):
    60             matrix_container<self_type> (),
    61             size1_ (size1), size2_ (size2),
    62             lower_ (lower), upper_ (upper), data_ ((std::max) (size1, size2) * (lower + 1 + upper)) {
    63         }
    64         BOOST_UBLAS_INLINE
    65         banded_matrix (size_type size1, size_type size2, size_type lower, size_type upper, const array_type &data):
    66             matrix_container<self_type> (),
    67             size1_ (size1), size2_ (size2),
    68             lower_ (lower), upper_ (upper), data_ (data) {}
    69         BOOST_UBLAS_INLINE
    70         banded_matrix (const banded_matrix &m):
    71             matrix_container<self_type> (),
    72             size1_ (m.size1_), size2_ (m.size2_),
    73             lower_ (m.lower_), upper_ (m.upper_), data_ (m.data_) {}
    74         template<class AE>
    75         BOOST_UBLAS_INLINE
    76         banded_matrix (const matrix_expression<AE> &ae, size_type lower = 0, size_type upper = 0):
    77             matrix_container<self_type> (),
    78             size1_ (ae ().size1 ()), size2_ (ae ().size2 ()),
    79             lower_ (lower), upper_ (upper),
    80             data_ ((std::max) (size1_, size2_) * (lower_ + 1 + upper_)) {
    81             matrix_assign<scalar_assign> (*this, ae);
    82         }
    83 
    84         // Accessors
    85         BOOST_UBLAS_INLINE
    86         size_type size1 () const {
    87             return size1_;
    88         }
    89         BOOST_UBLAS_INLINE
    90         size_type size2 () const {
    91             return size2_;
    92         }
    93         BOOST_UBLAS_INLINE
    94         size_type lower () const {
    95             return lower_;
    96         }
    97         BOOST_UBLAS_INLINE
    98         size_type upper () const {
    99             return upper_;
   100         }
   101 
   102         // Storage accessors
   103         BOOST_UBLAS_INLINE
   104         const array_type &data () const {
   105             return data_;
   106         }
   107         BOOST_UBLAS_INLINE
   108         array_type &data () {
   109             return data_;
   110         }
   111 
   112         // Resizing
   113         BOOST_UBLAS_INLINE
   114         void resize (size_type size1, size_type size2, size_type lower = 0, size_type upper = 0, bool preserve = true) {
   115             if (preserve) {
   116                 self_type temporary (size1, size2, lower, upper);
   117                 detail::matrix_resize_preserve<layout_type> (*this, temporary);
   118             }
   119             else {
   120                 data ().resize ((std::max) (size1, size2) * (lower + 1 + upper));
   121                 size1_ = size1;
   122                 size2_ = size2;
   123                 lower_ = lower;
   124                 upper_ = upper;
   125             }
   126         }
   127 
   128         BOOST_UBLAS_INLINE
   129         void resize_packed_preserve (size_type size1, size_type size2, size_type lower = 0, size_type upper = 0) {
   130             size1_ = size1;
   131             size2_ = size2;
   132             lower_ = lower;
   133             upper_ = upper;
   134             data ().resize ((std::max) (size1, size2) * (lower + 1 + upper), value_type ());
   135         }
   136 
   137         // Element access
   138         BOOST_UBLAS_INLINE
   139         const_reference operator () (size_type i, size_type j) const {
   140             BOOST_UBLAS_CHECK (i < size1_, bad_index ());
   141             BOOST_UBLAS_CHECK (j < size2_, bad_index ());
   142 #ifdef BOOST_UBLAS_OWN_BANDED
   143             const size_type k = (std::max) (i, j);
   144             const size_type l = lower_ + j - i;
   145             if (k < (std::max) (size1_, size2_) &&
   146                 l < lower_ + 1 + upper_)
   147                 return data () [layout_type::element (k, (std::max) (size1_, size2_),
   148                                                        l, lower_ + 1 + upper_)];
   149 #else
   150             const size_type k = j;
   151             const size_type l = upper_ + i - j;
   152             if (k < size2_ &&
   153                 l < lower_ + 1 + upper_)
   154                 return data () [layout_type::element (k, size2_,
   155                                                        l, lower_ + 1 + upper_)];
   156 #endif
   157             return zero_;
   158         }
   159         BOOST_UBLAS_INLINE
   160         reference at_element (size_type i, size_type j) {
   161             BOOST_UBLAS_CHECK (i < size1_, bad_index ());
   162             BOOST_UBLAS_CHECK (j < size2_, bad_index ());
   163 #ifdef BOOST_UBLAS_OWN_BANDED
   164             const size_type k = (std::max) (i, j);
   165             const size_type l = lower_ + j - i;
   166             return data () [layout_type::element (k, (std::max) (size1_, size2_),
   167                                                    l, lower_ + 1 + upper_)];
   168 #else
   169             const size_type k = j;
   170             const size_type l = upper_ + i - j;
   171             return data () [layout_type::element (k, size2_,
   172                                                    l, lower_ + 1 + upper_)];
   173 #endif
   174         }
   175         BOOST_UBLAS_INLINE
   176         reference operator () (size_type i, size_type j) {
   177             BOOST_UBLAS_CHECK (i < size1_, bad_index ());
   178             BOOST_UBLAS_CHECK (j < size2_, bad_index ());
   179 #ifdef BOOST_UBLAS_OWN_BANDED
   180             const size_type k = (std::max) (i, j);
   181             const size_type l = lower_ + j - i;
   182             if (k < (std::max) (size1_, size2_) &&
   183                 l < lower_ + 1 + upper_)
   184                 return data () [layout_type::element (k, (std::max) (size1_, size2_),
   185                                                        l, lower_ + 1 + upper_)];
   186 #else
   187             const size_type k = j;
   188             const size_type l = upper_ + i - j;
   189             if (k < size2_ &&
   190                 l < lower_ + 1 + upper_)
   191                 return data () [layout_type::element (k, size2_,
   192                                                        l, lower_ + 1 + upper_)];
   193 #endif
   194             bad_index ().raise ();
   195                 // arbitary return value
   196             return const_cast<reference>(zero_);
   197         }
   198 
   199         // Element assignment
   200         BOOST_UBLAS_INLINE
   201         reference insert_element (size_type i, size_type j, const_reference t) {
   202             return (operator () (i, j) = t);
   203         }
   204         BOOST_UBLAS_INLINE
   205         void erase_element (size_type i, size_type j) {
   206             operator () (i, j) = value_type/*zero*/();
   207         }
   208 
   209         // Zeroing
   210         BOOST_UBLAS_INLINE
   211         void clear () {
   212             std::fill (data ().begin (), data ().end (), value_type/*zero*/());
   213         }
   214 
   215         // Assignment
   216         BOOST_UBLAS_INLINE
   217         banded_matrix &operator = (const banded_matrix &m) {
   218             size1_ = m.size1_;
   219             size2_ = m.size2_;
   220             lower_ = m.lower_;
   221             upper_ = m.upper_;
   222             data () = m.data ();
   223             return *this;
   224         }
   225         BOOST_UBLAS_INLINE
   226         banded_matrix &assign_temporary (banded_matrix &m) {
   227             swap (m);
   228             return *this;
   229         }
   230         template<class AE>
   231         BOOST_UBLAS_INLINE
   232         banded_matrix &operator = (const matrix_expression<AE> &ae) {
   233             self_type temporary (ae, lower_, upper_);
   234             return assign_temporary (temporary);
   235         }
   236         template<class AE>
   237         BOOST_UBLAS_INLINE
   238         banded_matrix &assign (const matrix_expression<AE> &ae) {
   239             matrix_assign<scalar_assign> (*this, ae);
   240             return *this;
   241         }
   242         template<class AE>
   243         BOOST_UBLAS_INLINE
   244         banded_matrix& operator += (const matrix_expression<AE> &ae) {
   245             self_type temporary (*this + ae, lower_, upper_);
   246             return assign_temporary (temporary);
   247         }
   248         template<class AE>
   249         BOOST_UBLAS_INLINE
   250         banded_matrix &plus_assign (const matrix_expression<AE> &ae) {
   251             matrix_assign<scalar_plus_assign> (*this, ae);
   252             return *this;
   253         }
   254         template<class AE>
   255         BOOST_UBLAS_INLINE
   256         banded_matrix& operator -= (const matrix_expression<AE> &ae) {
   257             self_type temporary (*this - ae, lower_, upper_);
   258             return assign_temporary (temporary);
   259         }
   260         template<class AE>
   261         BOOST_UBLAS_INLINE
   262         banded_matrix &minus_assign (const matrix_expression<AE> &ae) {
   263             matrix_assign<scalar_minus_assign> (*this, ae);
   264             return *this;
   265         }
   266         template<class AT>
   267         BOOST_UBLAS_INLINE
   268         banded_matrix& operator *= (const AT &at) {
   269             matrix_assign_scalar<scalar_multiplies_assign> (*this, at);
   270             return *this;
   271         }
   272         template<class AT>
   273         BOOST_UBLAS_INLINE
   274         banded_matrix& operator /= (const AT &at) {
   275             matrix_assign_scalar<scalar_divides_assign> (*this, at);
   276             return *this;
   277         }
   278 
   279         // Swapping
   280         BOOST_UBLAS_INLINE
   281         void swap (banded_matrix &m) {
   282             if (this != &m) {
   283                 std::swap (size1_, m.size1_);
   284                 std::swap (size2_, m.size2_);
   285                 std::swap (lower_, m.lower_);
   286                 std::swap (upper_, m.upper_);
   287                 data ().swap (m.data ());
   288             }
   289         }
   290         BOOST_UBLAS_INLINE
   291         friend void swap (banded_matrix &m1, banded_matrix &m2) {
   292             m1.swap (m2);
   293         }
   294 
   295         // Iterator types
   296 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
   297         typedef indexed_iterator1<self_type, packed_random_access_iterator_tag> iterator1;
   298         typedef indexed_iterator2<self_type, packed_random_access_iterator_tag> iterator2;
   299         typedef indexed_const_iterator1<self_type, packed_random_access_iterator_tag> const_iterator1;
   300         typedef indexed_const_iterator2<self_type, packed_random_access_iterator_tag> const_iterator2;
   301 #else
   302         class const_iterator1;
   303         class iterator1;
   304         class const_iterator2;
   305         class iterator2;
   306 #endif
   307         typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
   308         typedef reverse_iterator_base1<iterator1> reverse_iterator1;
   309         typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
   310         typedef reverse_iterator_base2<iterator2> reverse_iterator2;
   311 
   312         // Element lookup
   313         BOOST_UBLAS_INLINE
   314         const_iterator1 find1 (int rank, size_type i, size_type j) const {
   315             if (rank == 1) {
   316                 size_type lower_i = (std::max) (difference_type (j - upper_), difference_type (0));
   317                 i = (std::max) (i, lower_i);
   318                 size_type upper_i = (std::min) (j + 1 + lower_, size1_);
   319                 i = (std::min) (i, upper_i);
   320             }
   321             return const_iterator1 (*this, i, j);
   322         }
   323         BOOST_UBLAS_INLINE
   324         iterator1 find1 (int rank, size_type i, size_type j) {
   325             if (rank == 1) {
   326                 size_type lower_i = (std::max) (difference_type (j - upper_), difference_type (0));
   327                 i = (std::max) (i, lower_i);
   328                 size_type upper_i = (std::min) (j + 1 + lower_, size1_);
   329                 i = (std::min) (i, upper_i);
   330             }
   331             return iterator1 (*this, i, j);
   332         }
   333         BOOST_UBLAS_INLINE
   334         const_iterator2 find2 (int rank, size_type i, size_type j) const {
   335             if (rank == 1) {
   336                 size_type lower_j = (std::max) (difference_type (i - lower_), difference_type (0));
   337                 j = (std::max) (j, lower_j);
   338                 size_type upper_j = (std::min) (i + 1 + upper_, size2_);
   339                 j = (std::min) (j, upper_j);
   340             }
   341             return const_iterator2 (*this, i, j);
   342         }
   343         BOOST_UBLAS_INLINE
   344         iterator2 find2 (int rank, size_type i, size_type j) {
   345             if (rank == 1) {
   346                 size_type lower_j = (std::max) (difference_type (i - lower_), difference_type (0));
   347                 j = (std::max) (j, lower_j);
   348                 size_type upper_j = (std::min) (i + 1 + upper_, size2_);
   349                 j = (std::min) (j, upper_j);
   350             }
   351             return iterator2 (*this, i, j);
   352         }
   353 
   354         // Iterators simply are indices.
   355 
   356 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
   357         class const_iterator1:
   358             public container_const_reference<banded_matrix>,
   359             public random_access_iterator_base<packed_random_access_iterator_tag,
   360                                                const_iterator1, value_type> {
   361         public:
   362             typedef typename banded_matrix::value_type value_type;
   363             typedef typename banded_matrix::difference_type difference_type;
   364             typedef typename banded_matrix::const_reference reference;
   365             typedef const typename banded_matrix::pointer pointer;
   366 
   367             typedef const_iterator2 dual_iterator_type;
   368             typedef const_reverse_iterator2 dual_reverse_iterator_type;
   369 
   370             // Construction and destruction
   371             BOOST_UBLAS_INLINE
   372             const_iterator1 ():
   373                 container_const_reference<self_type> (), it1_ (), it2_ () {}
   374             BOOST_UBLAS_INLINE
   375             const_iterator1 (const self_type &m, size_type it1, size_type it2):
   376                 container_const_reference<self_type> (m), it1_ (it1), it2_ (it2) {}
   377             BOOST_UBLAS_INLINE
   378             const_iterator1 (const iterator1 &it):
   379                 container_const_reference<self_type> (it ()), it1_ (it.it1_), it2_ (it.it2_) {}
   380 
   381             // Arithmetic
   382             BOOST_UBLAS_INLINE
   383             const_iterator1 &operator ++ () {
   384                 ++ it1_;
   385                 return *this;
   386             }
   387             BOOST_UBLAS_INLINE
   388             const_iterator1 &operator -- () {
   389                 -- it1_;
   390                 return *this;
   391             }
   392             BOOST_UBLAS_INLINE
   393             const_iterator1 &operator += (difference_type n) {
   394                 it1_ += n;
   395                 return *this;
   396             }
   397             BOOST_UBLAS_INLINE
   398             const_iterator1 &operator -= (difference_type n) {
   399                 it1_ -= n;
   400                 return *this;
   401             }
   402             BOOST_UBLAS_INLINE
   403             difference_type operator - (const const_iterator1 &it) const {
   404                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
   405                 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
   406                 return it1_ - it.it1_;
   407             }
   408 
   409             // Dereference
   410             BOOST_UBLAS_INLINE
   411             const_reference operator * () const {
   412                 return (*this) () (it1_, it2_);
   413             }
   414             BOOST_UBLAS_INLINE
   415             const_reference operator [] (difference_type n) const {
   416                 return *(*this + n);
   417             }
   418 
   419 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
   420             BOOST_UBLAS_INLINE
   421 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
   422             typename self_type::
   423 #endif
   424             const_iterator2 begin () const {
   425                 return (*this) ().find2 (1, it1_, 0);
   426             }
   427             BOOST_UBLAS_INLINE
   428 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
   429             typename self_type::
   430 #endif
   431             const_iterator2 end () const {
   432                 return (*this) ().find2 (1, it1_, (*this) ().size2 ());
   433             }
   434             BOOST_UBLAS_INLINE
   435 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
   436             typename self_type::
   437 #endif
   438             const_reverse_iterator2 rbegin () const {
   439                 return const_reverse_iterator2 (end ());
   440             }
   441             BOOST_UBLAS_INLINE
   442 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
   443             typename self_type::
   444 #endif
   445             const_reverse_iterator2 rend () const {
   446                 return const_reverse_iterator2 (begin ());
   447             }
   448 #endif
   449 
   450             // Indices
   451             BOOST_UBLAS_INLINE
   452             size_type index1 () const {
   453                 return it1_;
   454             }
   455             BOOST_UBLAS_INLINE
   456             size_type index2 () const {
   457                 return it2_;
   458             }
   459 
   460             // Assignment
   461             BOOST_UBLAS_INLINE
   462             const_iterator1 &operator = (const const_iterator1 &it) {
   463                 container_const_reference<self_type>::assign (&it ());
   464                 it1_ = it.it1_;
   465                 it2_ = it.it2_;
   466                 return *this;
   467             }
   468 
   469             // Comparison
   470             BOOST_UBLAS_INLINE
   471             bool operator == (const const_iterator1 &it) const {
   472                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
   473                 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
   474                 return it1_ == it.it1_;
   475             }
   476             BOOST_UBLAS_INLINE
   477             bool operator < (const const_iterator1 &it) const {
   478                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
   479                 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
   480                 return it1_ < it.it1_;
   481             }
   482 
   483         private:
   484             size_type it1_;
   485             size_type it2_;
   486         };
   487 #endif
   488 
   489         BOOST_UBLAS_INLINE
   490         const_iterator1 begin1 () const {
   491             return find1 (0, 0, 0);
   492         }
   493         BOOST_UBLAS_INLINE
   494         const_iterator1 end1 () const {
   495             return find1 (0, size1_, 0);
   496         }
   497 
   498 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
   499         class iterator1:
   500             public container_reference<banded_matrix>,
   501             public random_access_iterator_base<packed_random_access_iterator_tag,
   502                                                iterator1, value_type> {
   503         public:
   504             typedef typename banded_matrix::value_type value_type;
   505             typedef typename banded_matrix::difference_type difference_type;
   506             typedef typename banded_matrix::reference reference;
   507             typedef typename banded_matrix::pointer pointer;
   508 
   509             typedef iterator2 dual_iterator_type;
   510             typedef reverse_iterator2 dual_reverse_iterator_type;
   511 
   512             // Construction and destruction
   513             BOOST_UBLAS_INLINE
   514             iterator1 ():
   515                 container_reference<self_type> (), it1_ (), it2_ () {}
   516             BOOST_UBLAS_INLINE
   517             iterator1 (self_type &m, size_type it1, size_type it2):
   518                 container_reference<self_type> (m), it1_ (it1), it2_ (it2) {}
   519 
   520             // Arithmetic
   521             BOOST_UBLAS_INLINE
   522             iterator1 &operator ++ () {
   523                 ++ it1_;
   524                 return *this;
   525             }
   526             BOOST_UBLAS_INLINE
   527             iterator1 &operator -- () {
   528                 -- it1_;
   529                 return *this;
   530             }
   531             BOOST_UBLAS_INLINE
   532             iterator1 &operator += (difference_type n) {
   533                 it1_ += n;
   534                 return *this;
   535             }
   536             BOOST_UBLAS_INLINE
   537             iterator1 &operator -= (difference_type n) {
   538                 it1_ -= n;
   539                 return *this;
   540             }
   541             BOOST_UBLAS_INLINE
   542             difference_type operator - (const iterator1 &it) const {
   543                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
   544                 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
   545                 return it1_ - it.it1_;
   546             }
   547 
   548             // Dereference
   549             BOOST_UBLAS_INLINE
   550             reference operator * () const {
   551                 return (*this) ().at_element (it1_, it2_);
   552             }
   553             BOOST_UBLAS_INLINE
   554             reference operator [] (difference_type n) const {
   555                 return *(*this + n);
   556             }
   557 
   558 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
   559             BOOST_UBLAS_INLINE
   560 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
   561             typename self_type::
   562 #endif
   563             iterator2 begin () const {
   564                 return (*this) ().find2 (1, it1_, 0);
   565             }
   566             BOOST_UBLAS_INLINE
   567 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
   568             typename self_type::
   569 #endif
   570             iterator2 end () const {
   571                 return (*this) ().find2 (1, it1_, (*this) ().size2 ());
   572             }
   573             BOOST_UBLAS_INLINE
   574 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
   575             typename self_type::
   576 #endif
   577             reverse_iterator2 rbegin () const {
   578                 return reverse_iterator2 (end ());
   579             }
   580             BOOST_UBLAS_INLINE
   581 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
   582             typename self_type::
   583 #endif
   584             reverse_iterator2 rend () const {
   585                 return reverse_iterator2 (begin ());
   586             }
   587 #endif
   588 
   589             // Indices
   590             BOOST_UBLAS_INLINE
   591             size_type index1 () const {
   592                 return it1_;
   593             }
   594             BOOST_UBLAS_INLINE
   595             size_type index2 () const {
   596                 return it2_;
   597             }
   598 
   599             // Assignment
   600             BOOST_UBLAS_INLINE
   601             iterator1 &operator = (const iterator1 &it) {
   602                 container_reference<self_type>::assign (&it ());
   603                 it1_ = it.it1_;
   604                 it2_ = it.it2_;
   605                 return *this;
   606             }
   607 
   608             // Comparison
   609             BOOST_UBLAS_INLINE
   610             bool operator == (const iterator1 &it) const {
   611                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
   612                 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
   613                 return it1_ == it.it1_;
   614             }
   615             BOOST_UBLAS_INLINE
   616             bool operator < (const iterator1 &it) const {
   617                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
   618                 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
   619                 return it1_ < it.it1_;
   620             }
   621 
   622         private:
   623             size_type it1_;
   624             size_type it2_;
   625 
   626             friend class const_iterator1;
   627         };
   628 #endif
   629 
   630         BOOST_UBLAS_INLINE
   631         iterator1 begin1 () {
   632             return find1 (0, 0, 0);
   633         }
   634         BOOST_UBLAS_INLINE
   635         iterator1 end1 () {
   636             return find1 (0, size1_, 0);
   637         }
   638 
   639 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
   640         class const_iterator2:
   641             public container_const_reference<banded_matrix>,
   642             public random_access_iterator_base<packed_random_access_iterator_tag,
   643                                                const_iterator2, value_type> {
   644         public:
   645             typedef typename banded_matrix::value_type value_type;
   646             typedef typename banded_matrix::difference_type difference_type;
   647             typedef typename banded_matrix::const_reference reference;
   648             typedef const typename banded_matrix::pointer pointer;
   649 
   650             typedef const_iterator1 dual_iterator_type;
   651             typedef const_reverse_iterator1 dual_reverse_iterator_type;
   652 
   653             // Construction and destruction
   654             BOOST_UBLAS_INLINE
   655             const_iterator2 ():
   656                 container_const_reference<self_type> (), it1_ (), it2_ () {}
   657             BOOST_UBLAS_INLINE
   658             const_iterator2 (const self_type &m, size_type it1, size_type it2):
   659                 container_const_reference<self_type> (m), it1_ (it1), it2_ (it2) {}
   660             BOOST_UBLAS_INLINE
   661             const_iterator2 (const iterator2 &it):
   662                 container_const_reference<self_type> (it ()), it1_ (it.it1_), it2_ (it.it2_) {}
   663 
   664             // Arithmetic
   665             BOOST_UBLAS_INLINE
   666             const_iterator2 &operator ++ () {
   667                 ++ it2_;
   668                 return *this;
   669             }
   670             BOOST_UBLAS_INLINE
   671             const_iterator2 &operator -- () {
   672                 -- it2_;
   673                 return *this;
   674             }
   675             BOOST_UBLAS_INLINE
   676             const_iterator2 &operator += (difference_type n) {
   677                 it2_ += n;
   678                 return *this;
   679             }
   680             BOOST_UBLAS_INLINE
   681             const_iterator2 &operator -= (difference_type n) {
   682                 it2_ -= n;
   683                 return *this;
   684             }
   685             BOOST_UBLAS_INLINE
   686             difference_type operator - (const const_iterator2 &it) const {
   687                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
   688                 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
   689                 return it2_ - it.it2_;
   690             }
   691 
   692             // Dereference
   693             BOOST_UBLAS_INLINE
   694             const_reference operator * () const {
   695                 return (*this) () (it1_, it2_);
   696             }
   697             BOOST_UBLAS_INLINE
   698             const_reference operator [] (difference_type n) const {
   699                 return *(*this + n);
   700             }
   701 
   702 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
   703             BOOST_UBLAS_INLINE
   704 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
   705             typename self_type::
   706 #endif
   707             const_iterator1 begin () const {
   708                 return (*this) ().find1 (1, 0, it2_);
   709             }
   710             BOOST_UBLAS_INLINE
   711 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
   712             typename self_type::
   713 #endif
   714             const_iterator1 end () const {
   715                 return (*this) ().find1 (1, (*this) ().size1 (), it2_);
   716             }
   717             BOOST_UBLAS_INLINE
   718 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
   719             typename self_type::
   720 #endif
   721             const_reverse_iterator1 rbegin () const {
   722                 return const_reverse_iterator1 (end ());
   723             }
   724             BOOST_UBLAS_INLINE
   725 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
   726             typename self_type::
   727 #endif
   728             const_reverse_iterator1 rend () const {
   729                 return const_reverse_iterator1 (begin ());
   730             }
   731 #endif
   732 
   733             // Indices
   734             BOOST_UBLAS_INLINE
   735             size_type index1 () const {
   736                 return it1_;
   737             }
   738             BOOST_UBLAS_INLINE
   739             size_type index2 () const {
   740                 return it2_;
   741             }
   742 
   743             // Assignment
   744             BOOST_UBLAS_INLINE
   745             const_iterator2 &operator = (const const_iterator2 &it) {
   746                 container_const_reference<self_type>::assign (&it ());
   747                 it1_ = it.it1_;
   748                 it2_ = it.it2_;
   749                 return *this;
   750             }
   751 
   752             // Comparison
   753             BOOST_UBLAS_INLINE
   754             bool operator == (const const_iterator2 &it) const {
   755                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
   756                 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
   757                 return it2_ == it.it2_;
   758             }
   759             BOOST_UBLAS_INLINE
   760             bool operator < (const const_iterator2 &it) const {
   761                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
   762                 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
   763                 return it2_ < it.it2_;
   764             }
   765 
   766         private:
   767             size_type it1_;
   768             size_type it2_;
   769         };
   770 #endif
   771 
   772         BOOST_UBLAS_INLINE
   773         const_iterator2 begin2 () const {
   774             return find2 (0, 0, 0);
   775         }
   776         BOOST_UBLAS_INLINE
   777         const_iterator2 end2 () const {
   778             return find2 (0, 0, size2_);
   779         }
   780 
   781 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
   782         class iterator2:
   783             public container_reference<banded_matrix>,
   784             public random_access_iterator_base<packed_random_access_iterator_tag,
   785                                                iterator2, value_type> {
   786         public:
   787             typedef typename banded_matrix::value_type value_type;
   788             typedef typename banded_matrix::difference_type difference_type;
   789             typedef typename banded_matrix::reference reference;
   790             typedef typename banded_matrix::pointer pointer;
   791 
   792             typedef iterator1 dual_iterator_type;
   793             typedef reverse_iterator1 dual_reverse_iterator_type;
   794 
   795             // Construction and destruction
   796             BOOST_UBLAS_INLINE
   797             iterator2 ():
   798                 container_reference<self_type> (), it1_ (), it2_ () {}
   799             BOOST_UBLAS_INLINE
   800             iterator2 (self_type &m, size_type it1, size_type it2):
   801                 container_reference<self_type> (m), it1_ (it1), it2_ (it2) {}
   802 
   803             // Arithmetic
   804             BOOST_UBLAS_INLINE
   805             iterator2 &operator ++ () {
   806                 ++ it2_;
   807                 return *this;
   808             }
   809             BOOST_UBLAS_INLINE
   810             iterator2 &operator -- () {
   811                 -- it2_;
   812                 return *this;
   813             }
   814             BOOST_UBLAS_INLINE
   815             iterator2 &operator += (difference_type n) {
   816                 it2_ += n;
   817                 return *this;
   818             }
   819             BOOST_UBLAS_INLINE
   820             iterator2 &operator -= (difference_type n) {
   821                 it2_ -= n;
   822                 return *this;
   823             }
   824             BOOST_UBLAS_INLINE
   825             difference_type operator - (const iterator2 &it) const {
   826                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
   827                 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
   828                 return it2_ - it.it2_;
   829             }
   830 
   831             // Dereference
   832             BOOST_UBLAS_INLINE
   833             reference operator * () const {
   834                 return (*this) ().at_element (it1_, it2_);
   835             }
   836             BOOST_UBLAS_INLINE
   837             reference operator [] (difference_type n) const {
   838                 return *(*this + n);
   839             }
   840 
   841 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
   842             BOOST_UBLAS_INLINE
   843 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
   844             typename self_type::
   845 #endif
   846             iterator1 begin () const {
   847                 return (*this) ().find1 (1, 0, it2_);
   848             }
   849             BOOST_UBLAS_INLINE
   850 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
   851             typename self_type::
   852 #endif
   853             iterator1 end () const {
   854                 return (*this) ().find1 (1, (*this) ().size1 (), it2_);
   855             }
   856             BOOST_UBLAS_INLINE
   857 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
   858             typename self_type::
   859 #endif
   860             reverse_iterator1 rbegin () const {
   861                 return reverse_iterator1 (end ());
   862             }
   863             BOOST_UBLAS_INLINE
   864 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
   865             typename self_type::
   866 #endif
   867             reverse_iterator1 rend () const {
   868                 return reverse_iterator1 (begin ());
   869             }
   870 #endif
   871 
   872             // Indices
   873             BOOST_UBLAS_INLINE
   874             size_type index1 () const {
   875                 return it1_;
   876             }
   877             BOOST_UBLAS_INLINE
   878             size_type index2 () const {
   879                 return it2_;
   880             }
   881 
   882             // Assignment
   883             BOOST_UBLAS_INLINE
   884             iterator2 &operator = (const iterator2 &it) {
   885                 container_reference<self_type>::assign (&it ());
   886                 it1_ = it.it1_;
   887                 it2_ = it.it2_;
   888                 return *this;
   889             }
   890 
   891             // Comparison
   892             BOOST_UBLAS_INLINE
   893             bool operator == (const iterator2 &it) const {
   894                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
   895                 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
   896                 return it2_ == it.it2_;
   897             }
   898             BOOST_UBLAS_INLINE
   899             bool operator < (const iterator2 &it) const {
   900                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
   901                 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
   902                 return it2_ < it.it2_;
   903             }
   904 
   905         private:
   906             size_type it1_;
   907             size_type it2_;
   908 
   909             friend class const_iterator2;
   910         };
   911 #endif
   912 
   913         BOOST_UBLAS_INLINE
   914         iterator2 begin2 () {
   915             return find2 (0, 0, 0);
   916         }
   917         BOOST_UBLAS_INLINE
   918         iterator2 end2 () {
   919             return find2 (0, 0, size2_);
   920         }
   921 
   922         // Reverse iterators
   923 
   924         BOOST_UBLAS_INLINE
   925         const_reverse_iterator1 rbegin1 () const {
   926             return const_reverse_iterator1 (end1 ());
   927         }
   928         BOOST_UBLAS_INLINE
   929         const_reverse_iterator1 rend1 () const {
   930             return const_reverse_iterator1 (begin1 ());
   931         }
   932 
   933         BOOST_UBLAS_INLINE
   934         reverse_iterator1 rbegin1 () {
   935             return reverse_iterator1 (end1 ());
   936         }
   937         BOOST_UBLAS_INLINE
   938         reverse_iterator1 rend1 () {
   939             return reverse_iterator1 (begin1 ());
   940         }
   941 
   942         BOOST_UBLAS_INLINE
   943         const_reverse_iterator2 rbegin2 () const {
   944             return const_reverse_iterator2 (end2 ());
   945         }
   946         BOOST_UBLAS_INLINE
   947         const_reverse_iterator2 rend2 () const {
   948             return const_reverse_iterator2 (begin2 ());
   949         }
   950 
   951         BOOST_UBLAS_INLINE
   952         reverse_iterator2 rbegin2 () {
   953             return reverse_iterator2 (end2 ());
   954         }
   955         BOOST_UBLAS_INLINE
   956         reverse_iterator2 rend2 () {
   957             return reverse_iterator2 (begin2 ());
   958         }
   959 
   960     private:
   961         size_type size1_;
   962         size_type size2_;
   963         size_type lower_;
   964         size_type upper_;
   965         array_type data_;
   966         typedef const value_type const_value_type;
   967         static const_value_type zero_;
   968     };
   969 
   970     template<class T, class L, class A>
   971     typename banded_matrix<T, L, A>::const_value_type banded_matrix<T, L, A>::zero_ = value_type/*zero*/();
   972 
   973 
   974     // Diagonal matrix class
   975     template<class T, class L, class A>
   976     class diagonal_matrix:
   977         public banded_matrix<T, L, A> {
   978     public:
   979         typedef typename A::size_type size_type;
   980         typedef banded_matrix<T, L, A> matrix_type;
   981         typedef A array_type;
   982 
   983         // Construction and destruction
   984         BOOST_UBLAS_INLINE
   985         diagonal_matrix ():
   986             matrix_type () {}
   987         BOOST_UBLAS_INLINE
   988         diagonal_matrix (size_type size):
   989             matrix_type (size, size) {}
   990         BOOST_UBLAS_INLINE
   991         diagonal_matrix (size_type size, const array_type& data):
   992             matrix_type (size, size, 0, 0, data) {}
   993         BOOST_UBLAS_INLINE
   994         diagonal_matrix (size_type size1, size_type size2):
   995             matrix_type (size1, size2) {}
   996         template<class AE>
   997         BOOST_UBLAS_INLINE
   998         diagonal_matrix (const matrix_expression<AE> &ae):
   999             matrix_type (ae) {}
  1000         BOOST_UBLAS_INLINE
  1001         ~diagonal_matrix () {}
  1002 
  1003         // Assignment
  1004         BOOST_UBLAS_INLINE
  1005         diagonal_matrix &operator = (const diagonal_matrix &m) {
  1006             matrix_type::operator = (m);
  1007             return *this;
  1008         }
  1009         template<class AE>
  1010         BOOST_UBLAS_INLINE
  1011         diagonal_matrix &operator = (const matrix_expression<AE> &ae) {
  1012             matrix_type::operator = (ae);
  1013             return *this;
  1014         }
  1015     };
  1016 
  1017     // Banded matrix adaptor class
  1018     template<class M>
  1019     class banded_adaptor:
  1020         public matrix_expression<banded_adaptor<M> > {
  1021 
  1022         typedef banded_adaptor<M> self_type;
  1023     public:
  1024 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
  1025         using matrix_expression<self_type>::operator ();
  1026 #endif
  1027         typedef const M const_matrix_type;
  1028         typedef M matrix_type;
  1029         typedef typename M::size_type size_type;
  1030         typedef typename M::difference_type difference_type;
  1031         typedef typename M::value_type value_type;
  1032         typedef typename M::const_reference const_reference;
  1033         typedef typename boost::mpl::if_<boost::is_const<M>,
  1034                                           typename M::const_reference,
  1035                                           typename M::reference>::type reference;
  1036         typedef typename boost::mpl::if_<boost::is_const<M>,
  1037                                           typename M::const_closure_type,
  1038                                           typename M::closure_type>::type matrix_closure_type;
  1039         typedef const self_type const_closure_type;
  1040         typedef self_type closure_type;
  1041         // Replaced by _temporary_traits to avoid type requirements on M
  1042         //typedef typename M::vector_temporary_type vector_temporary_type;
  1043         //typedef typename M::matrix_temporary_type matrix_temporary_type;
  1044         typedef typename storage_restrict_traits<typename M::storage_category,
  1045                                                  packed_proxy_tag>::storage_category storage_category;
  1046         typedef typename M::orientation_category orientation_category;
  1047 
  1048         // Construction and destruction
  1049         BOOST_UBLAS_INLINE
  1050         banded_adaptor (matrix_type &data, size_type lower = 0, size_type upper = 0):
  1051             matrix_expression<self_type> (),
  1052             data_ (data), lower_ (lower), upper_ (upper) {}
  1053         BOOST_UBLAS_INLINE
  1054         banded_adaptor (const banded_adaptor &m):
  1055             matrix_expression<self_type> (),
  1056             data_ (m.data_), lower_ (m.lower_), upper_ (m.upper_) {}
  1057 
  1058         // Accessors
  1059         BOOST_UBLAS_INLINE
  1060         size_type size1 () const {
  1061             return data_.size1 ();
  1062         }
  1063         BOOST_UBLAS_INLINE
  1064         size_type size2 () const {
  1065             return data_.size2 ();
  1066         }
  1067         BOOST_UBLAS_INLINE
  1068         size_type lower () const {
  1069             return lower_;
  1070         }
  1071         BOOST_UBLAS_INLINE
  1072         size_type upper () const {
  1073             return upper_;
  1074         }
  1075 
  1076         // Storage accessors
  1077         BOOST_UBLAS_INLINE
  1078         const matrix_closure_type &data () const {
  1079             return data_;
  1080         }
  1081         BOOST_UBLAS_INLINE
  1082         matrix_closure_type &data () {
  1083             return data_;
  1084         }
  1085 
  1086         // Element access
  1087 #ifndef BOOST_UBLAS_PROXY_CONST_MEMBER
  1088         BOOST_UBLAS_INLINE
  1089         const_reference operator () (size_type i, size_type j) const {
  1090             BOOST_UBLAS_CHECK (i < size1 (), bad_index ());
  1091             BOOST_UBLAS_CHECK (j < size2 (), bad_index ());
  1092 #ifdef BOOST_UBLAS_OWN_BANDED
  1093             size_type k = (std::max) (i, j);
  1094             size_type l = lower_ + j - i;
  1095             if (k < (std::max) (size1 (), size2 ()) &&
  1096                 l < lower_ + 1 + upper_)
  1097                 return data () (i, j);
  1098 #else
  1099             size_type k = j;
  1100             size_type l = upper_ + i - j;
  1101             if (k < size2 () &&
  1102                 l < lower_ + 1 + upper_)
  1103                 return data () (i, j);
  1104 #endif
  1105             return zero_;
  1106         }
  1107         BOOST_UBLAS_INLINE
  1108         reference operator () (size_type i, size_type j) {
  1109             BOOST_UBLAS_CHECK (i < size1 (), bad_index ());
  1110             BOOST_UBLAS_CHECK (j < size2 (), bad_index ());
  1111 #ifdef BOOST_UBLAS_OWN_BANDED
  1112             size_type k = (std::max) (i, j);
  1113             size_type l = lower_ + j - i;
  1114             if (k < (std::max) (size1 (), size2 ()) &&
  1115                 l < lower_ + 1 + upper_)
  1116                 return data () (i, j);
  1117 #else
  1118             size_type k = j;
  1119             size_type l = upper_ + i - j;
  1120             if (k < size2 () &&
  1121                 l < lower_ + 1 + upper_)
  1122                 return data () (i, j);
  1123 #endif
  1124 #ifndef BOOST_UBLAS_REFERENCE_CONST_MEMBER
  1125             bad_index ().raise ();
  1126 #endif
  1127             return const_cast<reference>(zero_);
  1128         }
  1129 #else
  1130         BOOST_UBLAS_INLINE
  1131         reference operator () (size_type i, size_type j) const {
  1132             BOOST_UBLAS_CHECK (i < size1 (), bad_index ());
  1133             BOOST_UBLAS_CHECK (j < size2 (), bad_index ());
  1134 #ifdef BOOST_UBLAS_OWN_BANDED
  1135             size_type k = (std::max) (i, j);
  1136             size_type l = lower_ + j - i;
  1137             if (k < (std::max) (size1 (), size2 ()) &&
  1138                 l < lower_ + 1 + upper_)
  1139                 return data () (i, j);
  1140 #else
  1141             size_type k = j;
  1142             size_type l = upper_ + i - j;
  1143             if (k < size2 () &&
  1144                 l < lower_ + 1 + upper_)
  1145                 return data () (i, j);
  1146 #endif
  1147 #ifndef BOOST_UBLAS_REFERENCE_CONST_MEMBER
  1148             bad_index ().raise ();
  1149 #endif
  1150             return const_cast<reference>(zero_);
  1151         }
  1152 #endif
  1153 
  1154         // Assignment
  1155         BOOST_UBLAS_INLINE
  1156         banded_adaptor &operator = (const banded_adaptor &m) {
  1157             matrix_assign<scalar_assign> (*this, m);
  1158             return *this;
  1159         }
  1160         BOOST_UBLAS_INLINE
  1161         banded_adaptor &assign_temporary (banded_adaptor &m) {
  1162             *this = m;
  1163             return *this;
  1164         }
  1165         template<class AE>
  1166         BOOST_UBLAS_INLINE
  1167         banded_adaptor &operator = (const matrix_expression<AE> &ae) {
  1168             matrix_assign<scalar_assign> (*this, matrix<value_type> (ae));
  1169             return *this;
  1170         }
  1171         template<class AE>
  1172         BOOST_UBLAS_INLINE
  1173         banded_adaptor &assign (const matrix_expression<AE> &ae) {
  1174             matrix_assign<scalar_assign> (*this, ae);
  1175             return *this;
  1176         }
  1177         template<class AE>
  1178         BOOST_UBLAS_INLINE
  1179         banded_adaptor& operator += (const matrix_expression<AE> &ae) {
  1180             matrix_assign<scalar_assign> (*this, matrix<value_type> (*this + ae));
  1181             return *this;
  1182         }
  1183         template<class AE>
  1184         BOOST_UBLAS_INLINE
  1185         banded_adaptor &plus_assign (const matrix_expression<AE> &ae) {
  1186             matrix_assign<scalar_plus_assign> (*this, ae);
  1187             return *this;
  1188         }
  1189         template<class AE>
  1190         BOOST_UBLAS_INLINE
  1191         banded_adaptor& operator -= (const matrix_expression<AE> &ae) {
  1192             matrix_assign<scalar_assign> (*this, matrix<value_type> (*this - ae));
  1193             return *this;
  1194         }
  1195         template<class AE>
  1196         BOOST_UBLAS_INLINE
  1197         banded_adaptor &minus_assign (const matrix_expression<AE> &ae) {
  1198             matrix_assign<scalar_minus_assign> (*this, ae);
  1199             return *this;
  1200         }
  1201         template<class AT>
  1202         BOOST_UBLAS_INLINE
  1203         banded_adaptor& operator *= (const AT &at) {
  1204             matrix_assign_scalar<scalar_multiplies_assign> (*this, at);
  1205             return *this;
  1206         }
  1207         template<class AT>
  1208         BOOST_UBLAS_INLINE
  1209         banded_adaptor& operator /= (const AT &at) {
  1210             matrix_assign_scalar<scalar_divides_assign> (*this, at);
  1211             return *this;
  1212         }
  1213 
  1214         // Closure comparison
  1215         BOOST_UBLAS_INLINE
  1216         bool same_closure (const banded_adaptor &ba) const {
  1217             return (*this).data ().same_closure (ba.data ());
  1218         }
  1219 
  1220         // Swapping
  1221         BOOST_UBLAS_INLINE
  1222         void swap (banded_adaptor &m) {
  1223             if (this != &m) {
  1224                 BOOST_UBLAS_CHECK (lower_ == m.lower_, bad_size ());
  1225                 BOOST_UBLAS_CHECK (upper_ == m.upper_, bad_size ());
  1226                 matrix_swap<scalar_swap> (*this, m);
  1227             }
  1228         }
  1229         BOOST_UBLAS_INLINE
  1230         friend void swap (banded_adaptor &m1, banded_adaptor &m2) {
  1231             m1.swap (m2);
  1232         }
  1233 
  1234         // Iterator types
  1235     private:
  1236         // Use the matrix iterator
  1237         typedef typename M::const_iterator1 const_subiterator1_type;
  1238         typedef typename boost::mpl::if_<boost::is_const<M>,
  1239                                           typename M::const_iterator1,
  1240                                           typename M::iterator1>::type subiterator1_type;
  1241         typedef typename M::const_iterator2 const_subiterator2_type;
  1242         typedef typename boost::mpl::if_<boost::is_const<M>,
  1243                                           typename M::const_iterator2,
  1244                                           typename M::iterator2>::type subiterator2_type;
  1245 
  1246     public:
  1247 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
  1248         typedef indexed_iterator1<self_type, packed_random_access_iterator_tag> iterator1;
  1249         typedef indexed_iterator2<self_type, packed_random_access_iterator_tag> iterator2;
  1250         typedef indexed_const_iterator1<self_type, packed_random_access_iterator_tag> const_iterator1;
  1251         typedef indexed_const_iterator2<self_type, packed_random_access_iterator_tag> const_iterator2;
  1252 #else
  1253         class const_iterator1;
  1254         class iterator1;
  1255         class const_iterator2;
  1256         class iterator2;
  1257 #endif
  1258         typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
  1259         typedef reverse_iterator_base1<iterator1> reverse_iterator1;
  1260         typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
  1261         typedef reverse_iterator_base2<iterator2> reverse_iterator2;
  1262 
  1263         // Element lookup
  1264         BOOST_UBLAS_INLINE
  1265         const_iterator1 find1 (int rank, size_type i, size_type j) const {
  1266             if (rank == 1) {
  1267                 size_type lower_i = (std::max) (difference_type (j - upper_), difference_type (0));
  1268                 i = (std::max) (i, lower_i);
  1269                 size_type upper_i = (std::min) (j + 1 + lower_, size1 ());
  1270                 i = (std::min) (i, upper_i);
  1271             }
  1272             return const_iterator1 (*this, data ().find1 (rank, i, j));
  1273         }
  1274         BOOST_UBLAS_INLINE
  1275         iterator1 find1 (int rank, size_type i, size_type j) {
  1276             if (rank == 1) {
  1277                 size_type lower_i = (std::max) (difference_type (j - upper_), difference_type (0));
  1278                 i = (std::max) (i, lower_i);
  1279                 size_type upper_i = (std::min) (j + 1 + lower_, size1 ());
  1280                 i = (std::min) (i, upper_i);
  1281             }
  1282             return iterator1 (*this, data ().find1 (rank, i, j));
  1283         }
  1284         BOOST_UBLAS_INLINE
  1285         const_iterator2 find2 (int rank, size_type i, size_type j) const {
  1286             if (rank == 1) {
  1287                 size_type lower_j = (std::max) (difference_type (i - lower_), difference_type (0));
  1288                 j = (std::max) (j, lower_j);
  1289                 size_type upper_j = (std::min) (i + 1 + upper_, size2 ());
  1290                 j = (std::min) (j, upper_j);
  1291             }
  1292             return const_iterator2 (*this, data ().find2 (rank, i, j));
  1293         }
  1294         BOOST_UBLAS_INLINE
  1295         iterator2 find2 (int rank, size_type i, size_type j) {
  1296             if (rank == 1) {
  1297                 size_type lower_j = (std::max) (difference_type (i - lower_), difference_type (0));
  1298                 j = (std::max) (j, lower_j);
  1299                 size_type upper_j = (std::min) (i + 1 + upper_, size2 ());
  1300                 j = (std::min) (j, upper_j);
  1301             }
  1302             return iterator2 (*this, data ().find2 (rank, i, j));
  1303         }
  1304 
  1305         // Iterators simply are indices.
  1306 
  1307 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
  1308         class const_iterator1:
  1309             public container_const_reference<banded_adaptor>,
  1310             public random_access_iterator_base<typename iterator_restrict_traits<
  1311                                                    typename const_subiterator1_type::iterator_category, packed_random_access_iterator_tag>::iterator_category,
  1312                                                const_iterator1, value_type> {
  1313         public:
  1314             typedef typename const_subiterator1_type::value_type value_type;
  1315             typedef typename const_subiterator1_type::difference_type difference_type;
  1316             typedef typename const_subiterator1_type::reference reference;
  1317             typedef typename const_subiterator1_type::pointer pointer;
  1318 
  1319             typedef const_iterator2 dual_iterator_type;
  1320             typedef const_reverse_iterator2 dual_reverse_iterator_type;
  1321 
  1322             // Construction and destruction
  1323             BOOST_UBLAS_INLINE
  1324             const_iterator1 ():
  1325                 container_const_reference<self_type> (), it1_ () {}
  1326             BOOST_UBLAS_INLINE
  1327             const_iterator1 (const self_type &m, const const_subiterator1_type &it1):
  1328                 container_const_reference<self_type> (m), it1_ (it1) {}
  1329             BOOST_UBLAS_INLINE
  1330             const_iterator1 (const iterator1 &it):
  1331                 container_const_reference<self_type> (it ()), it1_ (it.it1_) {}
  1332 
  1333             // Arithmetic
  1334             BOOST_UBLAS_INLINE
  1335             const_iterator1 &operator ++ () {
  1336                 ++ it1_;
  1337                 return *this;
  1338             }
  1339             BOOST_UBLAS_INLINE
  1340             const_iterator1 &operator -- () {
  1341                 -- it1_;
  1342                 return *this;
  1343             }
  1344             BOOST_UBLAS_INLINE
  1345             const_iterator1 &operator += (difference_type n) {
  1346                 it1_ += n;
  1347                 return *this;
  1348             }
  1349             BOOST_UBLAS_INLINE
  1350             const_iterator1 &operator -= (difference_type n) {
  1351                 it1_ -= n;
  1352                 return *this;
  1353             }
  1354             BOOST_UBLAS_INLINE
  1355             difference_type operator - (const const_iterator1 &it) const {
  1356                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  1357                 return it1_ - it.it1_;
  1358             }
  1359 
  1360             // Dereference
  1361             BOOST_UBLAS_INLINE
  1362             const_reference operator * () const {
  1363                 size_type i = index1 ();
  1364                 size_type j = index2 ();
  1365                 BOOST_UBLAS_CHECK (i < (*this) ().size1 (), bad_index ());
  1366                 BOOST_UBLAS_CHECK (j < (*this) ().size2 (), bad_index ());
  1367 #ifdef BOOST_UBLAS_OWN_BANDED
  1368                 size_type k = (std::max) (i, j);
  1369                 size_type l = (*this) ().lower () + j - i;
  1370                 if (k < (std::max) ((*this) ().size1 (), (*this) ().size2 ()) &&
  1371                     l < (*this) ().lower () + 1 + (*this) ().upper ())
  1372                     return *it1_;
  1373 #else
  1374                 size_type k = j;
  1375                 size_type l = (*this) ().upper () + i - j;
  1376                 if (k < (*this) ().size2 () &&
  1377                     l < (*this) ().lower () + 1 + (*this) ().upper ())
  1378                     return *it1_;
  1379 #endif
  1380                 return (*this) () (i, j);
  1381             }
  1382             BOOST_UBLAS_INLINE
  1383             const_reference operator [] (difference_type n) const {
  1384                 return *(*this + n);
  1385             }
  1386 
  1387 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
  1388             BOOST_UBLAS_INLINE
  1389 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1390             typename self_type::
  1391 #endif
  1392             const_iterator2 begin () const {
  1393                 return (*this) ().find2 (1, index1 (), 0);
  1394             }
  1395             BOOST_UBLAS_INLINE
  1396 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1397             typename self_type::
  1398 #endif
  1399             const_iterator2 end () const {
  1400                 return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
  1401             }
  1402             BOOST_UBLAS_INLINE
  1403 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1404             typename self_type::
  1405 #endif
  1406             const_reverse_iterator2 rbegin () const {
  1407                 return const_reverse_iterator2 (end ());
  1408             }
  1409             BOOST_UBLAS_INLINE
  1410 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1411             typename self_type::
  1412 #endif
  1413             const_reverse_iterator2 rend () const {
  1414                 return const_reverse_iterator2 (begin ());
  1415             }
  1416 #endif
  1417 
  1418             // Indices
  1419             BOOST_UBLAS_INLINE
  1420             size_type index1 () const {
  1421                 return it1_.index1 ();
  1422             }
  1423             BOOST_UBLAS_INLINE
  1424             size_type index2 () const {
  1425                 return it1_.index2 ();
  1426             }
  1427 
  1428             // Assignment
  1429             BOOST_UBLAS_INLINE
  1430             const_iterator1 &operator = (const const_iterator1 &it) {
  1431                 container_const_reference<self_type>::assign (&it ());
  1432                 it1_ = it.it1_;
  1433                 return *this;
  1434             }
  1435 
  1436             // Comparison
  1437             BOOST_UBLAS_INLINE
  1438             bool operator == (const const_iterator1 &it) const {
  1439                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  1440                 return it1_ == it.it1_;
  1441             }
  1442             BOOST_UBLAS_INLINE
  1443             bool operator < (const const_iterator1 &it) const {
  1444                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  1445                 return it1_ < it.it1_;
  1446             }
  1447 
  1448         private:
  1449             const_subiterator1_type it1_;
  1450         };
  1451 #endif
  1452 
  1453         BOOST_UBLAS_INLINE
  1454         const_iterator1 begin1 () const {
  1455             return find1 (0, 0, 0);
  1456         }
  1457         BOOST_UBLAS_INLINE
  1458         const_iterator1 end1 () const {
  1459             return find1 (0, size1 (), 0);
  1460         }
  1461 
  1462 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
  1463         class iterator1:
  1464             public container_reference<banded_adaptor>,
  1465             public random_access_iterator_base<typename iterator_restrict_traits<
  1466                                                    typename subiterator1_type::iterator_category, packed_random_access_iterator_tag>::iterator_category,
  1467                                                iterator1, value_type> {
  1468         public:
  1469             typedef typename subiterator1_type::value_type value_type;
  1470             typedef typename subiterator1_type::difference_type difference_type;
  1471             typedef typename subiterator1_type::reference reference;
  1472             typedef typename subiterator1_type::pointer pointer;
  1473 
  1474             typedef iterator2 dual_iterator_type;
  1475             typedef reverse_iterator2 dual_reverse_iterator_type;
  1476 
  1477             // Construction and destruction
  1478             BOOST_UBLAS_INLINE
  1479             iterator1 ():
  1480                 container_reference<self_type> (), it1_ () {}
  1481             BOOST_UBLAS_INLINE
  1482             iterator1 (self_type &m, const subiterator1_type &it1):
  1483                 container_reference<self_type> (m), it1_ (it1) {}
  1484 
  1485             // Arithmetic
  1486             BOOST_UBLAS_INLINE
  1487             iterator1 &operator ++ () {
  1488                 ++ it1_;
  1489                 return *this;
  1490             }
  1491             BOOST_UBLAS_INLINE
  1492             iterator1 &operator -- () {
  1493                 -- it1_;
  1494                 return *this;
  1495             }
  1496             BOOST_UBLAS_INLINE
  1497             iterator1 &operator += (difference_type n) {
  1498                 it1_ += n;
  1499                 return *this;
  1500             }
  1501             BOOST_UBLAS_INLINE
  1502             iterator1 &operator -= (difference_type n) {
  1503                 it1_ -= n;
  1504                 return *this;
  1505             }
  1506             BOOST_UBLAS_INLINE
  1507             difference_type operator - (const iterator1 &it) const {
  1508                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  1509                 return it1_ - it.it1_;
  1510             }
  1511 
  1512             // Dereference
  1513             BOOST_UBLAS_INLINE
  1514             reference operator * () const {
  1515                 size_type i = index1 ();
  1516                 size_type j = index2 ();
  1517                 BOOST_UBLAS_CHECK (i < (*this) ().size1 (), bad_index ());
  1518                 BOOST_UBLAS_CHECK (j < (*this) ().size2 (), bad_index ());
  1519 #ifdef BOOST_UBLAS_OWN_BANDED
  1520                 size_type k = (std::max) (i, j);
  1521                 size_type l = (*this) ().lower () + j - i;
  1522                 if (k < (std::max) ((*this) ().size1 (), (*this) ().size2 ()) &&
  1523                     l < (*this) ().lower () + 1 + (*this) ().upper ())
  1524                     return *it1_;
  1525 #else
  1526                 size_type k = j;
  1527                 size_type l = (*this) ().upper () + i - j;
  1528                 if (k < (*this) ().size2 () &&
  1529                     l < (*this) ().lower () + 1 + (*this) ().upper ())
  1530                     return *it1_;
  1531 #endif
  1532                 return (*this) () (i, j);
  1533             }
  1534             BOOST_UBLAS_INLINE
  1535             reference operator [] (difference_type n) const {
  1536                 return *(*this + n);
  1537             }
  1538 
  1539 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
  1540             BOOST_UBLAS_INLINE
  1541 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1542             typename self_type::
  1543 #endif
  1544             iterator2 begin () const {
  1545                 return (*this) ().find2 (1, index1 (), 0);
  1546             }
  1547             BOOST_UBLAS_INLINE
  1548 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1549             typename self_type::
  1550 #endif
  1551             iterator2 end () const {
  1552                 return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
  1553             }
  1554             BOOST_UBLAS_INLINE
  1555 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1556             typename self_type::
  1557 #endif
  1558             reverse_iterator2 rbegin () const {
  1559                 return reverse_iterator2 (end ());
  1560             }
  1561             BOOST_UBLAS_INLINE
  1562 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1563             typename self_type::
  1564 #endif
  1565             reverse_iterator2 rend () const {
  1566                 return reverse_iterator2 (begin ());
  1567             }
  1568 #endif
  1569 
  1570             // Indices
  1571             BOOST_UBLAS_INLINE
  1572             size_type index1 () const {
  1573                 return it1_.index1 ();
  1574             }
  1575             BOOST_UBLAS_INLINE
  1576             size_type index2 () const {
  1577                 return it1_.index2 ();
  1578             }
  1579 
  1580             // Assignment
  1581             BOOST_UBLAS_INLINE
  1582             iterator1 &operator = (const iterator1 &it) {
  1583                 container_reference<self_type>::assign (&it ());
  1584                 it1_ = it.it1_;
  1585                 return *this;
  1586             }
  1587 
  1588             // Comparison
  1589             BOOST_UBLAS_INLINE
  1590             bool operator == (const iterator1 &it) const {
  1591                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  1592                 return it1_ == it.it1_;
  1593             }
  1594             BOOST_UBLAS_INLINE
  1595             bool operator < (const iterator1 &it) const {
  1596                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  1597                 return it1_ < it.it1_;
  1598             }
  1599 
  1600         private:
  1601             subiterator1_type it1_;
  1602 
  1603             friend class const_iterator1;
  1604         };
  1605 #endif
  1606 
  1607         BOOST_UBLAS_INLINE
  1608         iterator1 begin1 () {
  1609             return find1 (0, 0, 0);
  1610         }
  1611         BOOST_UBLAS_INLINE
  1612         iterator1 end1 () {
  1613             return find1 (0, size1 (), 0);
  1614         }
  1615 
  1616 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
  1617         class const_iterator2:
  1618             public container_const_reference<banded_adaptor>,
  1619             public random_access_iterator_base<packed_random_access_iterator_tag,
  1620                                                const_iterator2, value_type> {
  1621         public:
  1622             typedef typename iterator_restrict_traits<typename const_subiterator2_type::iterator_category,
  1623                                                       packed_random_access_iterator_tag>::iterator_category iterator_category;
  1624             typedef typename const_subiterator2_type::value_type value_type;
  1625             typedef typename const_subiterator2_type::difference_type difference_type;
  1626             typedef typename const_subiterator2_type::reference reference;
  1627             typedef typename const_subiterator2_type::pointer pointer;
  1628 
  1629             typedef const_iterator1 dual_iterator_type;
  1630             typedef const_reverse_iterator1 dual_reverse_iterator_type;
  1631 
  1632             // Construction and destruction
  1633             BOOST_UBLAS_INLINE
  1634             const_iterator2 ():
  1635                 container_const_reference<self_type> (), it2_ () {}
  1636             BOOST_UBLAS_INLINE
  1637             const_iterator2 (const self_type &m, const const_subiterator2_type &it2):
  1638                 container_const_reference<self_type> (m), it2_ (it2) {}
  1639             BOOST_UBLAS_INLINE
  1640             const_iterator2 (const iterator2 &it):
  1641                 container_const_reference<self_type> (it ()), it2_ (it.it2_) {}
  1642 
  1643             // Arithmetic
  1644             BOOST_UBLAS_INLINE
  1645             const_iterator2 &operator ++ () {
  1646                 ++ it2_;
  1647                 return *this;
  1648             }
  1649             BOOST_UBLAS_INLINE
  1650             const_iterator2 &operator -- () {
  1651                 -- it2_;
  1652                 return *this;
  1653             }
  1654             BOOST_UBLAS_INLINE
  1655             const_iterator2 &operator += (difference_type n) {
  1656                 it2_ += n;
  1657                 return *this;
  1658             }
  1659             BOOST_UBLAS_INLINE
  1660             const_iterator2 &operator -= (difference_type n) {
  1661                 it2_ -= n;
  1662                 return *this;
  1663             }
  1664             BOOST_UBLAS_INLINE
  1665             difference_type operator - (const const_iterator2 &it) const {
  1666                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  1667                 return it2_ - it.it2_;
  1668             }
  1669 
  1670             // Dereference
  1671             BOOST_UBLAS_INLINE
  1672             const_reference operator * () const {
  1673                 size_type i = index1 ();
  1674                 size_type j = index2 ();
  1675                 BOOST_UBLAS_CHECK (i < (*this) ().size1 (), bad_index ());
  1676                 BOOST_UBLAS_CHECK (j < (*this) ().size2 (), bad_index ());
  1677 #ifdef BOOST_UBLAS_OWN_BANDED
  1678                 size_type k = (std::max) (i, j);
  1679                 size_type l = (*this) ().lower () + j - i;
  1680                 if (k < (std::max) ((*this) ().size1 (), (*this) ().size2 ()) &&
  1681                     l < (*this) ().lower () + 1 + (*this) ().upper ())
  1682                     return *it2_;
  1683 #else
  1684                 size_type k = j;
  1685                 size_type l = (*this) ().upper () + i - j;
  1686                 if (k < (*this) ().size2 () &&
  1687                     l < (*this) ().lower () + 1 + (*this) ().upper ())
  1688                     return *it2_;
  1689 #endif
  1690                 return (*this) () (i, j);
  1691             }
  1692             BOOST_UBLAS_INLINE
  1693             const_reference operator [] (difference_type n) const {
  1694                 return *(*this + n);
  1695             }
  1696 
  1697 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
  1698             BOOST_UBLAS_INLINE
  1699 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1700             typename self_type::
  1701 #endif
  1702             const_iterator1 begin () const {
  1703                 return (*this) ().find1 (1, 0, index2 ());
  1704             }
  1705             BOOST_UBLAS_INLINE
  1706 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1707             typename self_type::
  1708 #endif
  1709             const_iterator1 end () const {
  1710                 return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
  1711             }
  1712             BOOST_UBLAS_INLINE
  1713 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1714             typename self_type::
  1715 #endif
  1716             const_reverse_iterator1 rbegin () const {
  1717                 return const_reverse_iterator1 (end ());
  1718             }
  1719             BOOST_UBLAS_INLINE
  1720 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1721             typename self_type::
  1722 #endif
  1723             const_reverse_iterator1 rend () const {
  1724                 return const_reverse_iterator1 (begin ());
  1725             }
  1726 #endif
  1727 
  1728             // Indices
  1729             BOOST_UBLAS_INLINE
  1730             size_type index1 () const {
  1731                 return it2_.index1 ();
  1732             }
  1733             BOOST_UBLAS_INLINE
  1734             size_type index2 () const {
  1735                 return it2_.index2 ();
  1736             }
  1737 
  1738             // Assignment
  1739             BOOST_UBLAS_INLINE
  1740             const_iterator2 &operator = (const const_iterator2 &it) {
  1741                 container_const_reference<self_type>::assign (&it ());
  1742                 it2_ = it.it2_;
  1743                 return *this;
  1744             }
  1745 
  1746             // Comparison
  1747             BOOST_UBLAS_INLINE
  1748             bool operator == (const const_iterator2 &it) const {
  1749                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  1750                 return it2_ == it.it2_;
  1751             }
  1752             BOOST_UBLAS_INLINE
  1753             bool operator < (const const_iterator2 &it) const {
  1754                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  1755                 return it2_ < it.it2_;
  1756             }
  1757 
  1758         private:
  1759             const_subiterator2_type it2_;
  1760         };
  1761 #endif
  1762 
  1763         BOOST_UBLAS_INLINE
  1764         const_iterator2 begin2 () const {
  1765             return find2 (0, 0, 0);
  1766         }
  1767         BOOST_UBLAS_INLINE
  1768         const_iterator2 end2 () const {
  1769             return find2 (0, 0, size2 ());
  1770         }
  1771 
  1772 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
  1773         class iterator2:
  1774             public container_reference<banded_adaptor>,
  1775             public random_access_iterator_base<typename iterator_restrict_traits<
  1776                                                    typename subiterator2_type::iterator_category, packed_random_access_iterator_tag>::iterator_category,
  1777                                                iterator2, value_type> {
  1778         public:
  1779             typedef typename subiterator2_type::value_type value_type;
  1780             typedef typename subiterator2_type::difference_type difference_type;
  1781             typedef typename subiterator2_type::reference reference;
  1782             typedef typename subiterator2_type::pointer pointer;
  1783 
  1784             typedef iterator1 dual_iterator_type;
  1785             typedef reverse_iterator1 dual_reverse_iterator_type;
  1786 
  1787             // Construction and destruction
  1788             BOOST_UBLAS_INLINE
  1789             iterator2 ():
  1790                 container_reference<self_type> (), it2_ () {}
  1791             BOOST_UBLAS_INLINE
  1792             iterator2 (self_type &m, const subiterator2_type &it2):
  1793                 container_reference<self_type> (m), it2_ (it2) {}
  1794 
  1795             // Arithmetic
  1796             BOOST_UBLAS_INLINE
  1797             iterator2 &operator ++ () {
  1798                 ++ it2_;
  1799                 return *this;
  1800             }
  1801             BOOST_UBLAS_INLINE
  1802             iterator2 &operator -- () {
  1803                 -- it2_;
  1804                 return *this;
  1805             }
  1806             BOOST_UBLAS_INLINE
  1807             iterator2 &operator += (difference_type n) {
  1808                 it2_ += n;
  1809                 return *this;
  1810             }
  1811             BOOST_UBLAS_INLINE
  1812             iterator2 &operator -= (difference_type n) {
  1813                 it2_ -= n;
  1814                 return *this;
  1815             }
  1816             BOOST_UBLAS_INLINE
  1817             difference_type operator - (const iterator2 &it) const {
  1818                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  1819                 return it2_ - it.it2_;
  1820             }
  1821 
  1822             // Dereference
  1823             BOOST_UBLAS_INLINE
  1824             reference operator * () const {
  1825                 size_type i = index1 ();
  1826                 size_type j = index2 ();
  1827                 BOOST_UBLAS_CHECK (i < (*this) ().size1 (), bad_index ());
  1828                 BOOST_UBLAS_CHECK (j < (*this) ().size2 (), bad_index ());
  1829 #ifdef BOOST_UBLAS_OWN_BANDED
  1830                 size_type k = (std::max) (i, j);
  1831                 size_type l = (*this) ().lower () + j - i;
  1832                 if (k < (std::max) ((*this) ().size1 (), (*this) ().size2 ()) &&
  1833                     l < (*this) ().lower () + 1 + (*this) ().upper ())
  1834                     return *it2_;
  1835 #else
  1836                 size_type k = j;
  1837                 size_type l = (*this) ().upper () + i - j;
  1838                 if (k < (*this) ().size2 () &&
  1839                     l < (*this) ().lower () + 1 + (*this) ().upper ())
  1840                     return *it2_;
  1841 #endif
  1842                 return (*this) () (i, j);
  1843             }
  1844             BOOST_UBLAS_INLINE
  1845             reference operator [] (difference_type n) const {
  1846                 return *(*this + n);
  1847             }
  1848 
  1849 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
  1850             BOOST_UBLAS_INLINE
  1851 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1852             typename self_type::
  1853 #endif
  1854             iterator1 begin () const {
  1855                 return (*this) ().find1 (1, 0, index2 ());
  1856             }
  1857             BOOST_UBLAS_INLINE
  1858 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1859             typename self_type::
  1860 #endif
  1861             iterator1 end () const {
  1862                 return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
  1863             }
  1864             BOOST_UBLAS_INLINE
  1865 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1866             typename self_type::
  1867 #endif
  1868             reverse_iterator1 rbegin () const {
  1869                 return reverse_iterator1 (end ());
  1870             }
  1871             BOOST_UBLAS_INLINE
  1872 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1873             typename self_type::
  1874 #endif
  1875             reverse_iterator1 rend () const {
  1876                 return reverse_iterator1 (begin ());
  1877             }
  1878 #endif
  1879 
  1880             // Indices
  1881             BOOST_UBLAS_INLINE
  1882             size_type index1 () const {
  1883                 return it2_.index1 ();
  1884             }
  1885             BOOST_UBLAS_INLINE
  1886             size_type index2 () const {
  1887                 return it2_.index2 ();
  1888             }
  1889 
  1890             // Assignment
  1891             BOOST_UBLAS_INLINE
  1892             iterator2 &operator = (const iterator2 &it) {
  1893                 container_reference<self_type>::assign (&it ());
  1894                 it2_ = it.it2_;
  1895                 return *this;
  1896             }
  1897 
  1898             // Comparison
  1899             BOOST_UBLAS_INLINE
  1900             bool operator == (const iterator2 &it) const {
  1901                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  1902                 return it2_ == it.it2_;
  1903             }
  1904             BOOST_UBLAS_INLINE
  1905             bool operator < (const iterator2 &it) const {
  1906                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  1907                 return it2_ < it.it2_;
  1908             }
  1909 
  1910         private:
  1911             subiterator2_type it2_;
  1912 
  1913             friend class const_iterator2;
  1914         };
  1915 #endif
  1916 
  1917         BOOST_UBLAS_INLINE
  1918         iterator2 begin2 () {
  1919             return find2 (0, 0, 0);
  1920         }
  1921         BOOST_UBLAS_INLINE
  1922         iterator2 end2 () {
  1923             return find2 (0, 0, size2 ());
  1924         }
  1925 
  1926         // Reverse iterators
  1927 
  1928         BOOST_UBLAS_INLINE
  1929         const_reverse_iterator1 rbegin1 () const {
  1930             return const_reverse_iterator1 (end1 ());
  1931         }
  1932         BOOST_UBLAS_INLINE
  1933         const_reverse_iterator1 rend1 () const {
  1934             return const_reverse_iterator1 (begin1 ());
  1935         }
  1936 
  1937         BOOST_UBLAS_INLINE
  1938         reverse_iterator1 rbegin1 () {
  1939             return reverse_iterator1 (end1 ());
  1940         }
  1941         BOOST_UBLAS_INLINE
  1942         reverse_iterator1 rend1 () {
  1943             return reverse_iterator1 (begin1 ());
  1944         }
  1945 
  1946         BOOST_UBLAS_INLINE
  1947         const_reverse_iterator2 rbegin2 () const {
  1948             return const_reverse_iterator2 (end2 ());
  1949         }
  1950         BOOST_UBLAS_INLINE
  1951         const_reverse_iterator2 rend2 () const {
  1952             return const_reverse_iterator2 (begin2 ());
  1953         }
  1954 
  1955         BOOST_UBLAS_INLINE
  1956         reverse_iterator2 rbegin2 () {
  1957             return reverse_iterator2 (end2 ());
  1958         }
  1959         BOOST_UBLAS_INLINE
  1960         reverse_iterator2 rend2 () {
  1961             return reverse_iterator2 (begin2 ());
  1962         }
  1963 
  1964     private:
  1965         matrix_closure_type data_;
  1966         size_type lower_;
  1967         size_type upper_;
  1968         typedef const value_type const_value_type;
  1969         static const_value_type zero_;
  1970     };
  1971 
  1972     // Specialization for temporary_traits
  1973     template <class M>
  1974     struct vector_temporary_traits< banded_adaptor<M> >
  1975     : vector_temporary_traits< M > {} ;
  1976     template <class M>
  1977     struct vector_temporary_traits< const banded_adaptor<M> >
  1978     : vector_temporary_traits< M > {} ;
  1979 
  1980     template <class M>
  1981     struct matrix_temporary_traits< banded_adaptor<M> >
  1982     : matrix_temporary_traits< M > {} ;
  1983     template <class M>
  1984     struct matrix_temporary_traits< const banded_adaptor<M> >
  1985     : matrix_temporary_traits< M > {} ;
  1986 
  1987 
  1988     template<class M>
  1989     typename banded_adaptor<M>::const_value_type banded_adaptor<M>::zero_ = value_type/*zero*/();
  1990 
  1991     // Diagonal matrix adaptor class
  1992     template<class M>
  1993     class diagonal_adaptor:
  1994         public banded_adaptor<M> {
  1995     public:
  1996         typedef M matrix_type;
  1997         typedef banded_adaptor<M> adaptor_type;
  1998 
  1999         // Construction and destruction
  2000         BOOST_UBLAS_INLINE
  2001         diagonal_adaptor ():
  2002             adaptor_type () {}
  2003         BOOST_UBLAS_INLINE
  2004         diagonal_adaptor (matrix_type &data):
  2005             adaptor_type (data) {}
  2006         BOOST_UBLAS_INLINE
  2007         ~diagonal_adaptor () {}
  2008 
  2009         // Assignment
  2010         BOOST_UBLAS_INLINE
  2011         diagonal_adaptor &operator = (const diagonal_adaptor &m) {
  2012             adaptor_type::operator = (m);
  2013             return *this;
  2014         }
  2015         template<class AE>
  2016         BOOST_UBLAS_INLINE
  2017         diagonal_adaptor &operator = (const matrix_expression<AE> &ae) {
  2018             adaptor_type::operator = (ae);
  2019             return *this;
  2020         }
  2021     };
  2022 
  2023 }}}
  2024 
  2025 #endif