//

//  Copyright (c) 2000-2002

//  Joerg Walter, Mathias Koch

//

//  Permission to use, copy, modify, distribute and sell this software

//  and its documentation for any purpose is hereby granted without fee,

//  provided that the above copyright notice appear in all copies and

//  that both that copyright notice and this permission notice appear

//  in supporting documentation.  The authors make no representations

//  about the suitability of this software for any purpose.

//  It is provided "as is" without express or implied warranty.

//

//  The authors gratefully acknowledge the support of

//  GeNeSys mbH & Co. KG in producing this work.

//



#ifndef BOOST_UBLAS_ITERATOR_H

#define BOOST_UBLAS_ITERATOR_H



#include <iterator>



#include <boost/numeric/ublas/config.hpp>



// Using GCC the following is missing:

//

// namespace std {

//

//    template <class C, class T, class D = std::ptrdiff_t, class P = T *, class R = T &>

//    struct iterator {

//        typedef C iterator_category;

//        typedef T value_type;

//        typedef D difference_type;

//        typedef P pointer;

//        typedef R reference;

//    };

//

// }

//

// We therefore include the following header

#include <boost/iterator.hpp>

// and use namespace boost instead of std.



namespace boost { namespace numeric { namespace ublas {



#ifdef BOOST_UBLAS_NEED_CONVERSION

    template<class C>

    class container_reference;

#endif



    template<class C>

    class container_const_reference {

    public:

        typedef C container_type;

#ifdef BOOST_UBLAS_NEED_CONVERSION

        typedef container_reference<container_type> container_reference;

#endif



        BOOST_UBLAS_INLINE

        container_const_reference ():

            c_ (0) {}

        BOOST_UBLAS_INLINE

        container_const_reference (const container_type &c):

            c_ (&c) {}

#ifdef BOOST_UBLAS_NEED_CONVERSION

        BOOST_UBLAS_INLINE

        container_const_reference (const container_reference &c):

            c_ (c.c ()) {}

#endif



        BOOST_UBLAS_INLINE

        const container_type &operator () () const {

            return *c_;

        }



        BOOST_UBLAS_INLINE

        container_const_reference &assign (const container_type *c) {

            c_ = c;

            return *this;

        }



    private:

        const container_type *c_;



        container_const_reference &operator = (const container_const_reference &) {

            return *this;

        }

    };



    template<class C>

    class container_reference {

    public:

        typedef C container_type;



        BOOST_UBLAS_INLINE

        container_reference ():

            c_ (0) {}

        BOOST_UBLAS_INLINE

        container_reference (container_type &c):

            c_ (&c) {}



        BOOST_UBLAS_INLINE

        container_type &operator () () const {

           return *c_;

        }



        BOOST_UBLAS_INLINE

        container_reference &assign (container_type *c) {

            c_ = c;

            return *this;

        }



    private:

        container_type *c_;



        container_reference operator = (const container_reference &) {

            return *this;

        }

    };



    template<class IC, class I, class T>

    struct forward_iterator_base:

        public boost::iterator<IC, T> {

        typedef I derived_iterator_type;

        typedef T derived_value_type;



        // Arithmetic

        BOOST_UBLAS_INLINE

        derived_iterator_type operator ++ (int) {

            derived_iterator_type &d (*static_cast<const derived_iterator_type *> (this));

            derived_iterator_type tmp (d);

            ++ d;

            return tmp;

        }

#ifdef BOOST_UBLAS_FRIEND_FUNCTION

        BOOST_UBLAS_INLINE

        friend derived_iterator_type operator ++ (derived_iterator_type &d, int) {

            derived_iterator_type tmp (d);

            ++ d;

            return tmp;

        }

#endif



        // Comparison

        BOOST_UBLAS_INLINE

        bool operator != (const derived_iterator_type &it) const {

            const derived_iterator_type *d = static_cast<const derived_iterator_type *> (this);

            return ! (*d == it);

        }

    };



#ifndef BOOST_UBLAS_FRIEND_FUNCTION

    template<class IC, class I, class T>

    BOOST_UBLAS_INLINE

    typename forward_iterator_base<IC, I, T>::derived_iterator_type operator ++ (forward_iterator_base<IC, I, T> &it, int) {

        typedef BOOST_UBLAS_TYPENAME forward_iterator_base<IC, I, T>::derived_iterator_type derived_iterator_type;

        derived_iterator_type &d (static_cast<derived_iterator_type &> (it));

        derived_iterator_type tmp (d);

        ++ d;

        return tmp;

    }

#endif



    template<class IC, class I, class T>

    struct bidirectional_iterator_base:

        public boost::iterator<IC, T> {

        typedef I derived_iterator_type;

        typedef T derived_value_type;



        // Arithmetic

        BOOST_UBLAS_INLINE

        derived_iterator_type operator ++ (int) {

            derived_iterator_type &d (*static_cast<const derived_iterator_type *> (this));

            derived_iterator_type tmp (d);

            ++ d;

            return tmp;

        }

#ifdef BOOST_UBLAS_FRIEND_FUNCTION

        BOOST_UBLAS_INLINE

        friend derived_iterator_type operator ++ (derived_iterator_type &d, int) {

            derived_iterator_type tmp (d);

            ++ d;

            return tmp;

        }

#endif

        BOOST_UBLAS_INLINE

        derived_iterator_type operator -- (int) {

            derived_iterator_type &d (*static_cast<const derived_iterator_type *> (this));

            derived_iterator_type tmp (d);

            -- d;

            return tmp;

        }

#ifdef BOOST_UBLAS_FRIEND_FUNCTION

        BOOST_UBLAS_INLINE

        friend derived_iterator_type operator -- (derived_iterator_type &d, int) {

            derived_iterator_type tmp (d);

            -- d;

            return tmp;

        }

#endif



        // Comparison

        BOOST_UBLAS_INLINE

        bool operator != (const derived_iterator_type &it) const {

            const derived_iterator_type *d = static_cast<const derived_iterator_type *> (this);

            return ! (*d == it);

        }

    };



#ifndef BOOST_UBLAS_FRIEND_FUNCTION

    template<class IC, class I, class T>

    BOOST_UBLAS_INLINE

    typename bidirectional_iterator_base<IC, I, T>::derived_iterator_type operator ++ (bidirectional_iterator_base<IC, I, T> &it, int) {
        typedef BOOST_UBLAS_TYPENAME bidirectional_iterator_base<IC, I, T>::derived_iterator_type derived_iterator_type;

        derived_iterator_type &d (static_cast<derived_iterator_type &> (it));

        derived_iterator_type tmp (d);

        ++ d;

        return tmp;

    }

    template<class IC, class I, class T>

    BOOST_UBLAS_INLINE

    typename bidirectional_iterator_base<IC, I, T>::derived_iterator_type operator -- (bidirectional_iterator_base<IC, I, T> &it, int) {

        typedef BOOST_UBLAS_TYPENAME bidirectional_iterator_base<IC, I, T>::derived_iterator_type derived_iterator_type;

        derived_iterator_type &d (static_cast<derived_iterator_type &> (it));

        derived_iterator_type tmp (d);

        -- d;

        return tmp;

    }

#endif



    template<class IC, class I, class T, class D = std::ptrdiff_t>

    struct random_access_iterator_base:

        public boost::iterator<IC, T> {

        typedef I derived_iterator_type;

        typedef T derived_value_type;

        typedef D derived_difference_type;
#ifdef BOOST_MSVC_STD_ITERATOR

        typedef D difference_type;

#endif



        // Arithmetic

        BOOST_UBLAS_INLINE

        derived_iterator_type operator ++ (int) {

            derived_iterator_type &d (*static_cast<derived_iterator_type *> (this));

            derived_iterator_type tmp (d);

            ++ d;

            return tmp;

        }

#ifdef BOOST_UBLAS_FRIEND_FUNCTION

        BOOST_UBLAS_INLINE

        friend derived_iterator_type operator ++ (derived_iterator_type &d, int) {

            derived_iterator_type tmp (d);

            ++ d;

            return tmp;

        }

#endif

        BOOST_UBLAS_INLINE

        derived_iterator_type operator -- (int) {

            derived_iterator_type &d (*static_cast<derived_iterator_type *> (this));

            derived_iterator_type tmp (d);

            -- d;

            return tmp;

        }

#ifdef BOOST_UBLAS_FRIEND_FUNCTION

        BOOST_UBLAS_INLINE

        friend derived_iterator_type operator -- (derived_iterator_type &d, int) {

            derived_iterator_type tmp (d);

            -- d;

            return tmp;

        }

#endif

        BOOST_UBLAS_INLINE

        derived_iterator_type operator + (derived_difference_type n) const {

            derived_iterator_type tmp (*static_cast<const derived_iterator_type *> (this));

            return tmp += n;

        }

#ifdef BOOST_UBLAS_FRIEND_FUNCTION

        BOOST_UBLAS_INLINE

        friend derived_iterator_type operator + (const derived_iterator_type &d, derived_difference_type n) {

            derived_iterator_type tmp (d);

            return tmp += n;

        }

#endif

        BOOST_UBLAS_INLINE

        derived_iterator_type operator - (derived_difference_type n) const {

            derived_iterator_type tmp (*static_cast<const derived_iterator_type *> (this));

            return tmp -= n;

        }

#ifdef BOOST_UBLAS_FRIEND_FUNCTION

        BOOST_UBLAS_INLINE

        friend derived_iterator_type operator - (const derived_iterator_type &d, derived_difference_type n) {

            derived_iterator_type tmp (d);

            return tmp -= n;

        }

#endif



        // Comparison

        BOOST_UBLAS_INLINE

        bool operator != (const derived_iterator_type &it) const {

            const derived_iterator_type *d = static_cast<const derived_iterator_type *> (this);

            return ! (*d == it);

        }

        BOOST_UBLAS_INLINE

        bool operator <= (const derived_iterator_type &it) const {

            const derived_iterator_type *d = static_cast<const derived_iterator_type *> (this);

            return ! (it < *d);

        }

        BOOST_UBLAS_INLINE

        bool operator >= (const derived_iterator_type &it) const {

            const derived_iterator_type *d = static_cast<const derived_iterator_type *> (this);

            return ! (*d < it);

        }

        BOOST_UBLAS_INLINE

        bool operator > (const derived_iterator_type &it) const {

            const derived_iterator_type *d = static_cast<const derived_iterator_type *> (this);

            return it < *d;

        }

    };



#ifndef BOOST_UBLAS_FRIEND_FUNCTION

    template<class IC, class I, class T>

    BOOST_UBLAS_INLINE

    typename random_access_iterator_base<IC, I, T>::derived_iterator_type operator ++ (random_access_iterator_base<IC, I, T> &it, int) {

        typedef BOOST_UBLAS_TYPENAME random_access_iterator_base<IC, I, T>::derived_iterator_type derived_iterator_type;

        derived_iterator_type &d (static_cast<derived_iterator_type &> (it));

        derived_iterator_type tmp (d);

        ++ d;

        return tmp;

    }

    template<class IC, class I, class T>

    BOOST_UBLAS_INLINE

    typename random_access_iterator_base<IC, I, T>::derived_iterator_type operator -- (random_access_iterator_base<IC, I, T> &it, int) {

        typedef BOOST_UBLAS_TYPENAME random_access_iterator_base<IC, I, T>::derived_iterator_type derived_iterator_type;

        derived_iterator_type &d (static_cast<derived_iterator_type &> (it));

        derived_iterator_type tmp (d);

        -- d;

        return tmp;

    }

    template<class IC, class I, class T>

    BOOST_UBLAS_INLINE

    typename random_access_iterator_base<IC, I, T>::derived_iterator_type operator + (const random_access_iterator_base<IC, I, T> &it, std::ptrdiff_t n) {

        typedef BOOST_UBLAS_TYPENAME random_access_iterator_base<IC, I, T>::derived_iterator_type derived_iterator_type;

        derived_iterator_type tmp (static_cast<const derived_iterator_type &> (it));

        return tmp += n;

    }

    template<class IC, class I, class T>

    BOOST_UBLAS_INLINE

    typename random_access_iterator_base<IC, I, T>::derived_iterator_type operator - (const random_access_iterator_base<IC, I, T> &it, std::ptrdiff_t n) {

        typedef BOOST_UBLAS_TYPENAME random_access_iterator_base<IC, I, T>::derived_iterator_type derived_iterator_type;

        derived_iterator_type tmp (static_cast<const derived_iterator_type &> (it));

        return tmp -= n;

    }

#endif



#ifdef BOOST_MSVC_STD_ITERATOR


    // Renamed this class from reverse_iterator to get
    // typedef reverse_iterator<...> reverse_iterator
    // working. Thanks to Gabriel Dos Reis for explaining this.
    template <class I, class T, class R>
    class reverse_iterator_base:
        public std::reverse_bidirectional_iterator<I, T, R> {

    public:

        typedef std::size_t size_type;

        typedef std::ptrdiff_t difference_type;

        typedef I iterator_type;

        typedef T value_type;

        typedef R reference;

        typedef typename I::container_type container_type;



        // Construction and destruction

        BOOST_UBLAS_INLINE

        reverse_iterator_base ():

            std::reverse_bidirectional_iterator<iterator_type, value_type, reference> () {}

        BOOST_UBLAS_INLINE

        reverse_iterator_base (const iterator_type &it):

            std::reverse_bidirectional_iterator<iterator_type, value_type, reference> (it) {}



        // Arithmetic

        BOOST_UBLAS_INLINE

        reverse_iterator_base &operator += (difference_type n) {

            // Comeau recommends...

            return *this = this->base () - n;

        }

        BOOST_UBLAS_INLINE

        reverse_iterator_base &operator -= (difference_type n) {

            // Comeau recommends...

            return *this = this->base () + n;

        }



        BOOST_UBLAS_INLINE

        const container_type &operator () () const {

            // Comeau recommends...

            return this->base () ();

        }



        BOOST_UBLAS_INLINE

        size_type index () const {

            // Comeau recommends...

            iterator_type tmp (this->base ());

            return (-- tmp).index ();

        }



        // Comparison

        BOOST_UBLAS_INLINE

        bool operator < (const reverse_iterator_base &it) const {

            return ! (this->base () < it.base ());

        }

        BOOST_UBLAS_INLINE

        bool operator <= (const reverse_iterator_base &it) const {

            return ! (this->base () <= it.base ());

        }

        BOOST_UBLAS_INLINE

        bool operator >= (const reverse_iterator_base &it) const {

            return ! (this->base () >= it.base ());

        }

        BOOST_UBLAS_INLINE

        bool operator > (const reverse_iterator_base &it) const {

            return ! (this->base () > it.base ());

        }

    };



    template<class I, class T, class R>

    BOOST_UBLAS_INLINE

    reverse_iterator_base<I, T, R> operator + (const reverse_iterator_base<I, T, R> &it, std::ptrdiff_t n) {

        reverse_iterator_base<I, T, R> tmp (it);

        return tmp += n;

    }

    template<class I, class T, class R>

    BOOST_UBLAS_INLINE

    reverse_iterator_base<I, T, R> operator - (const reverse_iterator_base<I, T, R> &it, std::ptrdiff_t n) {

        reverse_iterator_base<I, T, R> tmp (it);

        return tmp -= n;

    }

    template<class I, class T, class R>

    BOOST_UBLAS_INLINE

    std::ptrdiff_t operator - (const reverse_iterator_base<I, T, R> &it1, const reverse_iterator_base<I, T, R> &it2) {

        return it2.base () - it1.base ();

    }


    // Renamed this class from reverse_iterator1 to get
    // typedef reverse_iterator1<...> reverse_iterator1
    // working. Thanks to Gabriel Dos Reis for explaining this.
    template <class I, class T, class R>
    class reverse_iterator_base1:
        public std::reverse_bidirectional_iterator<I, T, R> {

    public:

        typedef std::size_t size_type;

        typedef std::ptrdiff_t difference_type;

        typedef I iterator_type;

        typedef T value_type;

        typedef R reference;

        typedef typename I::container_type container_type;

#ifndef BOOST_UBLAS_USE_CANONICAL_ITERATOR

        typedef typename I::dual_iterator_type dual_iterator_type;

        typedef typename I::dual_reverse_iterator_type dual_reverse_iterator_type;
#endif



        // Construction and destruction

        BOOST_UBLAS_INLINE

        reverse_iterator_base1 ():

            std::reverse_bidirectional_iterator<iterator_type, value_type, reference> () {}

        BOOST_UBLAS_INLINE

        reverse_iterator_base1 (const iterator_type &it):

            std::reverse_bidirectional_iterator<iterator_type, value_type, reference> (it) {}



        // Arithmetic

        BOOST_UBLAS_INLINE

        reverse_iterator_base1 &operator += (difference_type n) {

            // Comeau recommends...

            return *this = this->base () - n;

        }

        BOOST_UBLAS_INLINE

        reverse_iterator_base1 &operator -= (difference_type n) {

            // Comeau recommends...

            return *this = this->base () + n;

        }



        BOOST_UBLAS_INLINE

        const container_type &operator () () const {

            // Comeau recommends...

            return this->base () ();

        }



        BOOST_UBLAS_INLINE

        size_type index1 () const {

            // Comeau recommends...

            iterator_type tmp (this->base ());

            return (-- tmp).index1 ();

        }

        BOOST_UBLAS_INLINE

        size_type index2 () const {

            // Comeau recommends...

            iterator_type tmp (this->base ());

            return (-- tmp).index2 ();

        }



#ifndef BOOST_UBLAS_USE_CANONICAL_ITERATOR

        BOOST_UBLAS_INLINE

        dual_iterator_type begin () const {

            // Comeau recommends...

            return this->base ().begin ();

        }

        BOOST_UBLAS_INLINE

        dual_iterator_type end () const {

            // Comeau recommends...

            return this->base ().end ();

        }

        BOOST_UBLAS_INLINE

        dual_reverse_iterator_type rbegin () const {
            return dual_reverse_iterator_type (end ());

        }

        BOOST_UBLAS_INLINE

        dual_reverse_iterator_type rend () const {

            return dual_reverse_iterator_type (begin ());

        }

#endif



        // Comparison

        BOOST_UBLAS_INLINE

        bool operator < (const reverse_iterator_base1 &it) const {

            return ! (this->base () < it.base ());

        }

        BOOST_UBLAS_INLINE

        bool operator <= (const reverse_iterator_base1 &it) const {

            return ! (this->base () <= it.base ());

        }

        BOOST_UBLAS_INLINE

        bool operator >= (const reverse_iterator_base1 &it) const {

            return ! (this->base () >= it.base ());

        }

        BOOST_UBLAS_INLINE

        bool operator > (const reverse_iterator_base1 &it) const {

            return ! (this->base () > it.base ());

        }

    };



    template<class I, class T, class R>

    BOOST_UBLAS_INLINE

    reverse_iterator_base1<I, T, R> operator + (const reverse_iterator_base1<I, T, R> &it, std::ptrdiff_t n) {

        reverse_iterator_base1<I, T, R> tmp (it);

        return tmp += n;

    }

    template<class I, class T, class R>

    BOOST_UBLAS_INLINE

    reverse_iterator_base1<I, T, R> operator - (const reverse_iterator_base1<I, T, R> &it, std::ptrdiff_t n) {

        reverse_iterator_base1<I, T, R> tmp (it);

        return tmp -= n;

    }

    template<class I, class T, class R>

    BOOST_UBLAS_INLINE

    std::ptrdiff_t operator - (const reverse_iterator_base1<I, T, R> &it1, const reverse_iterator_base1<I, T, R> &it2) {

        return it2.base () - it1.base ();

    }



    // Renamed this class from reverse_iterator2 to get
    // typedef reverse_iterator2<...> reverse_iterator2
    // working. Thanks to Gabriel Dos Reis for explaining this.
    template <class I, class T, class R>
    class reverse_iterator_base2:
        public std::reverse_bidirectional_iterator<I, T, R> {

    public:

        typedef std::size_t size_type;

        typedef std::ptrdiff_t difference_type;

        typedef I iterator_type;

        typedef T value_type;

        typedef R reference;

        typedef typename I::container_type container_type;

#ifndef BOOST_UBLAS_USE_CANONICAL_ITERATOR

        typedef typename I::dual_iterator_type dual_iterator_type;

        typedef typename I::dual_reverse_iterator_type dual_reverse_iterator_type;

#endif



        // Construction and destruction

        BOOST_UBLAS_INLINE

        reverse_iterator_base2 ():

            std::reverse_bidirectional_iterator<iterator_type, value_type, reference> () {}

        BOOST_UBLAS_INLINE

        reverse_iterator_base2 (const iterator_type &it):

            std::reverse_bidirectional_iterator<iterator_type, value_type, reference> (it) {}



        // Arithmetic

        BOOST_UBLAS_INLINE

        reverse_iterator_base2 &operator += (difference_type n) {

            // Comeau recommends...

            return *this = this->base () - n;

        }

        BOOST_UBLAS_INLINE

        reverse_iterator_base2 &operator -= (difference_type n) {

            // Comeau recommends...

            return *this = this->base () + n;

        }



        BOOST_UBLAS_INLINE

        const container_type &operator () () const {

            // Comeau recommends...

            return this->base () ();

        }



        BOOST_UBLAS_INLINE

        size_type index1 () const {

            // Comeau recommends...

            iterator_type tmp (this->base ());

            return (-- tmp).index1 ();

        }

        BOOST_UBLAS_INLINE

        size_type index2 () const {

            // Comeau recommends...

            iterator_type tmp (this->base ());

            return (-- tmp).index2 ();

        }



#ifndef BOOST_UBLAS_USE_CANONICAL_ITERATOR

        BOOST_UBLAS_INLINE

        dual_iterator_type begin () const {

            // Comeau recommends...

            return this->base ().begin ();

        }

        BOOST_UBLAS_INLINE

        dual_iterator_type end () const {

            // Comeau recommends...

            return this->base ().end ();

        }

        BOOST_UBLAS_INLINE

        dual_reverse_iterator_type rbegin () const {

            return dual_reverse_iterator_type (end ());

        }

        BOOST_UBLAS_INLINE

        dual_reverse_iterator_type rend () const {

            return dual_reverse_iterator_type (begin ());

        }

#endif



        // Comparison

        BOOST_UBLAS_INLINE

        bool operator < (const reverse_iterator_base2 &it) const {

            return ! (this->base () < it.base ());

        }

        BOOST_UBLAS_INLINE

        bool operator <= (const reverse_iterator_base2 &it) const {

            return ! (this->base () <= it.base ());

        }

        BOOST_UBLAS_INLINE

        bool operator >= (const reverse_iterator_base2 &it) const {

            return ! (this->base () >= it.base ());

        }

        BOOST_UBLAS_INLINE

        bool operator > (const reverse_iterator_base2 &it) const {

            return ! (this->base () > it.base ());

        }

    };



    template<class I, class T, class R>

    BOOST_UBLAS_INLINE

    reverse_iterator_base2<I, T, R> operator + (const reverse_iterator_base2<I, T, R> &it, std::ptrdiff_t n) {

        reverse_iterator_base2<I, T, R> tmp (it);

        return tmp += n;

    }

    template<class I, class T, class R>

    BOOST_UBLAS_INLINE

    reverse_iterator_base2<I, T, R> operator - (const reverse_iterator_base2<I, T, R> &it, std::ptrdiff_t n) {

        reverse_iterator_base2<I, T, R> tmp (it);

        return tmp -= n;

    }

    template<class I, class T, class R>

    BOOST_UBLAS_INLINE
    std::ptrdiff_t operator - (const reverse_iterator_base2<I, T, R> &it1, const reverse_iterator_base2<I, T, R> &it2) {
        return it2.base () - it1.base ();
    }



#else



    // Renamed this class from reverse_iterator to get
    // typedef reverse_iterator<...> reverse_iterator
    // working. Thanks to Gabriel Dos Reis for explaining this.
    template <class I>
    class reverse_iterator_base:
        public std::reverse_iterator<I> {

    public:

        typedef std::size_t size_type;

        typedef std::ptrdiff_t difference_type;

        typedef I iterator_type;

        typedef typename I::container_type container_type;



        // Construction and destruction

        BOOST_UBLAS_INLINE

        reverse_iterator_base ():
            std::reverse_iterator<iterator_type> () {}
        BOOST_UBLAS_INLINE

        reverse_iterator_base (const iterator_type &it):
            std::reverse_iterator<iterator_type> (it) {}


#ifdef BOOST_UBLAS_REVERSE_ITERATOR_OVERLOADS

        // Arithmetic

        BOOST_UBLAS_INLINE

        reverse_iterator_base &operator ++ () {

            // Comeau recommends...

            return *this = -- this->base ();

        }

        BOOST_UBLAS_INLINE

        reverse_iterator_base operator ++ (int) {

            // Comeau recommends...

            reverse_iterator_base tmp (*this);

            *this = -- this->base ();

            return tmp;

        }

        BOOST_UBLAS_INLINE

        reverse_iterator_base &operator -- () {

            // Comeau recommends...

            return *this = ++ this->base ();

        }

        BOOST_UBLAS_INLINE

        reverse_iterator_base operator -- (int) {

            // Comeau recommends...

            reverse_iterator_base tmp (*this);

            *this = ++ this->base ();

            return tmp;

        }

        BOOST_UBLAS_INLINE

        reverse_iterator_base &operator += (difference_type n) {

            // Comeau recommends...

            return *this = this->base () - n;

        }

        BOOST_UBLAS_INLINE

        reverse_iterator_base &operator -= (difference_type n) {

            // Comeau recommends...

            return *this = this->base () + n;

        }

#endif



#ifdef BOOST_UBLAS_FRIEND_FUNCTION

        BOOST_UBLAS_INLINE

        friend reverse_iterator_base operator + (const reverse_iterator_base &it, difference_type n) {

            reverse_iterator_base tmp (it);

            return tmp += n;

        }

        BOOST_UBLAS_INLINE

        friend reverse_iterator_base operator - (const reverse_iterator_base &it, difference_type n) {

            reverse_iterator_base tmp (it);

            return tmp -= n;

        }

        BOOST_UBLAS_INLINE

        friend difference_type operator - (const reverse_iterator_base &it1, const reverse_iterator_base &it2) {

            return it2.base () - it1.base ();

        }

#endif



        BOOST_UBLAS_INLINE

        const container_type &operator () () const {

            // Comeau recommends...

            return this->base () ();

        }



        BOOST_UBLAS_INLINE

        size_type index () const {

            // Comeau recommends...

            iterator_type tmp (this->base ());

            return (-- tmp).index ();

        }

    };



#ifndef BOOST_UBLAS_FRIEND_FUNCTION

    template<class I>

    BOOST_UBLAS_INLINE

    reverse_iterator_base<I> operator + (const reverse_iterator_base<I> &it, std::ptrdiff_t n) {

        reverse_iterator_base<I> tmp (it);

        return tmp += n;

    }

    template<class I>

    BOOST_UBLAS_INLINE

    reverse_iterator_base<I> operator - (const reverse_iterator_base<I> &it, std::ptrdiff_t n) {

        reverse_iterator_base<I> tmp (it);

        return tmp -= n;

    }

    template<class I>

    BOOST_UBLAS_INLINE

    std::ptrdiff_t operator - (const reverse_iterator_base<I> &it1, const reverse_iterator_base<I> &it2) {

        return it2.base () - it1.base ();

    }

#endif



    // Renamed this class from reverse_iterator1 to get
    // typedef reverse_iterator1<...> reverse_iterator1
    // working. Thanks to Gabriel Dos Reis for explaining this.
    template <class I>
    class reverse_iterator_base1:
        public std::reverse_iterator<I> {

    public:

        typedef std::size_t size_type;

        typedef std::ptrdiff_t difference_type;

        typedef I iterator_type;

        typedef typename I::container_type container_type;

#ifndef BOOST_UBLAS_USE_CANONICAL_ITERATOR

        typedef typename I::dual_iterator_type dual_iterator_type;

        typedef typename I::dual_reverse_iterator_type dual_reverse_iterator_type;

#endif



        // Construction and destruction

        BOOST_UBLAS_INLINE

        reverse_iterator_base1 ():

            std::reverse_iterator<iterator_type> () {}

        BOOST_UBLAS_INLINE

        reverse_iterator_base1 (const iterator_type &it):

            std::reverse_iterator<iterator_type> (it) {}



#ifdef BOOST_UBLAS_REVERSE_ITERATOR_OVERLOADS

        // Arithmetic

        BOOST_UBLAS_INLINE

        reverse_iterator_base1 &operator ++ () {

            // Comeau recommends...

            return *this = -- this->base ();

        }

        BOOST_UBLAS_INLINE

        reverse_iterator_base1 operator ++ (int) {

            // Comeau recommends...

            reverse_iterator_base1 tmp (*this);

            *this = -- this->base ();

            return tmp;

        }

        BOOST_UBLAS_INLINE

        reverse_iterator_base1 &operator -- () {

            // Comeau recommends...

            return *this = ++ this->base ();

        }

        BOOST_UBLAS_INLINE

        reverse_iterator_base1 operator -- (int) {

            // Comeau recommends...

            reverse_iterator_base1 tmp (*this);

            *this = ++ this->base ();

            return tmp;

        }

        BOOST_UBLAS_INLINE

        reverse_iterator_base1 &operator += (difference_type n) {

            // Comeau recommends...

            return *this = this->base () - n;

        }

        BOOST_UBLAS_INLINE

        reverse_iterator_base1 &operator -= (difference_type n) {

            // Comeau recommends...

            return *this = this->base () + n;

        }

#endif



#ifdef BOOST_UBLAS_FRIEND_FUNCTION

        BOOST_UBLAS_INLINE

        friend reverse_iterator_base1 operator + (const reverse_iterator_base1 &it, difference_type n) {

            reverse_iterator_base1 tmp (it);

            return tmp += n;

        }

        BOOST_UBLAS_INLINE

        friend reverse_iterator_base1 operator - (const reverse_iterator_base1 &it, difference_type n) {

            reverse_iterator_base1 tmp (it);

            return tmp -= n;

        }

        BOOST_UBLAS_INLINE

        friend difference_type operator - (const reverse_iterator_base1 &it1, const reverse_iterator_base1 &it2) {

            return it2.base () - it1.base ();

        }

#endif



        BOOST_UBLAS_INLINE

        const container_type &operator () () const {

            // Comeau recommends...

            return this->base () ();

        }



        BOOST_UBLAS_INLINE

        size_type index1 () const {

            // Comeau recommends...

            iterator_type tmp (this->base ());

            return (-- tmp).index1 ();

        }

        BOOST_UBLAS_INLINE

        size_type index2 () const {

            // Comeau recommends...

            iterator_type tmp (this->base ());

            return (-- tmp).index2 ();

        }



#ifndef BOOST_UBLAS_USE_CANONICAL_ITERATOR

        BOOST_UBLAS_INLINE

        dual_iterator_type begin () const {

            // Comeau recommends...

            return this->base ().begin ();

        }

        BOOST_UBLAS_INLINE

        dual_iterator_type end () const {

            // Comeau recommends...

            return this->base ().end ();

        }

        BOOST_UBLAS_INLINE

        dual_reverse_iterator_type rbegin () const {

            return dual_reverse_iterator_type (end ());

        }

        BOOST_UBLAS_INLINE

        dual_reverse_iterator_type rend () const {

            return dual_reverse_iterator_type (begin ());

        }

#endif

    };



#ifndef BOOST_UBLAS_FRIEND_FUNCTION

    template<class I>

    BOOST_UBLAS_INLINE

    reverse_iterator_base1<I> operator + (const reverse_iterator_base1<I> &it, std::ptrdiff_t n) {

        reverse_iterator_base1<I> tmp (it);

        return tmp += n;

    }

    template<class I>

    BOOST_UBLAS_INLINE

    reverse_iterator_base1<I> operator - (const reverse_iterator_base1<I> &it, std::ptrdiff_t n) {

        reverse_iterator_base1<I> tmp (it);

        return tmp -= n;

    }

    template<class I>

    BOOST_UBLAS_INLINE

    std::ptrdiff_t operator - (const reverse_iterator_base1<I> &it1, const reverse_iterator_base1<I> &it2) {

        return it2.base () - it1.base ();

    }

#endif



    // Renamed this class from reverse_iterator2 to get
    // typedef reverse_iterator2<...> reverse_iterator2
    // working. Thanks to Gabriel Dos Reis for explaining this.
    template <class I>
    class reverse_iterator_base2:
        public std::reverse_iterator<I> {

    public:

        typedef std::size_t size_type;

        typedef std::ptrdiff_t difference_type;

        typedef I iterator_type;

        typedef typename I::container_type container_type;

#ifndef BOOST_UBLAS_USE_CANONICAL_ITERATOR

        typedef typename I::dual_iterator_type dual_iterator_type;

        typedef typename I::dual_reverse_iterator_type dual_reverse_iterator_type;

#endif



        // Construction and destruction

        BOOST_UBLAS_INLINE

        reverse_iterator_base2 ():

            std::reverse_iterator<iterator_type> () {}

        BOOST_UBLAS_INLINE

        reverse_iterator_base2 (const iterator_type &it):

            std::reverse_iterator<iterator_type> (it) {}



#ifdef BOOST_UBLAS_REVERSE_ITERATOR_OVERLOADS

        // Arithmetic

        BOOST_UBLAS_INLINE

        reverse_iterator_base2 &operator ++ () {

            // Comeau recommends...

            return *this = -- this->base ();

        }

        BOOST_UBLAS_INLINE

        reverse_iterator_base2 operator ++ (int) {

            // Comeau recommends...

            reverse_iterator_base2 tmp (*this);

            *this = -- this->base ();

            return tmp;

        }

        BOOST_UBLAS_INLINE

        reverse_iterator_base2 &operator -- () {

            // Comeau recommends...

            return *this = ++ this->base ();

        }

        BOOST_UBLAS_INLINE

        reverse_iterator_base2 operator -- (int) {

            // Comeau recommends...

            reverse_iterator_base2 tmp (*this);

            *this = ++ this->base ();

            return tmp;

        }

        BOOST_UBLAS_INLINE

        reverse_iterator_base2 &operator += (difference_type n) {

            // Comeau recommends...

            return *this = this->base () - n;

        }

        BOOST_UBLAS_INLINE

        reverse_iterator_base2 &operator -= (difference_type n) {

            // Comeau recommends...

            return *this = this->base () + n;

        }

#endif



#ifdef BOOST_UBLAS_FRIEND_FUNCTION

        BOOST_UBLAS_INLINE

        friend reverse_iterator_base2 operator + (const reverse_iterator_base2 &it, difference_type n) {

            reverse_iterator_base2 tmp (it);

            return tmp += n;

        }

        BOOST_UBLAS_INLINE

        friend reverse_iterator_base2 operator - (const reverse_iterator_base2 &it, difference_type n) {

            reverse_iterator_base2 tmp (it);

            return tmp -= n;

        }

        BOOST_UBLAS_INLINE

        friend difference_type operator - (const reverse_iterator_base2 &it1, const reverse_iterator_base2 &it2) {

            return it2.base () - it1.base ();

        }

#endif



        BOOST_UBLAS_INLINE

        const container_type &operator () () const {

            // Comeau recommends...

            return this->base () ();

        }



        BOOST_UBLAS_INLINE

        size_type index1 () const {

            // Comeau recommends...

            iterator_type tmp (this->base ());

            return (-- tmp).index1 ();

        }

        BOOST_UBLAS_INLINE

        size_type index2 () const {

            // Comeau recommends...

            iterator_type tmp (this->base ());

            return (-- tmp).index2 ();

        }



#ifndef BOOST_UBLAS_USE_CANONICAL_ITERATOR

        BOOST_UBLAS_INLINE

        dual_iterator_type begin () const {

            // Comeau recommends...

            return this->base ().begin ();

        }

        BOOST_UBLAS_INLINE

        dual_iterator_type end () const {

            // Comeau recommends...

            return this->base ().end ();

        }

        BOOST_UBLAS_INLINE

        dual_reverse_iterator_type rbegin () const {

            return dual_reverse_iterator_type (end ());

        }

        BOOST_UBLAS_INLINE

        dual_reverse_iterator_type rend () const {

            return dual_reverse_iterator_type (begin ());

        }

#endif

    };



#ifndef BOOST_UBLAS_FRIEND_FUNCTION

    template<class I>

    BOOST_UBLAS_INLINE

    reverse_iterator_base2<I> operator + (const reverse_iterator_base2<I> &it, std::ptrdiff_t n) {

        reverse_iterator_base2<I> tmp (it);

        return tmp += n;

    }

    template<class I>

    BOOST_UBLAS_INLINE

    reverse_iterator_base2<I> operator - (const reverse_iterator_base2<I> &it, std::ptrdiff_t n) {

        reverse_iterator_base2<I> tmp (it);

        return tmp -= n;

    }

    template<class I>

    BOOST_UBLAS_INLINE

    std::ptrdiff_t operator - (const reverse_iterator_base2<I> &it1, const reverse_iterator_base2<I> &it2) {

        return it2.base () - it1.base ();

    }

#endif



#endif



    template<class C, class IC>

    class indexed_iterator:

        public container_reference<C>,

        public random_access_iterator_base<IC,

                                           indexed_iterator<C, IC>,

                                           typename C::value_type,

                                           typename C::difference_type> {

    public:

        typedef C container_type;

        typedef IC iterator_category;

        typedef typename container_type::size_type size_type;

        typedef typename container_type::difference_type difference_type;

        typedef typename container_type::value_type value_type;

        typedef typename container_type::reference reference;



        // Construction and destruction

        BOOST_UBLAS_INLINE

        indexed_iterator ():

            container_reference<container_type> (), it_ () {}

        BOOST_UBLAS_INLINE

        indexed_iterator (container_type &c, size_type it):

            container_reference<container_type> (c), it_ (it) {}



        // Arithmetic

        BOOST_UBLAS_INLINE

        indexed_iterator &operator ++ () {

            ++ it_;

            return *this;

        }

        BOOST_UBLAS_INLINE

        indexed_iterator &operator -- () {

            -- it_;

            return *this;

        }

        BOOST_UBLAS_INLINE

        indexed_iterator &operator += (difference_type n) {

            it_ += n;

            return *this;

        }

        BOOST_UBLAS_INLINE

        indexed_iterator &operator -= (difference_type n) {

            it_ -= n;

            return *this;

        }

        BOOST_UBLAS_INLINE

        difference_type operator - (const indexed_iterator &it) const {

            return it_ - it.it_;

        }



        // Dereference

        BOOST_UBLAS_INLINE

        reference operator * () const {

            BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());

            return (*this) () (it_);

        }

        BOOST_UBLAS_INLINE

        reference operator [] (difference_type n) const {

            return *((*this) + n);

        }



        // Index

        BOOST_UBLAS_INLINE

        size_type index () const {

            return it_;

        }



        // Assignment 

        BOOST_UBLAS_INLINE

        indexed_iterator &operator = (const indexed_iterator &it) {

            assign (&it ());

            it_ = it.it_;

            return *this;

        }



        // Comparison

        BOOST_UBLAS_INLINE

        bool operator == (const indexed_iterator &it) const {

#ifndef BOOST_UBLAS_USE_CANONICAL_ITERATOR

            BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());

#endif

            return it_ == it.it_;

        }



    private:

        size_type it_;

    };



#ifdef BOOST_MSVC_STD_ITERATOR

    template<class C, class I>

    BOOST_UBLAS_INLINE

    indexed_iterator<C, I> operator ++ (const indexed_iterator<C, I> &it, int) {

        indexed_iterator<C, I> tmp (it);

        ++ tmp;

        return tmp;

    }

    template<class C, class I>

    BOOST_UBLAS_INLINE

    indexed_iterator<C, I> operator -- (const indexed_iterator<C, I> &it, int) {

        indexed_iterator<C, I> tmp (it);

        -- tmp;

        return tmp;

    }

    template<class C, class I>

    BOOST_UBLAS_INLINE

    indexed_iterator<C, I> operator + (const indexed_iterator<C, I> &it, std::ptrdiff_t n) {

        indexed_iterator<C, I> tmp (it);

        return tmp += n;

    }

    template<class C, class I>

    BOOST_UBLAS_INLINE

    indexed_iterator<C, I> operator - (const indexed_iterator<C, I> &it, std::ptrdiff_t n) {

        indexed_iterator<C, I> tmp (it);

        return tmp -= n;

    }

#endif



    template<class C, class IC>

    class indexed_const_iterator:

        public container_const_reference<C>,

        public random_access_iterator_base<IC,

                                           indexed_const_iterator<C, IC>, 

                                           typename C::value_type,

                                           typename C::difference_type> {

    public:

        typedef C container_type;

        typedef IC iterator_category;

        typedef typename container_type::size_type size_type;

        typedef typename container_type::difference_type difference_type;

        typedef typename container_type::value_type value_type;

        typedef typename container_type::const_reference const_reference;

        typedef indexed_iterator<container_type, iterator_category> iterator_type;



        // Construction and destruction

        BOOST_UBLAS_INLINE

        indexed_const_iterator ():

            container_const_reference<container_type> (), it_ () {}

        BOOST_UBLAS_INLINE

        indexed_const_iterator (const container_type &c, size_type it):

            container_const_reference<container_type> (c), it_ (it) {}

        BOOST_UBLAS_INLINE 

        indexed_const_iterator (const iterator_type &it):

            container_const_reference<container_type> (it ()), it_ (it.index ()) {}



        // Arithmetic

        BOOST_UBLAS_INLINE

        indexed_const_iterator &operator ++ () {

            ++ it_;

            return *this;

        }

        BOOST_UBLAS_INLINE

        indexed_const_iterator &operator -- () {

            -- it_;

            return *this;

        }

        BOOST_UBLAS_INLINE

        indexed_const_iterator &operator += (difference_type n) {

            it_ += n;

            return *this;

        }

        BOOST_UBLAS_INLINE

        indexed_const_iterator &operator -= (difference_type n) {

            it_ -= n;

            return *this;

        }

        BOOST_UBLAS_INLINE

        difference_type operator - (const indexed_const_iterator &it) const {

            return it_ - it.it_;

        }



        // Dereference

        BOOST_UBLAS_INLINE

        const_reference operator * () const {

            BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());

            return (*this) () (it_);

        }

        BOOST_UBLAS_INLINE

        const_reference operator [] (difference_type n) const {

            return *((*this) + n);

        }



        // Index

        BOOST_UBLAS_INLINE

        size_type index () const {

            return it_;

        }



        // Assignment 

        BOOST_UBLAS_INLINE

        indexed_const_iterator &operator = (const indexed_const_iterator &it) {

            assign (&it ());

            it_ = it.it_;

            return *this;

        }



        // Comparison

        BOOST_UBLAS_INLINE

        bool operator == (const indexed_const_iterator &it) const {

#ifndef BOOST_UBLAS_USE_CANONICAL_ITERATOR

            BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());

#endif

            return it_ == it.it_;

        }



    private:

        size_type it_;



        friend class indexed_iterator<container_type, iterator_category>;

    };



#ifdef BOOST_MSVC_STD_ITERATOR

    template<class C, class I>

    BOOST_UBLAS_INLINE

    indexed_const_iterator<C, I> operator ++ (const indexed_const_iterator<C, I> &it, int) {

        indexed_const_iterator<C, I> tmp (it);

        ++ tmp;

        return tmp;

    }

    template<class C, class I>

    BOOST_UBLAS_INLINE

    indexed_const_iterator<C, I> operator -- (const indexed_const_iterator<C, I> &it, int) {

        indexed_const_iterator<C, I> tmp (it);

        -- tmp;

        return tmp;

    }

    template<class C, class I>

    BOOST_UBLAS_INLINE

    indexed_const_iterator<C, I> operator + (const indexed_const_iterator<C, I> &it, std::ptrdiff_t n) {

        indexed_const_iterator<C, I> tmp (it);

        return tmp += n;

    }

    template<class C, class I>

    BOOST_UBLAS_INLINE

    indexed_const_iterator<C, I> operator - (const indexed_const_iterator<C, I> &it, std::ptrdiff_t n) {

        indexed_const_iterator<C, I> tmp (it);

        return tmp -= n;

    }

#endif



    template<class C, class IC>

    class indexed_iterator2;



    template<class C, class IC>

    class indexed_iterator1:

        public container_reference<C>, 

        public random_access_iterator_base<IC,

                                           indexed_iterator1<C, IC>, 

                                           typename C::value_type,

                                           typename C::reference> {

    public:

        typedef C container_type;

        typedef IC iterator_category;

        typedef typename container_type::size_type size_type;

        typedef typename container_type::difference_type difference_type;

        typedef typename container_type::value_type value_type;

        typedef typename container_type::reference reference;

        typedef indexed_iterator2<container_type, iterator_category> dual_iterator_type;

#ifdef BOOST_MSVC_STD_ITERATOR

        typedef reverse_iterator_base2<dual_iterator_type, value_type, reference> dual_reverse_iterator_type;

#else

        typedef reverse_iterator_base2<dual_iterator_type> dual_reverse_iterator_type;

#endif



        // Construction and destruction

        BOOST_UBLAS_INLINE

        indexed_iterator1 ():

            container_reference<container_type> (), it1_ (), it2_ () {}

        BOOST_UBLAS_INLINE 

        indexed_iterator1 (container_type &c, size_type it1, size_type it2):

            container_reference<container_type> (c), it1_ (it1), it2_ (it2) {}



        // Arithmetic

        BOOST_UBLAS_INLINE

        indexed_iterator1 &operator ++ () {

            ++ it1_;

            return *this;

        }

        BOOST_UBLAS_INLINE

        indexed_iterator1 &operator -- () {

            -- it1_;

            return *this;

        }

        BOOST_UBLAS_INLINE

        indexed_iterator1 &operator += (difference_type n) {

            it1_ += n;

            return *this;

        }

        BOOST_UBLAS_INLINE

        indexed_iterator1 &operator -= (difference_type n) {

            it1_ -= n;

            return *this;

        }

        BOOST_UBLAS_INLINE

        difference_type operator - (const indexed_iterator1 &it) const {

            return it1_ - it.it1_;

        }



        // Dereference

        BOOST_UBLAS_INLINE

        reference operator * () const {

            BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());

            BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());

            return (*this) () (it1_, it2_);

        }

        BOOST_UBLAS_INLINE

        reference operator [] (difference_type n) const {

            return *((*this) + n);

        }



        // Index

        BOOST_UBLAS_INLINE

        size_type index1 () const {

            return it1_;

        }

        BOOST_UBLAS_INLINE

        size_type index2 () const {

            return it2_;

        }



        BOOST_UBLAS_INLINE

        dual_iterator_type begin () const {

            return (*this) ().find_first2 (1, index1 (), 0); 

        }

        BOOST_UBLAS_INLINE

        dual_iterator_type end () const {

            return (*this) ().find_first2 (1, index1 (), (*this) ().size2 ()); 

        }

        BOOST_UBLAS_INLINE

        dual_reverse_iterator_type rbegin () const {

            return dual_reverse_iterator_type (end ()); 

        }

        BOOST_UBLAS_INLINE

        dual_reverse_iterator_type rend () const {

            return dual_reverse_iterator_type (begin ()); 

        }



        // Assignment 

        BOOST_UBLAS_INLINE

        indexed_iterator1 &operator = (const indexed_iterator1 &it) {

            assign (&it ());

            it1_ = it.it1_;

            it2_ = it.it2_;

            return *this;

        }



        // Comparison

        BOOST_UBLAS_INLINE

        bool operator == (const indexed_iterator1 &it) const {

            BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());

            return it1_ == it.it1_ && it2_ == it.it2_;

        }



    private:

        size_type it1_;

        size_type it2_;

    };



#ifdef BOOST_MSVC_STD_ITERATOR

    template<class C, class I>

    BOOST_UBLAS_INLINE

    indexed_iterator1<C, I> operator ++ (const indexed_iterator1<C, I> &it, int) {

        indexed_iterator1<C, I> tmp (it);

        ++ tmp;

        return tmp;

    }

    template<class C, class I>

    BOOST_UBLAS_INLINE

    indexed_iterator1<C, I> operator -- (const indexed_iterator1<C, I> &it, int) {

        indexed_iterator1<C, I> tmp (it);

        -- tmp;

        return tmp;

    }

    template<class C, class I>

    BOOST_UBLAS_INLINE

    indexed_iterator1<C, I> operator + (const indexed_iterator1<C, I> &it, std::ptrdiff_t n) {

        indexed_iterator1<C, I> tmp (it);

        return tmp += n;

    }

    template<class C, class I>

    BOOST_UBLAS_INLINE

    indexed_iterator1<C, I> operator - (const indexed_iterator1<C, I> &it, std::ptrdiff_t n) {

        indexed_iterator1<C, I> tmp (it);

        return tmp -= n;

    }

#endif



    template<class C, class IC>

    class indexed_const_iterator2;



    template<class C, class IC>

    class indexed_const_iterator1:

        public container_const_reference<C>, 

        public random_access_iterator_base<IC,

                                           indexed_const_iterator1<C, IC>, 

                                           typename C::value_type,

                                           typename C::const_reference> {

    public:

        typedef C container_type;

        typedef IC iterator_category;

        typedef typename container_type::size_type size_type;

        typedef typename container_type::difference_type difference_type;

        typedef typename container_type::value_type value_type;

        typedef typename container_type::const_reference const_reference;

        typedef indexed_iterator1<container_type, iterator_category> iterator_type;

        typedef indexed_const_iterator2<container_type, iterator_category> dual_iterator_type;

#ifdef BOOST_MSVC_STD_ITERATOR

        typedef reverse_iterator_base2<dual_iterator_type, value_type, const_reference> dual_reverse_iterator_type;

#else

        typedef reverse_iterator_base2<dual_iterator_type> dual_reverse_iterator_type;

#endif



        // Construction and destruction

        BOOST_UBLAS_INLINE

        indexed_const_iterator1 ():

            container_const_reference<container_type> (), it1_ (), it2_ () {}

        BOOST_UBLAS_INLINE

        indexed_const_iterator1 (const container_type &c, size_type it1, size_type it2):

            container_const_reference<container_type> (c), it1_ (it1), it2_ (it2) {}

        BOOST_UBLAS_INLINE 

        indexed_const_iterator1 (const iterator_type &it):

            container_const_reference<container_type> (it ()), it1_ (it.index1 ()), it2_ (it.index2 ()) {}



        // Arithmetic

        BOOST_UBLAS_INLINE

        indexed_const_iterator1 &operator ++ () {

            ++ it1_;

            return *this;

        }

        BOOST_UBLAS_INLINE

        indexed_const_iterator1 &operator -- () {

            -- it1_;

            return *this;

        }

        BOOST_UBLAS_INLINE

        indexed_const_iterator1 &operator += (difference_type n) {

            it1_ += n;

            return *this;

        }

        BOOST_UBLAS_INLINE

        indexed_const_iterator1 &operator -= (difference_type n) {

            it1_ -= n;

            return *this;

        }

        BOOST_UBLAS_INLINE

        difference_type operator - (const indexed_const_iterator1 &it) const {

            return it1_ - it.it1_;

        }



        // Dereference

        BOOST_UBLAS_INLINE

        const_reference operator * () const {

            BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());

            BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());

            return (*this) () (it1_, it2_);

        }

        BOOST_UBLAS_INLINE

        const_reference operator [] (difference_type n) const {

            return *((*this) + n);

        }



        // Index

        BOOST_UBLAS_INLINE

        size_type index1 () const {

            return it1_;

        }

        BOOST_UBLAS_INLINE

        size_type index2 () const {

            return it2_;

        }



        BOOST_UBLAS_INLINE

        dual_iterator_type begin () const {

            return (*this) ().find_first2 (1, index1 (), 0); 

        }

        BOOST_UBLAS_INLINE

        dual_iterator_type end () const {

            return (*this) ().find_first2 (1, index1 (), (*this) ().size2 ()); 

        }

        BOOST_UBLAS_INLINE

        dual_reverse_iterator_type rbegin () const {

            return dual_reverse_iterator_type (end ()); 

        }

        BOOST_UBLAS_INLINE

        dual_reverse_iterator_type rend () const {

            return dual_reverse_iterator_type (begin ()); 

        }



        // Assignment 

        BOOST_UBLAS_INLINE

        indexed_const_iterator1 &operator = (const indexed_const_iterator1 &it) {

            assign (&it ());

            it1_ = it.it1_;

            it2_ = it.it2_;

            return *this;

        }



        // Comparison

        BOOST_UBLAS_INLINE

        bool operator == (const indexed_const_iterator1 &it) const {

            BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());

            return it1_ == it.it1_ && it2_ == it.it2_;

        }



    private:

        size_type it1_;

        size_type it2_;



        friend class indexed_iterator1<container_type, iterator_category>;

    };



#ifdef BOOST_MSVC_STD_ITERATOR

    template<class C, class I>

    BOOST_UBLAS_INLINE

    indexed_const_iterator1<C, I> operator ++ (const indexed_const_iterator1<C, I> &it, int) {

        indexed_const_iterator1<C, I> tmp (it);

        ++ tmp;

        return tmp;

    }

    template<class C, class I>

    BOOST_UBLAS_INLINE

    indexed_const_iterator1<C, I> operator -- (const indexed_const_iterator1<C, I> &it, int) {

        indexed_const_iterator1<C, I> tmp (it);

        -- tmp;

        return tmp;

    }

    template<class C, class I>

    BOOST_UBLAS_INLINE

    indexed_const_iterator1<C, I> operator + (const indexed_const_iterator1<C, I> &it, std::ptrdiff_t n) {

        indexed_const_iterator1<C, I> tmp (it);

        return tmp += n;

    }

    template<class C, class I>

    BOOST_UBLAS_INLINE

    indexed_const_iterator1<C, I> operator - (const indexed_const_iterator1<C, I> &it, std::ptrdiff_t n) {

        indexed_const_iterator1<C, I> tmp (it);

        return tmp -= n;

    }

#endif



    template<class C, class IC>

    class indexed_iterator2:

        public container_reference<C>, 

        public random_access_iterator_base<IC,

                                           indexed_iterator2<C, IC>, 

                                           typename C::value_type,

                                           typename C::reference> {

    public:

        typedef C container_type;

        typedef IC iterator_category;

        typedef typename container_type::size_type size_type;

        typedef typename container_type::difference_type difference_type;

        typedef typename container_type::value_type value_type;

        typedef typename container_type::reference reference;

        typedef indexed_iterator1<container_type, iterator_category> dual_iterator_type;

#ifdef BOOST_MSVC_STD_ITERATOR

        typedef reverse_iterator_base1<dual_iterator_type, value_type, reference> dual_reverse_iterator_type;

#else

        typedef reverse_iterator_base1<dual_iterator_type> dual_reverse_iterator_type;

#endif



        // Construction and destruction

        BOOST_UBLAS_INLINE

        indexed_iterator2 ():

            container_reference<container_type> (), it1_ (), it2_ () {}

        BOOST_UBLAS_INLINE

        indexed_iterator2 (container_type &c, size_type it1, size_type it2):

            container_reference<container_type> (c), it1_ (it1), it2_ (it2) {}



        // Arithmetic

        BOOST_UBLAS_INLINE

        indexed_iterator2 &operator ++ () {

            ++ it2_;

            return *this;

        }

        BOOST_UBLAS_INLINE

        indexed_iterator2 &operator -- () {

            -- it2_;

            return *this;

        }

        BOOST_UBLAS_INLINE

        indexed_iterator2 &operator += (difference_type n) {

            it2_ += n;

            return *this;

        }

        BOOST_UBLAS_INLINE

        indexed_iterator2 &operator -= (difference_type n) {

            it2_ -= n;

            return *this;

        }

        BOOST_UBLAS_INLINE

        difference_type operator - (const indexed_iterator2 &it) const {

            return it2_ - it.it2_;

        }



        // Dereference

        BOOST_UBLAS_INLINE

        reference operator * () const {

            BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());

            BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());

            return (*this) () (it1_, it2_);

        }

        BOOST_UBLAS_INLINE

        reference operator [] (difference_type n) const {

            return *((*this) + n);

        }



        // Index

        BOOST_UBLAS_INLINE

        size_type index1 () const {

            return it1_;

        }

        BOOST_UBLAS_INLINE

        size_type index2 () const {

            return it2_;

        }



        BOOST_UBLAS_INLINE

        dual_iterator_type begin () const {

            return (*this) ().find_first1 (1, 0, index2 ()); 

        }

        BOOST_UBLAS_INLINE

        dual_iterator_type end () const {

            return (*this) ().find_first1 (1, (*this) ().size1 (), index2 ()); 

        }

        BOOST_UBLAS_INLINE

        dual_reverse_iterator_type rbegin () const {

            return dual_reverse_iterator_type (end ()); 

        }

        BOOST_UBLAS_INLINE

        dual_reverse_iterator_type rend () const {

            return dual_reverse_iterator_type (begin ()); 

        }



        // Assignment 

        BOOST_UBLAS_INLINE

        indexed_iterator2 &operator = (const indexed_iterator2 &it) {

            assign (&it ());

            it1_ = it.it1_;

            it2_ = it.it2_;

            return *this;

        }



        // Comparison

        BOOST_UBLAS_INLINE

        bool operator == (const indexed_iterator2 &it) const {

            BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());

            return it1_ == it.it1_ && it2_ == it.it2_;

        }



    private:

        size_type it1_;

        size_type it2_;

    };



#ifdef BOOST_MSVC_STD_ITERATOR

    template<class C, class I>

    BOOST_UBLAS_INLINE

    indexed_iterator2<C, I> operator ++ (const indexed_iterator2<C, I> &it, int) {

        indexed_iterator2<C, I> tmp (it);

        ++ tmp;

        return tmp;

    }

    template<class C, class I>

    BOOST_UBLAS_INLINE

    indexed_iterator2<C, I> operator -- (const indexed_iterator2<C, I> &it, int) {

        indexed_iterator2<C, I> tmp (it);

        -- tmp;

        return tmp;

    }

    template<class C, class I>

    BOOST_UBLAS_INLINE

    indexed_iterator2<C, I> operator + (const indexed_iterator2<C, I> &it, std::ptrdiff_t n) {

        indexed_iterator2<C, I> tmp (it);

        return tmp += n;

    }

    template<class C, class I>

    BOOST_UBLAS_INLINE

    indexed_iterator2<C, I> operator - (const indexed_iterator2<C, I> &it, std::ptrdiff_t n) {

        indexed_iterator2<C, I> tmp (it);

        return tmp -= n;

    }

#endif



    template<class C, class IC>

    class indexed_const_iterator2:

        public container_const_reference<C>, 

        public random_access_iterator_base<IC,

                                           indexed_const_iterator2<C, IC>, 

                                           typename C::value_type,

                                           typename C::const_reference> {

    public:

        typedef C container_type;

        typedef IC iterator_category;

        typedef typename container_type::size_type size_type;

        typedef typename container_type::difference_type difference_type;

        typedef typename container_type::value_type value_type;

        typedef typename container_type::const_reference const_reference;

        typedef indexed_iterator2<container_type, iterator_category> iterator_type;

        typedef indexed_const_iterator1<container_type, iterator_category> dual_iterator_type;

#ifdef BOOST_MSVC_STD_ITERATOR

        typedef reverse_iterator_base1<dual_iterator_type, value_type, const_reference> dual_reverse_iterator_type;

#else

        typedef reverse_iterator_base1<dual_iterator_type> dual_reverse_iterator_type;

#endif



        // Construction and destruction

        BOOST_UBLAS_INLINE

        indexed_const_iterator2 ():

            container_const_reference<container_type> (), it1_ (), it2_ () {}

        BOOST_UBLAS_INLINE

        indexed_const_iterator2 (const container_type &c, size_type it1, size_type it2):

            container_const_reference<container_type> (c), it1_ (it1), it2_ (it2) {}

        BOOST_UBLAS_INLINE 

        indexed_const_iterator2 (const iterator_type &it):

            container_const_reference<container_type> (it ()), it1_ (it.index1 ()), it2_ (it.index2 ()) {}



        // Arithmetic

        BOOST_UBLAS_INLINE

        indexed_const_iterator2 &operator ++ () {

            ++ it2_;

            return *this;

        }

        BOOST_UBLAS_INLINE

        indexed_const_iterator2 &operator -- () {

            -- it2_;

            return *this;

        }

        BOOST_UBLAS_INLINE

        indexed_const_iterator2 &operator += (difference_type n) {

            it2_ += n;

            return *this;

        }

        BOOST_UBLAS_INLINE

        indexed_const_iterator2 &operator -= (difference_type n) {

            it2_ -= n;

            return *this;

        }

        BOOST_UBLAS_INLINE

        difference_type operator - (const indexed_const_iterator2 &it) const {

            return it2_ - it.it2_;

        }



        // Dereference

        BOOST_UBLAS_INLINE

        const_reference operator * () const {

            BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());

            BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());

            return (*this) () (it1_, it2_);

        }

        BOOST_UBLAS_INLINE

        const_reference operator [] (difference_type n) const {

            return *((*this) + n);

        }



        // Index

        BOOST_UBLAS_INLINE

        size_type index1 () const {

            return it1_;

        }

        BOOST_UBLAS_INLINE

        size_type index2 () const {

            return it2_;

        }



        BOOST_UBLAS_INLINE

        dual_iterator_type begin () const {

            return (*this) ().find_first1 (1, 0, index2 ()); 

        }

        BOOST_UBLAS_INLINE

        dual_iterator_type end () const {

            return (*this) ().find_first1 (1, (*this) ().size1 (), index2 ()); 

        }

        BOOST_UBLAS_INLINE

        dual_reverse_iterator_type rbegin () const {

            return dual_reverse_iterator_type (end ()); 

        }

        BOOST_UBLAS_INLINE

        dual_reverse_iterator_type rend () const {

            return dual_reverse_iterator_type (begin ()); 

        }



        // Assignment 

        BOOST_UBLAS_INLINE

        indexed_const_iterator2 &operator = (const indexed_const_iterator2 &it) {

            assign (&it ());

            it1_ = it.it1_;

            it2_ = it.it2_;

            return *this;

        }



        // Comparison

        BOOST_UBLAS_INLINE

        bool operator == (const indexed_const_iterator2 &it) const {

            BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());

            return it1_ == it.it1_ && it2_ == it.it2_;

        }



    private:

        size_type it1_;

        size_type it2_;



        friend class indexed_iterator2<container_type, iterator_category>;

    };



#ifdef BOOST_MSVC_STD_ITERATOR

    template<class C, class I>

    BOOST_UBLAS_INLINE

    indexed_const_iterator2<C, I> operator ++ (const indexed_const_iterator2<C, I> &it, int) {

        indexed_const_iterator2<C, I> tmp (it);

        ++ tmp;

        return tmp;

    }

    template<class C, class I>

    BOOST_UBLAS_INLINE

    indexed_const_iterator2<C, I> operator -- (const indexed_const_iterator2<C, I> &it, int) {

        indexed_const_iterator2<C, I> tmp (it);

        -- tmp;

        return tmp;

    }

    template<class C, class I>

    BOOST_UBLAS_INLINE

    indexed_const_iterator2<C, I> operator + (const indexed_const_iterator2<C, I> &it, std::ptrdiff_t n) {

        indexed_const_iterator2<C, I> tmp (it);

        return tmp += n;

    }

    template<class C, class I>

    BOOST_UBLAS_INLINE

    indexed_const_iterator2<C, I> operator - (const indexed_const_iterator2<C, I> &it, std::ptrdiff_t n) {

        indexed_const_iterator2<C, I> tmp (it);

        return tmp -= n;

    }

#endif



}}}



#endif













