Chris@16: // Chris@16: // Copyright (c) 2000-2007 Chris@16: // Joerg Walter, Mathias Koch, Gunter Winkler Chris@16: // Chris@16: // Distributed under the Boost Software License, Version 1.0. (See Chris@16: // accompanying file LICENSE_1_0.txt or copy at Chris@16: // http://www.boost.org/LICENSE_1_0.txt) Chris@16: // Chris@16: // The authors gratefully acknowledge the support of Chris@16: // GeNeSys mbH & Co. KG in producing this work. Chris@16: // Chris@16: Chris@16: #ifndef _BOOST_UBLAS_MATRIX_SPARSE_ Chris@16: #define _BOOST_UBLAS_MATRIX_SPARSE_ Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #if BOOST_UBLAS_TYPE_CHECK Chris@16: #include Chris@16: #endif Chris@16: Chris@16: // Iterators based on ideas of Jeremy Siek Chris@16: Chris@16: namespace boost { namespace numeric { namespace ublas { Chris@16: Chris@16: #ifdef BOOST_UBLAS_STRICT_MATRIX_SPARSE Chris@16: Chris@16: template Chris@16: class sparse_matrix_element: Chris@16: public container_reference { Chris@16: public: Chris@16: typedef M matrix_type; Chris@16: typedef typename M::size_type size_type; Chris@16: typedef typename M::value_type value_type; Chris@16: typedef const value_type &const_reference; Chris@16: typedef value_type *pointer; Chris@16: typedef const value_type *const_pointer; Chris@16: Chris@16: private: Chris@16: // Proxied element operations Chris@16: void get_d () const { Chris@16: const_pointer p = (*this) ().find_element (i_, j_); Chris@16: if (p) Chris@16: d_ = *p; Chris@16: else Chris@16: d_ = value_type/*zero*/(); Chris@16: } Chris@16: Chris@16: void set (const value_type &s) const { Chris@16: pointer p = (*this) ().find_element (i_, j_); Chris@16: if (!p) Chris@16: (*this) ().insert_element (i_, j_, s); Chris@16: else Chris@16: *p = s; Chris@16: } Chris@16: Chris@16: public: Chris@16: // Construction and destruction Chris@16: BOOST_UBLAS_INLINE Chris@16: sparse_matrix_element (matrix_type &m, size_type i, size_type j): Chris@16: container_reference (m), i_ (i), j_ (j) { Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: sparse_matrix_element (const sparse_matrix_element &p): Chris@16: container_reference (p), i_ (p.i_), j_ (p.j_) {} Chris@16: BOOST_UBLAS_INLINE Chris@16: ~sparse_matrix_element () { Chris@16: } Chris@16: Chris@16: // Assignment Chris@16: BOOST_UBLAS_INLINE Chris@16: sparse_matrix_element &operator = (const sparse_matrix_element &p) { Chris@16: // Overide the implict copy assignment Chris@16: p.get_d (); Chris@16: set (p.d_); Chris@16: return *this; Chris@16: } Chris@16: template Chris@16: BOOST_UBLAS_INLINE Chris@16: sparse_matrix_element &operator = (const D &d) { Chris@16: set (d); Chris@16: return *this; Chris@16: } Chris@16: template Chris@16: BOOST_UBLAS_INLINE Chris@16: sparse_matrix_element &operator += (const D &d) { Chris@16: get_d (); Chris@16: d_ += d; Chris@16: set (d_); Chris@16: return *this; Chris@16: } Chris@16: template Chris@16: BOOST_UBLAS_INLINE Chris@16: sparse_matrix_element &operator -= (const D &d) { Chris@16: get_d (); Chris@16: d_ -= d; Chris@16: set (d_); Chris@16: return *this; Chris@16: } Chris@16: template Chris@16: BOOST_UBLAS_INLINE Chris@16: sparse_matrix_element &operator *= (const D &d) { Chris@16: get_d (); Chris@16: d_ *= d; Chris@16: set (d_); Chris@16: return *this; Chris@16: } Chris@16: template Chris@16: BOOST_UBLAS_INLINE Chris@16: sparse_matrix_element &operator /= (const D &d) { Chris@16: get_d (); Chris@16: d_ /= d; Chris@16: set (d_); Chris@16: return *this; Chris@16: } Chris@16: Chris@16: // Comparison Chris@16: template Chris@16: BOOST_UBLAS_INLINE Chris@16: bool operator == (const D &d) const { Chris@16: get_d (); Chris@16: return d_ == d; Chris@16: } Chris@16: template Chris@16: BOOST_UBLAS_INLINE Chris@16: bool operator != (const D &d) const { Chris@16: get_d (); Chris@16: return d_ != d; Chris@16: } Chris@16: Chris@16: // Conversion - weak link in proxy as d_ is not a perfect alias for the element Chris@16: BOOST_UBLAS_INLINE Chris@16: operator const_reference () const { Chris@16: get_d (); Chris@16: return d_; Chris@16: } Chris@16: Chris@16: // Conversion to reference - may be invalidated Chris@16: BOOST_UBLAS_INLINE Chris@16: value_type& ref () const { Chris@16: const pointer p = (*this) ().find_element (i_, j_); Chris@16: if (!p) Chris@16: return (*this) ().insert_element (i_, j_, value_type/*zero*/()); Chris@16: else Chris@16: return *p; Chris@16: } Chris@16: Chris@16: private: Chris@16: size_type i_; Chris@16: size_type j_; Chris@16: mutable value_type d_; Chris@16: }; Chris@16: Chris@16: /* Chris@16: * Generalise explicit reference access Chris@16: */ Chris@16: namespace detail { Chris@16: template Chris@16: struct element_reference > { Chris@16: typedef typename V::value_type& reference; Chris@16: static reference get_reference (const sparse_matrix_element& sve) Chris@16: { Chris@16: return sve.ref (); Chris@16: } Chris@16: }; Chris@16: } Chris@16: Chris@16: Chris@16: template Chris@16: struct type_traits > { Chris@16: typedef typename M::value_type element_type; Chris@16: typedef type_traits > self_type; Chris@16: typedef typename type_traits::value_type value_type; Chris@16: typedef typename type_traits::const_reference const_reference; Chris@16: typedef sparse_matrix_element reference; Chris@16: typedef typename type_traits::real_type real_type; Chris@16: typedef typename type_traits::precision_type precision_type; Chris@16: Chris@16: static const unsigned plus_complexity = type_traits::plus_complexity; Chris@16: static const unsigned multiplies_complexity = type_traits::multiplies_complexity; Chris@16: Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: real_type real (const_reference t) { Chris@16: return type_traits::real (t); Chris@16: } Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: real_type imag (const_reference t) { Chris@16: return type_traits::imag (t); Chris@16: } Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: value_type conj (const_reference t) { Chris@16: return type_traits::conj (t); Chris@16: } Chris@16: Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: real_type type_abs (const_reference t) { Chris@16: return type_traits::type_abs (t); Chris@16: } Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: value_type type_sqrt (const_reference t) { Chris@16: return type_traits::type_sqrt (t); Chris@16: } Chris@16: Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: real_type norm_1 (const_reference t) { Chris@16: return type_traits::norm_1 (t); Chris@16: } Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: real_type norm_2 (const_reference t) { Chris@16: return type_traits::norm_2 (t); Chris@16: } Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: real_type norm_inf (const_reference t) { Chris@16: return type_traits::norm_inf (t); Chris@16: } Chris@16: Chris@16: static Chris@16: BOOST_UBLAS_INLINE Chris@16: bool equals (const_reference t1, const_reference t2) { Chris@16: return type_traits::equals (t1, t2); Chris@16: } Chris@16: }; Chris@16: Chris@16: template Chris@16: struct promote_traits, T2> { Chris@16: typedef typename promote_traits::value_type, T2>::promote_type promote_type; Chris@16: }; Chris@16: template Chris@16: struct promote_traits > { Chris@16: typedef typename promote_traits::value_type>::promote_type promote_type; Chris@16: }; Chris@16: template Chris@16: struct promote_traits, sparse_matrix_element > { Chris@16: typedef typename promote_traits::value_type, Chris@16: typename sparse_matrix_element::value_type>::promote_type promote_type; Chris@16: }; Chris@16: Chris@16: #endif Chris@16: Chris@16: /** \brief Index map based sparse matrix of values of type \c T Chris@16: * Chris@16: * This class represents a matrix by using a \c key to value mapping. The default type is Chris@16: * \code template > class mapped_matrix; \endcode Chris@16: * So, by default a STL map container is used to associate keys and values. The key is computed depending on Chris@16: * the layout type \c L as \code key = layout_type::element(i, size1_, j, size2_); \endcode Chris@16: * which means \code key = (i*size2+j) \endcode for a row major matrix. Chris@16: * Limitations: The matrix size must not exceed \f$(size1*size2) < \f$ \code std::limits \endcode. Chris@16: * The \ref find1() and \ref find2() operations have a complexity of at least \f$\mathcal{O}(log(nnz))\f$, depending Chris@16: * on the efficiency of \c std::lower_bound on the key set of the map. Chris@16: * Orientation and storage can also be specified, otherwise a row major orientation is used. Chris@16: * It is \b not required by the storage to initialize elements of the matrix. By default, the orientation is \c row_major. Chris@16: * Chris@16: * \sa fwd.hpp, storage_sparse.hpp Chris@16: * Chris@16: * \tparam T the type of object stored in the matrix (like double, float, complex, etc...) Chris@16: * \tparam L the storage organization. It can be either \c row_major or \c column_major. By default it is \c row_major Chris@16: */ Chris@16: template Chris@16: class mapped_matrix: Chris@16: public matrix_container > { Chris@16: Chris@16: typedef T &true_reference; Chris@16: typedef T *pointer; Chris@16: typedef const T * const_pointer; Chris@16: typedef L layout_type; Chris@16: typedef mapped_matrix self_type; Chris@16: public: Chris@16: #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS Chris@16: using matrix_container::operator (); Chris@16: #endif Chris@16: typedef typename A::size_type size_type; Chris@16: typedef typename A::difference_type difference_type; Chris@16: typedef T value_type; Chris@16: typedef A array_type; Chris@16: typedef const T &const_reference; Chris@16: #ifndef BOOST_UBLAS_STRICT_MATRIX_SPARSE Chris@16: typedef typename detail::map_traits::reference reference; Chris@16: #else Chris@16: typedef sparse_matrix_element reference; Chris@16: #endif Chris@16: typedef const matrix_reference const_closure_type; Chris@16: typedef matrix_reference closure_type; Chris@16: typedef mapped_vector vector_temporary_type; Chris@16: typedef self_type matrix_temporary_type; Chris@16: typedef sparse_tag storage_category; Chris@16: typedef typename L::orientation_category orientation_category; Chris@16: Chris@16: // Construction and destruction Chris@16: BOOST_UBLAS_INLINE Chris@16: mapped_matrix (): Chris@16: matrix_container (), Chris@16: size1_ (0), size2_ (0), data_ () {} Chris@16: BOOST_UBLAS_INLINE Chris@16: mapped_matrix (size_type size1, size_type size2, size_type non_zeros = 0): Chris@16: matrix_container (), Chris@16: size1_ (size1), size2_ (size2), data_ () { Chris@16: detail::map_reserve (data (), restrict_capacity (non_zeros)); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: mapped_matrix (const mapped_matrix &m): Chris@16: matrix_container (), Chris@16: size1_ (m.size1_), size2_ (m.size2_), data_ (m.data_) {} Chris@16: template Chris@16: BOOST_UBLAS_INLINE Chris@16: mapped_matrix (const matrix_expression &ae, size_type non_zeros = 0): Chris@16: matrix_container (), Chris@16: size1_ (ae ().size1 ()), size2_ (ae ().size2 ()), data_ () { Chris@16: detail::map_reserve (data (), restrict_capacity (non_zeros)); Chris@16: matrix_assign (*this, ae); Chris@16: } Chris@16: Chris@16: // Accessors Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type size1 () const { Chris@16: return size1_; Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type size2 () const { Chris@16: return size2_; Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type nnz_capacity () const { Chris@16: return detail::map_capacity (data ()); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type nnz () const { Chris@16: return data (). size (); Chris@16: } Chris@16: Chris@16: // Storage accessors Chris@16: BOOST_UBLAS_INLINE Chris@16: const array_type &data () const { Chris@16: return data_; Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: array_type &data () { Chris@16: return data_; Chris@16: } Chris@16: Chris@16: // Resizing Chris@16: private: Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type restrict_capacity (size_type non_zeros) const { Chris@16: // Guarding against overflow - thanks to Alexei Novakov for the hint. Chris@16: // non_zeros = (std::min) (non_zeros, size1_ * size2_); Chris@16: if (size1_ > 0 && non_zeros / size1_ >= size2_) Chris@16: non_zeros = size1_ * size2_; Chris@16: return non_zeros; Chris@16: } Chris@16: public: Chris@16: BOOST_UBLAS_INLINE Chris@16: void resize (size_type size1, size_type size2, bool preserve = true) { Chris@16: // FIXME preserve unimplemented Chris@16: BOOST_UBLAS_CHECK (!preserve, internal_logic ()); Chris@16: size1_ = size1; Chris@16: size2_ = size2; Chris@16: data ().clear (); Chris@16: } Chris@16: Chris@16: // Reserving Chris@16: BOOST_UBLAS_INLINE Chris@16: void reserve (size_type non_zeros, bool preserve = true) { Chris@16: detail::map_reserve (data (), restrict_capacity (non_zeros)); Chris@16: } Chris@16: Chris@16: // Element support Chris@16: BOOST_UBLAS_INLINE Chris@16: pointer find_element (size_type i, size_type j) { Chris@16: return const_cast (const_cast(*this).find_element (i, j)); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: const_pointer find_element (size_type i, size_type j) const { Chris@16: const size_type element = layout_type::element (i, size1_, j, size2_); Chris@16: const_subiterator_type it (data ().find (element)); Chris@16: if (it == data ().end ()) Chris@16: return 0; Chris@16: BOOST_UBLAS_CHECK ((*it).first == element, internal_logic ()); // broken map Chris@16: return &(*it).second; Chris@16: } Chris@16: Chris@16: // Element access Chris@16: BOOST_UBLAS_INLINE Chris@16: const_reference operator () (size_type i, size_type j) const { Chris@16: const size_type element = layout_type::element (i, size1_, j, size2_); Chris@16: const_subiterator_type it (data ().find (element)); Chris@16: if (it == data ().end ()) Chris@16: return zero_; Chris@16: BOOST_UBLAS_CHECK ((*it).first == element, internal_logic ()); // broken map Chris@16: return (*it).second; Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: reference operator () (size_type i, size_type j) { Chris@16: #ifndef BOOST_UBLAS_STRICT_MATRIX_SPARSE Chris@16: const size_type element = layout_type::element (i, size1_, j, size2_); Chris@16: std::pair ii (data ().insert (typename array_type::value_type (element, value_type/*zero*/()))); Chris@16: BOOST_UBLAS_CHECK ((ii.first)->first == element, internal_logic ()); // broken map Chris@16: return (ii.first)->second; Chris@16: #else Chris@16: return reference (*this, i, j); Chris@16: #endif Chris@16: } Chris@16: Chris@16: // Element assingment Chris@16: BOOST_UBLAS_INLINE Chris@16: true_reference insert_element (size_type i, size_type j, const_reference t) { Chris@16: BOOST_UBLAS_CHECK (!find_element (i, j), bad_index ()); // duplicate element Chris@16: const size_type element = layout_type::element (i, size1_, j, size2_); Chris@16: std::pair ii (data ().insert (typename array_type::value_type (element, t))); Chris@16: BOOST_UBLAS_CHECK ((ii.first)->first == element, internal_logic ()); // broken map Chris@16: if (!ii.second) // existing element Chris@16: (ii.first)->second = t; Chris@16: return (ii.first)->second; Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: void erase_element (size_type i, size_type j) { Chris@16: subiterator_type it = data ().find (layout_type::element (i, size1_, j, size2_)); Chris@16: if (it == data ().end ()) Chris@16: return; Chris@16: data ().erase (it); Chris@16: } Chris@16: Chris@16: // Zeroing Chris@16: BOOST_UBLAS_INLINE Chris@16: void clear () { Chris@16: data ().clear (); Chris@16: } Chris@16: Chris@16: // Assignment Chris@16: BOOST_UBLAS_INLINE Chris@16: mapped_matrix &operator = (const mapped_matrix &m) { Chris@16: if (this != &m) { Chris@16: size1_ = m.size1_; Chris@16: size2_ = m.size2_; Chris@16: data () = m.data (); Chris@16: } Chris@16: return *this; Chris@16: } Chris@16: template // Container assignment without temporary Chris@16: BOOST_UBLAS_INLINE Chris@16: mapped_matrix &operator = (const matrix_container &m) { Chris@16: resize (m ().size1 (), m ().size2 (), false); Chris@16: assign (m); Chris@16: return *this; Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: mapped_matrix &assign_temporary (mapped_matrix &m) { Chris@16: swap (m); Chris@16: return *this; Chris@16: } Chris@16: template Chris@16: BOOST_UBLAS_INLINE Chris@16: mapped_matrix &operator = (const matrix_expression &ae) { Chris@16: self_type temporary (ae, detail::map_capacity (data ())); Chris@16: return assign_temporary (temporary); Chris@16: } Chris@16: template Chris@16: BOOST_UBLAS_INLINE Chris@16: mapped_matrix &assign (const matrix_expression &ae) { Chris@16: matrix_assign (*this, ae); Chris@16: return *this; Chris@16: } Chris@16: template Chris@16: BOOST_UBLAS_INLINE Chris@16: mapped_matrix& operator += (const matrix_expression &ae) { Chris@16: self_type temporary (*this + ae, detail::map_capacity (data ())); Chris@16: return assign_temporary (temporary); Chris@16: } Chris@16: template // Container assignment without temporary Chris@16: BOOST_UBLAS_INLINE Chris@16: mapped_matrix &operator += (const matrix_container &m) { Chris@16: plus_assign (m); Chris@16: return *this; Chris@16: } Chris@16: template Chris@16: BOOST_UBLAS_INLINE Chris@16: mapped_matrix &plus_assign (const matrix_expression &ae) { Chris@16: matrix_assign (*this, ae); Chris@16: return *this; Chris@16: } Chris@16: template Chris@16: BOOST_UBLAS_INLINE Chris@16: mapped_matrix& operator -= (const matrix_expression &ae) { Chris@16: self_type temporary (*this - ae, detail::map_capacity (data ())); Chris@16: return assign_temporary (temporary); Chris@16: } Chris@16: template // Container assignment without temporary Chris@16: BOOST_UBLAS_INLINE Chris@16: mapped_matrix &operator -= (const matrix_container &m) { Chris@16: minus_assign (m); Chris@16: return *this; Chris@16: } Chris@16: template Chris@16: BOOST_UBLAS_INLINE Chris@16: mapped_matrix &minus_assign (const matrix_expression &ae) { Chris@16: matrix_assign (*this, ae); Chris@16: return *this; Chris@16: } Chris@16: template Chris@16: BOOST_UBLAS_INLINE Chris@16: mapped_matrix& operator *= (const AT &at) { Chris@16: matrix_assign_scalar (*this, at); Chris@16: return *this; Chris@16: } Chris@16: template Chris@16: BOOST_UBLAS_INLINE Chris@16: mapped_matrix& operator /= (const AT &at) { Chris@16: matrix_assign_scalar (*this, at); Chris@16: return *this; Chris@16: } Chris@16: Chris@16: // Swapping Chris@16: BOOST_UBLAS_INLINE Chris@16: void swap (mapped_matrix &m) { Chris@16: if (this != &m) { Chris@16: std::swap (size1_, m.size1_); Chris@16: std::swap (size2_, m.size2_); Chris@16: data ().swap (m.data ()); Chris@16: } Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: friend void swap (mapped_matrix &m1, mapped_matrix &m2) { Chris@16: m1.swap (m2); Chris@16: } Chris@16: Chris@16: // Iterator types Chris@16: private: Chris@16: // Use storage iterator Chris@16: typedef typename A::const_iterator const_subiterator_type; Chris@16: typedef typename A::iterator subiterator_type; Chris@16: Chris@16: BOOST_UBLAS_INLINE Chris@16: true_reference at_element (size_type i, size_type j) { Chris@16: const size_type element = layout_type::element (i, size1_, j, size2_); Chris@16: subiterator_type it (data ().find (element)); Chris@16: BOOST_UBLAS_CHECK (it != data ().end(), bad_index ()); Chris@16: BOOST_UBLAS_CHECK ((*it).first == element, internal_logic ()); // broken map Chris@16: return it->second; Chris@16: } Chris@16: Chris@16: public: Chris@16: class const_iterator1; Chris@16: class iterator1; Chris@16: class const_iterator2; Chris@16: class iterator2; Chris@16: typedef reverse_iterator_base1 const_reverse_iterator1; Chris@16: typedef reverse_iterator_base1 reverse_iterator1; Chris@16: typedef reverse_iterator_base2 const_reverse_iterator2; Chris@16: typedef reverse_iterator_base2 reverse_iterator2; Chris@16: Chris@16: // Element lookup Chris@16: // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it. Chris@16: const_iterator1 find1 (int rank, size_type i, size_type j, int direction = 1) const { Chris@16: const_subiterator_type it (data ().lower_bound (layout_type::address (i, size1_, j, size2_))); Chris@16: const_subiterator_type it_end (data ().end ()); Chris@16: size_type index1 = size_type (-1); Chris@16: size_type index2 = size_type (-1); Chris@16: while (rank == 1 && it != it_end) { Chris@16: index1 = layout_type::index_i ((*it).first, size1_, size2_); Chris@16: index2 = layout_type::index_j ((*it).first, size1_, size2_); Chris@16: if (direction > 0) { Chris@16: if ((index1 >= i && index2 == j) || (i >= size1_)) Chris@16: break; Chris@16: ++ i; Chris@16: } else /* if (direction < 0) */ { Chris@16: if ((index1 <= i && index2 == j) || (i == 0)) Chris@16: break; Chris@16: -- i; Chris@16: } Chris@16: it = data ().lower_bound (layout_type::address (i, size1_, j, size2_)); Chris@16: } Chris@16: if (rank == 1 && index2 != j) { Chris@16: if (direction > 0) Chris@16: i = size1_; Chris@16: else /* if (direction < 0) */ Chris@16: i = 0; Chris@16: rank = 0; Chris@16: } Chris@16: return const_iterator1 (*this, rank, i, j, it); Chris@16: } Chris@16: // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it. Chris@16: iterator1 find1 (int rank, size_type i, size_type j, int direction = 1) { Chris@16: subiterator_type it (data ().lower_bound (layout_type::address (i, size1_, j, size2_))); Chris@16: subiterator_type it_end (data ().end ()); Chris@16: size_type index1 = size_type (-1); Chris@16: size_type index2 = size_type (-1); Chris@16: while (rank == 1 && it != it_end) { Chris@16: index1 = layout_type::index_i ((*it).first, size1_, size2_); Chris@16: index2 = layout_type::index_j ((*it).first, size1_, size2_); Chris@16: if (direction > 0) { Chris@16: if ((index1 >= i && index2 == j) || (i >= size1_)) Chris@16: break; Chris@16: ++ i; Chris@16: } else /* if (direction < 0) */ { Chris@16: if ((index1 <= i && index2 == j) || (i == 0)) Chris@16: break; Chris@16: -- i; Chris@16: } Chris@16: it = data ().lower_bound (layout_type::address (i, size1_, j, size2_)); Chris@16: } Chris@16: if (rank == 1 && index2 != j) { Chris@16: if (direction > 0) Chris@16: i = size1_; Chris@16: else /* if (direction < 0) */ Chris@16: i = 0; Chris@16: rank = 0; Chris@16: } Chris@16: return iterator1 (*this, rank, i, j, it); Chris@16: } Chris@16: // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it. Chris@16: const_iterator2 find2 (int rank, size_type i, size_type j, int direction = 1) const { Chris@16: const_subiterator_type it (data ().lower_bound (layout_type::address (i, size1_, j, size2_))); Chris@16: const_subiterator_type it_end (data ().end ()); Chris@16: size_type index1 = size_type (-1); Chris@16: size_type index2 = size_type (-1); Chris@16: while (rank == 1 && it != it_end) { Chris@16: index1 = layout_type::index_i ((*it).first, size1_, size2_); Chris@16: index2 = layout_type::index_j ((*it).first, size1_, size2_); Chris@16: if (direction > 0) { Chris@16: if ((index2 >= j && index1 == i) || (j >= size2_)) Chris@16: break; Chris@16: ++ j; Chris@16: } else /* if (direction < 0) */ { Chris@16: if ((index2 <= j && index1 == i) || (j == 0)) Chris@16: break; Chris@16: -- j; Chris@16: } Chris@16: it = data ().lower_bound (layout_type::address (i, size1_, j, size2_)); Chris@16: } Chris@16: if (rank == 1 && index1 != i) { Chris@16: if (direction > 0) Chris@16: j = size2_; Chris@16: else /* if (direction < 0) */ Chris@16: j = 0; Chris@16: rank = 0; Chris@16: } Chris@16: return const_iterator2 (*this, rank, i, j, it); Chris@16: } Chris@16: // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it. Chris@16: iterator2 find2 (int rank, size_type i, size_type j, int direction = 1) { Chris@16: subiterator_type it (data ().lower_bound (layout_type::address (i, size1_, j, size2_))); Chris@16: subiterator_type it_end (data ().end ()); Chris@16: size_type index1 = size_type (-1); Chris@16: size_type index2 = size_type (-1); Chris@16: while (rank == 1 && it != it_end) { Chris@16: index1 = layout_type::index_i ((*it).first, size1_, size2_); Chris@16: index2 = layout_type::index_j ((*it).first, size1_, size2_); Chris@16: if (direction > 0) { Chris@16: if ((index2 >= j && index1 == i) || (j >= size2_)) Chris@16: break; Chris@16: ++ j; Chris@16: } else /* if (direction < 0) */ { Chris@16: if ((index2 <= j && index1 == i) || (j == 0)) Chris@16: break; Chris@16: -- j; Chris@16: } Chris@16: it = data ().lower_bound (layout_type::address (i, size1_, j, size2_)); Chris@16: } Chris@16: if (rank == 1 && index1 != i) { Chris@16: if (direction > 0) Chris@16: j = size2_; Chris@16: else /* if (direction < 0) */ Chris@16: j = 0; Chris@16: rank = 0; Chris@16: } Chris@16: return iterator2 (*this, rank, i, j, it); Chris@16: } Chris@16: Chris@16: Chris@16: class const_iterator1: Chris@16: public container_const_reference, Chris@16: public bidirectional_iterator_base { Chris@16: public: Chris@16: typedef typename mapped_matrix::value_type value_type; Chris@16: typedef typename mapped_matrix::difference_type difference_type; Chris@16: typedef typename mapped_matrix::const_reference reference; Chris@16: typedef const typename mapped_matrix::pointer pointer; Chris@16: Chris@16: typedef const_iterator2 dual_iterator_type; Chris@16: typedef const_reverse_iterator2 dual_reverse_iterator_type; Chris@16: Chris@16: // Construction and destruction Chris@16: BOOST_UBLAS_INLINE Chris@16: const_iterator1 (): Chris@16: container_const_reference (), rank_ (), i_ (), j_ (), it_ () {} Chris@16: BOOST_UBLAS_INLINE Chris@16: const_iterator1 (const self_type &m, int rank, size_type i, size_type j, const const_subiterator_type &it): Chris@16: container_const_reference (m), rank_ (rank), i_ (i), j_ (j), it_ (it) {} Chris@16: BOOST_UBLAS_INLINE Chris@16: const_iterator1 (const iterator1 &it): Chris@16: container_const_reference (it ()), rank_ (it.rank_), i_ (it.i_), j_ (it.j_), it_ (it.it_) {} Chris@16: Chris@16: // Arithmetic Chris@16: BOOST_UBLAS_INLINE Chris@16: const_iterator1 &operator ++ () { Chris@16: if (rank_ == 1 && layout_type::fast_i ()) Chris@16: ++ it_; Chris@16: else Chris@16: *this = (*this) ().find1 (rank_, index1 () + 1, j_, 1); Chris@16: return *this; Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: const_iterator1 &operator -- () { Chris@16: if (rank_ == 1 && layout_type::fast_i ()) Chris@16: -- it_; Chris@16: else Chris@16: *this = (*this) ().find1 (rank_, index1 () - 1, j_, -1); Chris@16: return *this; Chris@16: } Chris@16: Chris@16: // Dereference Chris@16: BOOST_UBLAS_INLINE Chris@16: const_reference operator * () const { Chris@16: BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ()); Chris@16: BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ()); Chris@16: if (rank_ == 1) { Chris@16: return (*it_).second; Chris@16: } else { Chris@16: return (*this) () (i_, j_); Chris@16: } Chris@16: } Chris@16: Chris@16: #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION Chris@16: BOOST_UBLAS_INLINE Chris@16: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@16: typename self_type:: Chris@16: #endif Chris@16: const_iterator2 begin () const { Chris@16: const self_type &m = (*this) (); Chris@16: return m.find2 (1, index1 (), 0); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@16: typename self_type:: Chris@16: #endif Chris@101: const_iterator2 cbegin () const { Chris@101: return begin (); Chris@101: } Chris@101: BOOST_UBLAS_INLINE Chris@101: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@101: typename self_type:: Chris@101: #endif Chris@16: const_iterator2 end () const { Chris@16: const self_type &m = (*this) (); Chris@16: return m.find2 (1, index1 (), m.size2 ()); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@16: typename self_type:: Chris@16: #endif Chris@101: const_iterator2 cend () const { Chris@101: return end (); Chris@101: } Chris@101: BOOST_UBLAS_INLINE Chris@101: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@101: typename self_type:: Chris@101: #endif Chris@16: const_reverse_iterator2 rbegin () const { Chris@16: return const_reverse_iterator2 (end ()); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@16: typename self_type:: Chris@16: #endif Chris@101: const_reverse_iterator2 crbegin () const { Chris@101: return rbegin (); Chris@101: } Chris@101: BOOST_UBLAS_INLINE Chris@101: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@101: typename self_type:: Chris@101: #endif Chris@16: const_reverse_iterator2 rend () const { Chris@16: return const_reverse_iterator2 (begin ()); Chris@16: } Chris@101: BOOST_UBLAS_INLINE Chris@101: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@101: typename self_type:: Chris@101: #endif Chris@101: const_reverse_iterator2 crend () const { Chris@101: return rend (); Chris@101: } Chris@16: #endif Chris@16: Chris@16: // Indices Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type index1 () const { Chris@16: BOOST_UBLAS_CHECK (*this != (*this) ().find1 (0, (*this) ().size1 (), j_), bad_index ()); Chris@16: if (rank_ == 1) { Chris@16: const self_type &m = (*this) (); Chris@16: BOOST_UBLAS_CHECK (layout_type::index_i ((*it_).first, m.size1 (), m.size2 ()) < (*this) ().size1 (), bad_index ()); Chris@16: return layout_type::index_i ((*it_).first, m.size1 (), m.size2 ()); Chris@16: } else { Chris@16: return i_; Chris@16: } Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type index2 () const { Chris@16: if (rank_ == 1) { Chris@16: const self_type &m = (*this) (); Chris@16: BOOST_UBLAS_CHECK (layout_type::index_j ((*it_).first, m.size1 (), m.size2 ()) < (*this) ().size2 (), bad_index ()); Chris@16: return layout_type::index_j ((*it_).first, m.size1 (), m.size2 ()); Chris@16: } else { Chris@16: return j_; Chris@16: } Chris@16: } Chris@16: Chris@16: // Assignment Chris@16: BOOST_UBLAS_INLINE Chris@16: const_iterator1 &operator = (const const_iterator1 &it) { Chris@16: container_const_reference::assign (&it ()); Chris@16: rank_ = it.rank_; Chris@16: i_ = it.i_; Chris@16: j_ = it.j_; Chris@16: it_ = it.it_; Chris@16: return *this; Chris@16: } Chris@16: Chris@16: // Comparison Chris@16: BOOST_UBLAS_INLINE Chris@16: bool operator == (const const_iterator1 &it) const { Chris@16: BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); Chris@16: // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ()); Chris@16: if (rank_ == 1 || it.rank_ == 1) { Chris@16: return it_ == it.it_; Chris@16: } else { Chris@16: return i_ == it.i_ && j_ == it.j_; Chris@16: } Chris@16: } Chris@16: Chris@16: private: Chris@16: int rank_; Chris@16: size_type i_; Chris@16: size_type j_; Chris@16: const_subiterator_type it_; Chris@16: }; Chris@16: Chris@16: BOOST_UBLAS_INLINE Chris@16: const_iterator1 begin1 () const { Chris@16: return find1 (0, 0, 0); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@101: const_iterator1 cbegin1 () const { Chris@101: return begin1 (); Chris@101: } Chris@101: BOOST_UBLAS_INLINE Chris@16: const_iterator1 end1 () const { Chris@16: return find1 (0, size1_, 0); Chris@16: } Chris@101: BOOST_UBLAS_INLINE Chris@101: const_iterator1 cend1 () const { Chris@101: return end1 (); Chris@101: } Chris@16: Chris@16: class iterator1: Chris@16: public container_reference, Chris@16: public bidirectional_iterator_base { Chris@16: public: Chris@16: typedef typename mapped_matrix::value_type value_type; Chris@16: typedef typename mapped_matrix::difference_type difference_type; Chris@16: typedef typename mapped_matrix::true_reference reference; Chris@16: typedef typename mapped_matrix::pointer pointer; Chris@16: Chris@16: typedef iterator2 dual_iterator_type; Chris@16: typedef reverse_iterator2 dual_reverse_iterator_type; Chris@16: Chris@16: // Construction and destruction Chris@16: BOOST_UBLAS_INLINE Chris@16: iterator1 (): Chris@16: container_reference (), rank_ (), i_ (), j_ (), it_ () {} Chris@16: BOOST_UBLAS_INLINE Chris@16: iterator1 (self_type &m, int rank, size_type i, size_type j, const subiterator_type &it): Chris@16: container_reference (m), rank_ (rank), i_ (i), j_ (j), it_ (it) {} Chris@16: Chris@16: // Arithmetic Chris@16: BOOST_UBLAS_INLINE Chris@16: iterator1 &operator ++ () { Chris@16: if (rank_ == 1 && layout_type::fast_i ()) Chris@16: ++ it_; Chris@16: else Chris@16: *this = (*this) ().find1 (rank_, index1 () + 1, j_, 1); Chris@16: return *this; Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: iterator1 &operator -- () { Chris@16: if (rank_ == 1 && layout_type::fast_i ()) Chris@16: -- it_; Chris@16: else Chris@16: *this = (*this) ().find1 (rank_, index1 () - 1, j_, -1); Chris@16: return *this; Chris@16: } Chris@16: Chris@16: // Dereference Chris@16: BOOST_UBLAS_INLINE Chris@16: reference operator * () const { Chris@16: BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ()); Chris@16: BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ()); Chris@16: if (rank_ == 1) { Chris@16: return (*it_).second; Chris@16: } else { Chris@16: return (*this) ().at_element (i_, j_); Chris@16: } Chris@16: } Chris@16: Chris@16: #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION Chris@16: BOOST_UBLAS_INLINE Chris@16: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@16: typename self_type:: Chris@16: #endif Chris@16: iterator2 begin () const { Chris@16: self_type &m = (*this) (); Chris@16: return m.find2 (1, index1 (), 0); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@16: typename self_type:: Chris@16: #endif Chris@16: iterator2 end () const { Chris@16: self_type &m = (*this) (); Chris@16: return m.find2 (1, index1 (), m.size2 ()); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@16: typename self_type:: Chris@16: #endif Chris@16: reverse_iterator2 rbegin () const { Chris@16: return reverse_iterator2 (end ()); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@16: typename self_type:: Chris@16: #endif Chris@16: reverse_iterator2 rend () const { Chris@16: return reverse_iterator2 (begin ()); Chris@16: } Chris@16: #endif Chris@16: Chris@16: // Indices Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type index1 () const { Chris@16: BOOST_UBLAS_CHECK (*this != (*this) ().find1 (0, (*this) ().size1 (), j_), bad_index ()); Chris@16: if (rank_ == 1) { Chris@16: const self_type &m = (*this) (); Chris@16: BOOST_UBLAS_CHECK (layout_type::index_i ((*it_).first, m.size1 (), m.size2 ()) < (*this) ().size1 (), bad_index ()); Chris@16: return layout_type::index_i ((*it_).first, m.size1 (), m.size2 ()); Chris@16: } else { Chris@16: return i_; Chris@16: } Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type index2 () const { Chris@16: if (rank_ == 1) { Chris@16: const self_type &m = (*this) (); Chris@16: BOOST_UBLAS_CHECK (layout_type::index_j ((*it_).first, m.size1 (), m.size2 ()) < (*this) ().size2 (), bad_index ()); Chris@16: return layout_type::index_j ((*it_).first, m.size1 (), m.size2 ()); Chris@16: } else { Chris@16: return j_; Chris@16: } Chris@16: } Chris@16: Chris@16: // Assignment Chris@16: BOOST_UBLAS_INLINE Chris@16: iterator1 &operator = (const iterator1 &it) { Chris@16: container_reference::assign (&it ()); Chris@16: rank_ = it.rank_; Chris@16: i_ = it.i_; Chris@16: j_ = it.j_; Chris@16: it_ = it.it_; Chris@16: return *this; Chris@16: } Chris@16: Chris@16: // Comparison Chris@16: BOOST_UBLAS_INLINE Chris@16: bool operator == (const iterator1 &it) const { Chris@16: BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); Chris@16: // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ()); Chris@16: if (rank_ == 1 || it.rank_ == 1) { Chris@16: return it_ == it.it_; Chris@16: } else { Chris@16: return i_ == it.i_ && j_ == it.j_; Chris@16: } Chris@16: } Chris@16: Chris@16: private: Chris@16: int rank_; Chris@16: size_type i_; Chris@16: size_type j_; Chris@16: subiterator_type it_; Chris@16: Chris@16: friend class const_iterator1; Chris@16: }; Chris@16: Chris@16: BOOST_UBLAS_INLINE Chris@16: iterator1 begin1 () { Chris@16: return find1 (0, 0, 0); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: iterator1 end1 () { Chris@16: return find1 (0, size1_, 0); Chris@16: } Chris@16: Chris@16: class const_iterator2: Chris@16: public container_const_reference, Chris@16: public bidirectional_iterator_base { Chris@16: public: Chris@16: typedef typename mapped_matrix::value_type value_type; Chris@16: typedef typename mapped_matrix::difference_type difference_type; Chris@16: typedef typename mapped_matrix::const_reference reference; Chris@16: typedef const typename mapped_matrix::pointer pointer; Chris@16: Chris@16: typedef const_iterator1 dual_iterator_type; Chris@16: typedef const_reverse_iterator1 dual_reverse_iterator_type; Chris@16: Chris@16: // Construction and destruction Chris@16: BOOST_UBLAS_INLINE Chris@16: const_iterator2 (): Chris@16: container_const_reference (), rank_ (), i_ (), j_ (), it_ () {} Chris@16: BOOST_UBLAS_INLINE Chris@16: const_iterator2 (const self_type &m, int rank, size_type i, size_type j, const const_subiterator_type &it): Chris@16: container_const_reference (m), rank_ (rank), i_ (i), j_ (j), it_ (it) {} Chris@16: BOOST_UBLAS_INLINE Chris@16: const_iterator2 (const iterator2 &it): Chris@16: container_const_reference (it ()), rank_ (it.rank_), i_ (it.i_), j_ (it.j_), it_ (it.it_) {} Chris@16: Chris@16: // Arithmetic Chris@16: BOOST_UBLAS_INLINE Chris@16: const_iterator2 &operator ++ () { Chris@16: if (rank_ == 1 && layout_type::fast_j ()) Chris@16: ++ it_; Chris@16: else Chris@16: *this = (*this) ().find2 (rank_, i_, index2 () + 1, 1); Chris@16: return *this; Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: const_iterator2 &operator -- () { Chris@16: if (rank_ == 1 && layout_type::fast_j ()) Chris@16: -- it_; Chris@16: else Chris@16: *this = (*this) ().find2 (rank_, i_, index2 () - 1, -1); Chris@16: return *this; Chris@16: } Chris@16: Chris@16: // Dereference Chris@16: BOOST_UBLAS_INLINE Chris@16: const_reference operator * () const { Chris@16: BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ()); Chris@16: BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ()); Chris@16: if (rank_ == 1) { Chris@16: return (*it_).second; Chris@16: } else { Chris@16: return (*this) () (i_, j_); Chris@16: } Chris@16: } Chris@16: Chris@16: #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION Chris@16: BOOST_UBLAS_INLINE Chris@16: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@16: typename self_type:: Chris@16: #endif Chris@16: const_iterator1 begin () const { Chris@16: const self_type &m = (*this) (); Chris@16: return m.find1 (1, 0, index2 ()); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@16: typename self_type:: Chris@16: #endif Chris@101: const_iterator1 cbegin () const { Chris@101: return begin (); Chris@101: } Chris@101: BOOST_UBLAS_INLINE Chris@101: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@101: typename self_type:: Chris@101: #endif Chris@16: const_iterator1 end () const { Chris@16: const self_type &m = (*this) (); Chris@16: return m.find1 (1, m.size1 (), index2 ()); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@16: typename self_type:: Chris@16: #endif Chris@101: const_iterator1 cend () const { Chris@101: return end (); Chris@101: } Chris@101: BOOST_UBLAS_INLINE Chris@101: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@101: typename self_type:: Chris@101: #endif Chris@16: const_reverse_iterator1 rbegin () const { Chris@16: return const_reverse_iterator1 (end ()); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@16: typename self_type:: Chris@16: #endif Chris@101: const_reverse_iterator1 crbegin () const { Chris@101: return rbegin (); Chris@101: } Chris@101: BOOST_UBLAS_INLINE Chris@101: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@101: typename self_type:: Chris@101: #endif Chris@16: const_reverse_iterator1 rend () const { Chris@16: return const_reverse_iterator1 (begin ()); Chris@16: } Chris@101: BOOST_UBLAS_INLINE Chris@101: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@101: typename self_type:: Chris@101: #endif Chris@101: const_reverse_iterator1 crend () const { Chris@101: return rend (); Chris@101: } Chris@16: #endif Chris@16: Chris@16: // Indices Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type index1 () const { Chris@16: if (rank_ == 1) { Chris@16: const self_type &m = (*this) (); Chris@16: BOOST_UBLAS_CHECK (layout_type::index_i ((*it_).first, m.size1 (), m.size2 ()) < (*this) ().size1 (), bad_index ()); Chris@16: return layout_type::index_i ((*it_).first, m.size1 (), m.size2 ()); Chris@16: } else { Chris@16: return i_; Chris@16: } Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type index2 () const { Chris@16: BOOST_UBLAS_CHECK (*this != (*this) ().find2 (0, i_, (*this) ().size2 ()), bad_index ()); Chris@16: if (rank_ == 1) { Chris@16: const self_type &m = (*this) (); Chris@16: BOOST_UBLAS_CHECK (layout_type::index_j ((*it_).first, m.size1 (), m.size2 ()) < (*this) ().size2 (), bad_index ()); Chris@16: return layout_type::index_j ((*it_).first, m.size1 (), m.size2 ()); Chris@16: } else { Chris@16: return j_; Chris@16: } Chris@16: } Chris@16: Chris@16: // Assignment Chris@16: BOOST_UBLAS_INLINE Chris@16: const_iterator2 &operator = (const const_iterator2 &it) { Chris@16: container_const_reference::assign (&it ()); Chris@16: rank_ = it.rank_; Chris@16: i_ = it.i_; Chris@16: j_ = it.j_; Chris@16: it_ = it.it_; Chris@16: return *this; Chris@16: } Chris@16: Chris@16: // Comparison Chris@16: BOOST_UBLAS_INLINE Chris@16: bool operator == (const const_iterator2 &it) const { Chris@16: BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); Chris@16: // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ()); Chris@16: if (rank_ == 1 || it.rank_ == 1) { Chris@16: return it_ == it.it_; Chris@16: } else { Chris@16: return i_ == it.i_ && j_ == it.j_; Chris@16: } Chris@16: } Chris@16: Chris@16: private: Chris@16: int rank_; Chris@16: size_type i_; Chris@16: size_type j_; Chris@16: const_subiterator_type it_; Chris@16: }; Chris@16: Chris@16: BOOST_UBLAS_INLINE Chris@16: const_iterator2 begin2 () const { Chris@16: return find2 (0, 0, 0); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@101: const_iterator2 cbegin2 () const { Chris@101: return begin2 (); Chris@101: } Chris@101: BOOST_UBLAS_INLINE Chris@16: const_iterator2 end2 () const { Chris@16: return find2 (0, 0, size2_); Chris@16: } Chris@101: BOOST_UBLAS_INLINE Chris@101: const_iterator2 cend2 () const { Chris@101: return end2 (); Chris@101: } Chris@16: Chris@16: class iterator2: Chris@16: public container_reference, Chris@16: public bidirectional_iterator_base { Chris@16: public: Chris@16: typedef typename mapped_matrix::value_type value_type; Chris@16: typedef typename mapped_matrix::difference_type difference_type; Chris@16: typedef typename mapped_matrix::true_reference reference; Chris@16: typedef typename mapped_matrix::pointer pointer; Chris@16: Chris@16: typedef iterator1 dual_iterator_type; Chris@16: typedef reverse_iterator1 dual_reverse_iterator_type; Chris@16: Chris@16: // Construction and destruction Chris@16: BOOST_UBLAS_INLINE Chris@16: iterator2 (): Chris@16: container_reference (), rank_ (), i_ (), j_ (), it_ () {} Chris@16: BOOST_UBLAS_INLINE Chris@16: iterator2 (self_type &m, int rank, size_type i, size_type j, const subiterator_type &it): Chris@16: container_reference (m), rank_ (rank), i_ (i), j_ (j), it_ (it) {} Chris@16: Chris@16: // Arithmetic Chris@16: BOOST_UBLAS_INLINE Chris@16: iterator2 &operator ++ () { Chris@16: if (rank_ == 1 && layout_type::fast_j ()) Chris@16: ++ it_; Chris@16: else Chris@16: *this = (*this) ().find2 (rank_, i_, index2 () + 1, 1); Chris@16: return *this; Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: iterator2 &operator -- () { Chris@16: if (rank_ == 1 && layout_type::fast_j ()) Chris@16: -- it_; Chris@16: else Chris@16: *this = (*this) ().find2 (rank_, i_, index2 () - 1, -1); Chris@16: return *this; Chris@16: } Chris@16: Chris@16: // Dereference Chris@16: BOOST_UBLAS_INLINE Chris@16: reference operator * () const { Chris@16: BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ()); Chris@16: BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ()); Chris@16: if (rank_ == 1) { Chris@16: return (*it_).second; Chris@16: } else { Chris@16: return (*this) ().at_element (i_, j_); Chris@16: } Chris@16: } Chris@16: Chris@16: #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION Chris@16: BOOST_UBLAS_INLINE Chris@16: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@16: typename self_type:: Chris@16: #endif Chris@16: iterator1 begin () const { Chris@16: self_type &m = (*this) (); Chris@16: return m.find1 (1, 0, index2 ()); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@16: typename self_type:: Chris@16: #endif Chris@16: iterator1 end () const { Chris@16: self_type &m = (*this) (); Chris@16: return m.find1 (1, m.size1 (), index2 ()); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@16: typename self_type:: Chris@16: #endif Chris@16: reverse_iterator1 rbegin () const { Chris@16: return reverse_iterator1 (end ()); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@16: typename self_type:: Chris@16: #endif Chris@16: reverse_iterator1 rend () const { Chris@16: return reverse_iterator1 (begin ()); Chris@16: } Chris@16: #endif Chris@16: Chris@16: // Indices Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type index1 () const { Chris@16: if (rank_ == 1) { Chris@16: const self_type &m = (*this) (); Chris@16: BOOST_UBLAS_CHECK (layout_type::index_i ((*it_).first, m.size1 (), m.size2 ()) < (*this) ().size1 (), bad_index ()); Chris@16: return layout_type::index_i ((*it_).first, m.size1 (), m.size2 ()); Chris@16: } else { Chris@16: return i_; Chris@16: } Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type index2 () const { Chris@16: BOOST_UBLAS_CHECK (*this != (*this) ().find2 (0, i_, (*this) ().size2 ()), bad_index ()); Chris@16: if (rank_ == 1) { Chris@16: const self_type &m = (*this) (); Chris@16: BOOST_UBLAS_CHECK (layout_type::index_j ((*it_).first, m.size1 (), m.size2 ()) < (*this) ().size2 (), bad_index ()); Chris@16: return layout_type::index_j ((*it_).first, m.size1 (), m.size2 ()); Chris@16: } else { Chris@16: return j_; Chris@16: } Chris@16: } Chris@16: Chris@16: // Assignment Chris@16: BOOST_UBLAS_INLINE Chris@16: iterator2 &operator = (const iterator2 &it) { Chris@16: container_reference::assign (&it ()); Chris@16: rank_ = it.rank_; Chris@16: i_ = it.i_; Chris@16: j_ = it.j_; Chris@16: it_ = it.it_; Chris@16: return *this; Chris@16: } Chris@16: Chris@16: // Comparison Chris@16: BOOST_UBLAS_INLINE Chris@16: bool operator == (const iterator2 &it) const { Chris@16: BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); Chris@16: // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ()); Chris@16: if (rank_ == 1 || it.rank_ == 1) { Chris@16: return it_ == it.it_; Chris@16: } else { Chris@16: return i_ == it.i_ && j_ == it.j_; Chris@16: } Chris@16: } Chris@16: Chris@16: private: Chris@16: int rank_; Chris@16: size_type i_; Chris@16: size_type j_; Chris@16: subiterator_type it_; Chris@16: Chris@16: friend class const_iterator2; Chris@16: }; Chris@16: Chris@16: BOOST_UBLAS_INLINE Chris@16: iterator2 begin2 () { Chris@16: return find2 (0, 0, 0); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: iterator2 end2 () { Chris@16: return find2 (0, 0, size2_); Chris@16: } Chris@16: Chris@16: // Reverse iterators Chris@16: Chris@16: BOOST_UBLAS_INLINE Chris@16: const_reverse_iterator1 rbegin1 () const { Chris@16: return const_reverse_iterator1 (end1 ()); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@101: const_reverse_iterator1 crbegin1 () const { Chris@101: return rbegin1 (); Chris@101: } Chris@101: BOOST_UBLAS_INLINE Chris@16: const_reverse_iterator1 rend1 () const { Chris@16: return const_reverse_iterator1 (begin1 ()); Chris@16: } Chris@101: BOOST_UBLAS_INLINE Chris@101: const_reverse_iterator1 crend1 () const { Chris@101: return rend1 (); Chris@101: } Chris@16: Chris@16: BOOST_UBLAS_INLINE Chris@16: reverse_iterator1 rbegin1 () { Chris@16: return reverse_iterator1 (end1 ()); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: reverse_iterator1 rend1 () { Chris@16: return reverse_iterator1 (begin1 ()); Chris@16: } Chris@16: Chris@16: BOOST_UBLAS_INLINE Chris@16: const_reverse_iterator2 rbegin2 () const { Chris@16: return const_reverse_iterator2 (end2 ()); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@101: const_reverse_iterator2 crbegin2 () const { Chris@101: return rbegin2 (); Chris@101: } Chris@101: BOOST_UBLAS_INLINE Chris@16: const_reverse_iterator2 rend2 () const { Chris@16: return const_reverse_iterator2 (begin2 ()); Chris@16: } Chris@101: BOOST_UBLAS_INLINE Chris@101: const_reverse_iterator2 crend2 () const { Chris@101: return rend2 (); Chris@101: } Chris@16: Chris@16: BOOST_UBLAS_INLINE Chris@16: reverse_iterator2 rbegin2 () { Chris@16: return reverse_iterator2 (end2 ()); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: reverse_iterator2 rend2 () { Chris@16: return reverse_iterator2 (begin2 ()); Chris@16: } Chris@16: Chris@16: // Serialization Chris@16: template Chris@16: void serialize(Archive & ar, const unsigned int /* file_version */){ Chris@16: serialization::collection_size_type s1 (size1_); Chris@16: serialization::collection_size_type s2 (size2_); Chris@16: ar & serialization::make_nvp("size1",s1); Chris@16: ar & serialization::make_nvp("size2",s2); Chris@16: if (Archive::is_loading::value) { Chris@16: size1_ = s1; Chris@16: size2_ = s2; Chris@16: } Chris@16: ar & serialization::make_nvp("data", data_); Chris@16: } Chris@16: Chris@16: private: Chris@16: size_type size1_; Chris@16: size_type size2_; Chris@16: array_type data_; Chris@16: static const value_type zero_; Chris@16: }; Chris@16: Chris@16: template Chris@16: const typename mapped_matrix::value_type mapped_matrix::zero_ = value_type/*zero*/(); Chris@16: Chris@16: Chris@16: // Vector index map based sparse matrix class Chris@16: template Chris@16: class mapped_vector_of_mapped_vector: Chris@16: public matrix_container > { Chris@16: Chris@16: typedef T &true_reference; Chris@16: typedef T *pointer; Chris@16: typedef const T *const_pointer; Chris@16: typedef A array_type; Chris@16: typedef const A const_array_type; Chris@16: typedef L layout_type; Chris@16: typedef mapped_vector_of_mapped_vector self_type; Chris@16: public: Chris@16: #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS Chris@16: using matrix_container::operator (); Chris@16: #endif Chris@16: typedef typename A::size_type size_type; Chris@16: typedef typename A::difference_type difference_type; Chris@16: typedef T value_type; Chris@16: typedef const T &const_reference; Chris@16: #ifndef BOOST_UBLAS_STRICT_MATRIX_SPARSE Chris@16: typedef typename detail::map_traits::reference reference; Chris@16: #else Chris@16: typedef sparse_matrix_element reference; Chris@16: #endif Chris@16: typedef const matrix_reference const_closure_type; Chris@16: typedef matrix_reference closure_type; Chris@16: typedef mapped_vector vector_temporary_type; Chris@16: typedef self_type matrix_temporary_type; Chris@16: typedef typename A::value_type::second_type vector_data_value_type; Chris@16: typedef sparse_tag storage_category; Chris@16: typedef typename L::orientation_category orientation_category; Chris@16: Chris@16: // Construction and destruction Chris@16: BOOST_UBLAS_INLINE Chris@16: mapped_vector_of_mapped_vector (): Chris@16: matrix_container (), Chris@16: size1_ (0), size2_ (0), data_ () { Chris@16: data_ [layout_type::size_M (size1_, size2_)] = vector_data_value_type (); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: mapped_vector_of_mapped_vector (size_type size1, size_type size2, size_type non_zeros = 0): Chris@16: matrix_container (), Chris@16: size1_ (size1), size2_ (size2), data_ () { Chris@16: data_ [layout_type::size_M (size1_, size2_)] = vector_data_value_type (); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: mapped_vector_of_mapped_vector (const mapped_vector_of_mapped_vector &m): Chris@16: matrix_container (), Chris@16: size1_ (m.size1_), size2_ (m.size2_), data_ (m.data_) {} Chris@16: template Chris@16: BOOST_UBLAS_INLINE Chris@16: mapped_vector_of_mapped_vector (const matrix_expression &ae, size_type non_zeros = 0): Chris@16: matrix_container (), Chris@16: size1_ (ae ().size1 ()), size2_ (ae ().size2 ()), data_ () { Chris@16: data_ [layout_type::size_M (size1_, size2_)] = vector_data_value_type (); Chris@16: matrix_assign (*this, ae); Chris@16: } Chris@16: Chris@16: // Accessors Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type size1 () const { Chris@16: return size1_; Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type size2 () const { Chris@16: return size2_; Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type nnz_capacity () const { Chris@16: size_type non_zeros = 0; Chris@16: for (vector_const_subiterator_type itv = data_ ().begin (); itv != data_ ().end (); ++ itv) Chris@16: non_zeros += detail::map_capacity (*itv); Chris@16: return non_zeros; Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type nnz () const { Chris@16: size_type filled = 0; Chris@16: for (vector_const_subiterator_type itv = data_ ().begin (); itv != data_ ().end (); ++ itv) Chris@16: filled += (*itv).size (); Chris@16: return filled; Chris@16: } Chris@16: Chris@16: // Storage accessors Chris@16: BOOST_UBLAS_INLINE Chris@16: const_array_type &data () const { Chris@16: return data_; Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: array_type &data () { Chris@16: return data_; Chris@16: } Chris@16: Chris@16: // Resizing Chris@16: BOOST_UBLAS_INLINE Chris@16: void resize (size_type size1, size_type size2, bool preserve = true) { Chris@16: // FIXME preserve unimplemented Chris@16: BOOST_UBLAS_CHECK (!preserve, internal_logic ()); Chris@16: size1_ = size1; Chris@16: size2_ = size2; Chris@16: data ().clear (); Chris@16: data () [layout_type::size_M (size1_, size2_)] = vector_data_value_type (); Chris@16: } Chris@16: Chris@16: // Element support Chris@16: BOOST_UBLAS_INLINE Chris@16: pointer find_element (size_type i, size_type j) { Chris@16: return const_cast (const_cast(*this).find_element (i, j)); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: const_pointer find_element (size_type i, size_type j) const { Chris@16: const size_type element1 = layout_type::index_M (i, j); Chris@16: const size_type element2 = layout_type::index_m (i, j); Chris@16: vector_const_subiterator_type itv (data ().find (element1)); Chris@16: if (itv == data ().end ()) Chris@16: return 0; Chris@16: BOOST_UBLAS_CHECK ((*itv).first == element1, internal_logic ()); // broken map Chris@16: const_subiterator_type it ((*itv).second.find (element2)); Chris@16: if (it == (*itv).second.end ()) Chris@16: return 0; Chris@16: BOOST_UBLAS_CHECK ((*it).first == element2, internal_logic ()); // broken map Chris@16: return &(*it).second; Chris@16: } Chris@16: Chris@16: // Element access Chris@16: BOOST_UBLAS_INLINE Chris@16: const_reference operator () (size_type i, size_type j) const { Chris@16: const size_type element1 = layout_type::index_M (i, j); Chris@16: const size_type element2 = layout_type::index_m (i, j); Chris@16: vector_const_subiterator_type itv (data ().find (element1)); Chris@16: if (itv == data ().end ()) Chris@16: return zero_; Chris@16: BOOST_UBLAS_CHECK ((*itv).first == element1, internal_logic ()); // broken map Chris@16: const_subiterator_type it ((*itv).second.find (element2)); Chris@16: if (it == (*itv).second.end ()) Chris@16: return zero_; Chris@16: BOOST_UBLAS_CHECK ((*itv).first == element1, internal_logic ()); // broken map Chris@16: return (*it).second; Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: reference operator () (size_type i, size_type j) { Chris@16: #ifndef BOOST_UBLAS_STRICT_MATRIX_SPARSE Chris@16: const size_type element1 = layout_type::index_M (i, j); Chris@16: const size_type element2 = layout_type::index_m (i, j); Chris@16: vector_data_value_type& vd (data () [element1]); Chris@16: std::pair ii (vd.insert (typename array_type::value_type::second_type::value_type (element2, value_type/*zero*/()))); Chris@16: BOOST_UBLAS_CHECK ((ii.first)->first == element2, internal_logic ()); // broken map Chris@16: return (ii.first)->second; Chris@16: #else Chris@16: return reference (*this, i, j); Chris@16: #endif Chris@16: } Chris@16: Chris@16: // Element assignment Chris@16: BOOST_UBLAS_INLINE Chris@16: true_reference insert_element (size_type i, size_type j, const_reference t) { Chris@16: BOOST_UBLAS_CHECK (!find_element (i, j), bad_index ()); // duplicate element Chris@16: const size_type element1 = layout_type::index_M (i, j); Chris@16: const size_type element2 = layout_type::index_m (i, j); Chris@16: Chris@16: vector_data_value_type& vd (data () [element1]); Chris@16: std::pair ii (vd.insert (typename vector_data_value_type::value_type (element2, t))); Chris@16: BOOST_UBLAS_CHECK ((ii.first)->first == element2, internal_logic ()); // broken map Chris@16: if (!ii.second) // existing element Chris@16: (ii.first)->second = t; Chris@16: return (ii.first)->second; Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: void erase_element (size_type i, size_type j) { Chris@16: vector_subiterator_type itv (data ().find (layout_type::index_M (i, j))); Chris@16: if (itv == data ().end ()) Chris@16: return; Chris@16: subiterator_type it ((*itv).second.find (layout_type::index_m (i, j))); Chris@16: if (it == (*itv).second.end ()) Chris@16: return; Chris@16: (*itv).second.erase (it); Chris@16: } Chris@16: Chris@16: // Zeroing Chris@16: BOOST_UBLAS_INLINE Chris@16: void clear () { Chris@16: data ().clear (); Chris@16: data_ [layout_type::size_M (size1_, size2_)] = vector_data_value_type (); Chris@16: } Chris@16: Chris@16: // Assignment Chris@16: BOOST_UBLAS_INLINE Chris@16: mapped_vector_of_mapped_vector &operator = (const mapped_vector_of_mapped_vector &m) { Chris@16: if (this != &m) { Chris@16: size1_ = m.size1_; Chris@16: size2_ = m.size2_; Chris@16: data () = m.data (); Chris@16: } Chris@16: return *this; Chris@16: } Chris@16: template // Container assignment without temporary Chris@16: BOOST_UBLAS_INLINE Chris@16: mapped_vector_of_mapped_vector &operator = (const matrix_container &m) { Chris@16: resize (m ().size1 (), m ().size2 (), false); Chris@16: assign (m); Chris@16: return *this; Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: mapped_vector_of_mapped_vector &assign_temporary (mapped_vector_of_mapped_vector &m) { Chris@16: swap (m); Chris@16: return *this; Chris@16: } Chris@16: template Chris@16: BOOST_UBLAS_INLINE Chris@16: mapped_vector_of_mapped_vector &operator = (const matrix_expression &ae) { Chris@16: self_type temporary (ae); Chris@16: return assign_temporary (temporary); Chris@16: } Chris@16: template Chris@16: BOOST_UBLAS_INLINE Chris@16: mapped_vector_of_mapped_vector &assign (const matrix_expression &ae) { Chris@16: matrix_assign (*this, ae); Chris@16: return *this; Chris@16: } Chris@16: template Chris@16: BOOST_UBLAS_INLINE Chris@16: mapped_vector_of_mapped_vector& operator += (const matrix_expression &ae) { Chris@16: self_type temporary (*this + ae); Chris@16: return assign_temporary (temporary); Chris@16: } Chris@16: template // Container assignment without temporary Chris@16: BOOST_UBLAS_INLINE Chris@16: mapped_vector_of_mapped_vector &operator += (const matrix_container &m) { Chris@16: plus_assign (m); Chris@16: return *this; Chris@16: } Chris@16: template Chris@16: BOOST_UBLAS_INLINE Chris@16: mapped_vector_of_mapped_vector &plus_assign (const matrix_expression &ae) { Chris@16: matrix_assign (*this, ae); Chris@16: return *this; Chris@16: } Chris@16: template Chris@16: BOOST_UBLAS_INLINE Chris@16: mapped_vector_of_mapped_vector& operator -= (const matrix_expression &ae) { Chris@16: self_type temporary (*this - ae); Chris@16: return assign_temporary (temporary); Chris@16: } Chris@16: template // Container assignment without temporary Chris@16: BOOST_UBLAS_INLINE Chris@16: mapped_vector_of_mapped_vector &operator -= (const matrix_container &m) { Chris@16: minus_assign (m); Chris@16: return *this; Chris@16: } Chris@16: template Chris@16: BOOST_UBLAS_INLINE Chris@16: mapped_vector_of_mapped_vector &minus_assign (const matrix_expression &ae) { Chris@16: matrix_assign (*this, ae); Chris@16: return *this; Chris@16: } Chris@16: template Chris@16: BOOST_UBLAS_INLINE Chris@16: mapped_vector_of_mapped_vector& operator *= (const AT &at) { Chris@16: matrix_assign_scalar (*this, at); Chris@16: return *this; Chris@16: } Chris@16: template Chris@16: BOOST_UBLAS_INLINE Chris@16: mapped_vector_of_mapped_vector& operator /= (const AT &at) { Chris@16: matrix_assign_scalar (*this, at); Chris@16: return *this; Chris@16: } Chris@16: Chris@16: // Swapping Chris@16: BOOST_UBLAS_INLINE Chris@16: void swap (mapped_vector_of_mapped_vector &m) { Chris@16: if (this != &m) { Chris@16: std::swap (size1_, m.size1_); Chris@16: std::swap (size2_, m.size2_); Chris@16: data ().swap (m.data ()); Chris@16: } Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: friend void swap (mapped_vector_of_mapped_vector &m1, mapped_vector_of_mapped_vector &m2) { Chris@16: m1.swap (m2); Chris@16: } Chris@16: Chris@16: // Iterator types Chris@16: private: Chris@16: // Use storage iterators Chris@16: typedef typename A::const_iterator vector_const_subiterator_type; Chris@16: typedef typename A::iterator vector_subiterator_type; Chris@16: typedef typename A::value_type::second_type::const_iterator const_subiterator_type; Chris@16: typedef typename A::value_type::second_type::iterator subiterator_type; Chris@16: Chris@16: BOOST_UBLAS_INLINE Chris@16: true_reference at_element (size_type i, size_type j) { Chris@16: const size_type element1 = layout_type::index_M (i, j); Chris@16: const size_type element2 = layout_type::index_m (i, j); Chris@16: vector_subiterator_type itv (data ().find (element1)); Chris@16: BOOST_UBLAS_CHECK (itv != data ().end(), bad_index ()); Chris@16: BOOST_UBLAS_CHECK ((*itv).first == element1, internal_logic ()); // broken map Chris@16: subiterator_type it ((*itv).second.find (element2)); Chris@16: BOOST_UBLAS_CHECK (it != (*itv).second.end (), bad_index ()); Chris@16: BOOST_UBLAS_CHECK ((*it).first == element2, internal_logic ()); // broken map Chris@16: Chris@16: return it->second; Chris@16: } Chris@16: Chris@16: public: Chris@16: class const_iterator1; Chris@16: class iterator1; Chris@16: class const_iterator2; Chris@16: class iterator2; Chris@16: typedef reverse_iterator_base1 const_reverse_iterator1; Chris@16: typedef reverse_iterator_base1 reverse_iterator1; Chris@16: typedef reverse_iterator_base2 const_reverse_iterator2; Chris@16: typedef reverse_iterator_base2 reverse_iterator2; Chris@16: Chris@16: // Element lookup Chris@16: // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it. Chris@16: const_iterator1 find1 (int rank, size_type i, size_type j, int direction = 1) const { Chris@16: BOOST_UBLAS_CHECK (data ().begin () != data ().end (), internal_logic ()); Chris@16: for (;;) { Chris@16: vector_const_subiterator_type itv (data ().lower_bound (layout_type::index_M (i, j))); Chris@16: vector_const_subiterator_type itv_end (data ().end ()); Chris@16: if (itv == itv_end) Chris@16: return const_iterator1 (*this, rank, i, j, itv_end, (*(-- itv)).second.end ()); Chris@16: Chris@16: const_subiterator_type it ((*itv).second.lower_bound (layout_type::index_m (i, j))); Chris@16: const_subiterator_type it_end ((*itv).second.end ()); Chris@16: if (rank == 0) { Chris@16: // advance to the first available major index Chris@16: size_type M = itv->first; Chris@16: size_type m; Chris@16: if (it != it_end) { Chris@16: m = it->first; Chris@16: } else { Chris@16: m = layout_type::size_m(size1_, size2_); Chris@16: } Chris@16: size_type first_i = layout_type::index_M(M,m); Chris@16: return const_iterator1 (*this, rank, first_i, j, itv, it); Chris@16: } Chris@16: if (it != it_end && (*it).first == layout_type::index_m (i, j)) Chris@16: return const_iterator1 (*this, rank, i, j, itv, it); Chris@16: if (direction > 0) { Chris@16: if (layout_type::fast_i ()) { Chris@16: if (it == it_end) Chris@16: return const_iterator1 (*this, rank, i, j, itv, it); Chris@16: i = (*it).first; Chris@16: } else { Chris@16: if (i >= size1_) Chris@16: return const_iterator1 (*this, rank, i, j, itv, it); Chris@16: ++ i; Chris@16: } Chris@16: } else /* if (direction < 0) */ { Chris@16: if (layout_type::fast_i ()) { Chris@16: if (it == (*itv).second.begin ()) Chris@16: return const_iterator1 (*this, rank, i, j, itv, it); Chris@16: -- it; Chris@16: i = (*it).first; Chris@16: } else { Chris@16: if (i == 0) Chris@16: return const_iterator1 (*this, rank, i, j, itv, it); Chris@16: -- i; Chris@16: } Chris@16: } Chris@16: } Chris@16: } Chris@16: // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it. Chris@16: iterator1 find1 (int rank, size_type i, size_type j, int direction = 1) { Chris@16: BOOST_UBLAS_CHECK (data ().begin () != data ().end (), internal_logic ()); Chris@16: for (;;) { Chris@16: vector_subiterator_type itv (data ().lower_bound (layout_type::index_M (i, j))); Chris@16: vector_subiterator_type itv_end (data ().end ()); Chris@16: if (itv == itv_end) Chris@16: return iterator1 (*this, rank, i, j, itv_end, (*(-- itv)).second.end ()); Chris@16: Chris@16: subiterator_type it ((*itv).second.lower_bound (layout_type::index_m (i, j))); Chris@16: subiterator_type it_end ((*itv).second.end ()); Chris@16: if (rank == 0) { Chris@16: // advance to the first available major index Chris@16: size_type M = itv->first; Chris@16: size_type m; Chris@16: if (it != it_end) { Chris@16: m = it->first; Chris@16: } else { Chris@16: m = layout_type::size_m(size1_, size2_); Chris@16: } Chris@16: size_type first_i = layout_type::index_M(M,m); Chris@16: return iterator1 (*this, rank, first_i, j, itv, it); Chris@16: } Chris@16: if (it != it_end && (*it).first == layout_type::index_m (i, j)) Chris@16: return iterator1 (*this, rank, i, j, itv, it); Chris@16: if (direction > 0) { Chris@16: if (layout_type::fast_i ()) { Chris@16: if (it == it_end) Chris@16: return iterator1 (*this, rank, i, j, itv, it); Chris@16: i = (*it).first; Chris@16: } else { Chris@16: if (i >= size1_) Chris@16: return iterator1 (*this, rank, i, j, itv, it); Chris@16: ++ i; Chris@16: } Chris@16: } else /* if (direction < 0) */ { Chris@16: if (layout_type::fast_i ()) { Chris@16: if (it == (*itv).second.begin ()) Chris@16: return iterator1 (*this, rank, i, j, itv, it); Chris@16: -- it; Chris@16: i = (*it).first; Chris@16: } else { Chris@16: if (i == 0) Chris@16: return iterator1 (*this, rank, i, j, itv, it); Chris@16: -- i; Chris@16: } Chris@16: } Chris@16: } Chris@16: } Chris@16: // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it. Chris@16: const_iterator2 find2 (int rank, size_type i, size_type j, int direction = 1) const { Chris@16: BOOST_UBLAS_CHECK (data ().begin () != data ().end (), internal_logic ()); Chris@16: for (;;) { Chris@16: vector_const_subiterator_type itv (data ().lower_bound (layout_type::index_M (i, j))); Chris@16: vector_const_subiterator_type itv_end (data ().end ()); Chris@16: if (itv == itv_end) Chris@16: return const_iterator2 (*this, rank, i, j, itv_end, (*(-- itv)).second.end ()); Chris@16: Chris@16: const_subiterator_type it ((*itv).second.lower_bound (layout_type::index_m (i, j))); Chris@16: const_subiterator_type it_end ((*itv).second.end ()); Chris@16: if (rank == 0) { Chris@16: // advance to the first available major index Chris@16: size_type M = itv->first; Chris@16: size_type m; Chris@16: if (it != it_end) { Chris@16: m = it->first; Chris@16: } else { Chris@16: m = layout_type::size_m(size1_, size2_); Chris@16: } Chris@16: size_type first_j = layout_type::index_m(M,m); Chris@16: return const_iterator2 (*this, rank, i, first_j, itv, it); Chris@16: } Chris@16: if (it != it_end && (*it).first == layout_type::index_m (i, j)) Chris@16: return const_iterator2 (*this, rank, i, j, itv, it); Chris@16: if (direction > 0) { Chris@16: if (layout_type::fast_j ()) { Chris@16: if (it == it_end) Chris@16: return const_iterator2 (*this, rank, i, j, itv, it); Chris@16: j = (*it).first; Chris@16: } else { Chris@16: if (j >= size2_) Chris@16: return const_iterator2 (*this, rank, i, j, itv, it); Chris@16: ++ j; Chris@16: } Chris@16: } else /* if (direction < 0) */ { Chris@16: if (layout_type::fast_j ()) { Chris@16: if (it == (*itv).second.begin ()) Chris@16: return const_iterator2 (*this, rank, i, j, itv, it); Chris@16: -- it; Chris@16: j = (*it).first; Chris@16: } else { Chris@16: if (j == 0) Chris@16: return const_iterator2 (*this, rank, i, j, itv, it); Chris@16: -- j; Chris@16: } Chris@16: } Chris@16: } Chris@16: } Chris@16: // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it. Chris@16: iterator2 find2 (int rank, size_type i, size_type j, int direction = 1) { Chris@16: BOOST_UBLAS_CHECK (data ().begin () != data ().end (), internal_logic ()); Chris@16: for (;;) { Chris@16: vector_subiterator_type itv (data ().lower_bound (layout_type::index_M (i, j))); Chris@16: vector_subiterator_type itv_end (data ().end ()); Chris@16: if (itv == itv_end) Chris@16: return iterator2 (*this, rank, i, j, itv_end, (*(-- itv)).second.end ()); Chris@16: Chris@16: subiterator_type it ((*itv).second.lower_bound (layout_type::index_m (i, j))); Chris@16: subiterator_type it_end ((*itv).second.end ()); Chris@16: if (rank == 0) { Chris@16: // advance to the first available major index Chris@16: size_type M = itv->first; Chris@16: size_type m; Chris@16: if (it != it_end) { Chris@16: m = it->first; Chris@16: } else { Chris@16: m = layout_type::size_m(size1_, size2_); Chris@16: } Chris@16: size_type first_j = layout_type::index_m(M,m); Chris@16: return iterator2 (*this, rank, i, first_j, itv, it); Chris@16: } Chris@16: if (it != it_end && (*it).first == layout_type::index_m (i, j)) Chris@16: return iterator2 (*this, rank, i, j, itv, it); Chris@16: if (direction > 0) { Chris@16: if (layout_type::fast_j ()) { Chris@16: if (it == it_end) Chris@16: return iterator2 (*this, rank, i, j, itv, it); Chris@16: j = (*it).first; Chris@16: } else { Chris@16: if (j >= size2_) Chris@16: return iterator2 (*this, rank, i, j, itv, it); Chris@16: ++ j; Chris@16: } Chris@16: } else /* if (direction < 0) */ { Chris@16: if (layout_type::fast_j ()) { Chris@16: if (it == (*itv).second.begin ()) Chris@16: return iterator2 (*this, rank, i, j, itv, it); Chris@16: -- it; Chris@16: j = (*it).first; Chris@16: } else { Chris@16: if (j == 0) Chris@16: return iterator2 (*this, rank, i, j, itv, it); Chris@16: -- j; Chris@16: } Chris@16: } Chris@16: } Chris@16: } Chris@16: Chris@16: class const_iterator1: Chris@16: public container_const_reference, Chris@16: public bidirectional_iterator_base { Chris@16: public: Chris@16: typedef typename mapped_vector_of_mapped_vector::value_type value_type; Chris@16: typedef typename mapped_vector_of_mapped_vector::difference_type difference_type; Chris@16: typedef typename mapped_vector_of_mapped_vector::const_reference reference; Chris@16: typedef const typename mapped_vector_of_mapped_vector::pointer pointer; Chris@16: Chris@16: typedef const_iterator2 dual_iterator_type; Chris@16: typedef const_reverse_iterator2 dual_reverse_iterator_type; Chris@16: Chris@16: // Construction and destruction Chris@16: BOOST_UBLAS_INLINE Chris@16: const_iterator1 (): Chris@16: container_const_reference (), rank_ (), i_ (), j_ (), itv_ (), it_ () {} Chris@16: BOOST_UBLAS_INLINE Chris@16: const_iterator1 (const self_type &m, int rank, size_type i, size_type j, const vector_const_subiterator_type &itv, const const_subiterator_type &it): Chris@16: container_const_reference (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {} Chris@16: BOOST_UBLAS_INLINE Chris@16: const_iterator1 (const iterator1 &it): Chris@16: container_const_reference (it ()), rank_ (it.rank_), i_ (it.i_), j_ (it.j_), itv_ (it.itv_), it_ (it.it_) {} Chris@16: Chris@16: // Arithmetic Chris@16: BOOST_UBLAS_INLINE Chris@16: const_iterator1 &operator ++ () { Chris@16: if (rank_ == 1 && layout_type::fast_i ()) Chris@16: ++ it_; Chris@16: else { Chris@16: const self_type &m = (*this) (); Chris@16: if (rank_ == 0) { Chris@16: ++ itv_; Chris@16: i_ = itv_->first; Chris@16: } else { Chris@16: i_ = index1 () + 1; Chris@16: } Chris@16: if (rank_ == 1 && ++ itv_ == m.end1 ().itv_) Chris@16: *this = m.find1 (rank_, i_, j_, 1); Chris@16: else if (rank_ == 1) { Chris@16: it_ = (*itv_).second.begin (); Chris@16: if (it_ == (*itv_).second.end () || index2 () != j_) Chris@16: *this = m.find1 (rank_, i_, j_, 1); Chris@16: } Chris@16: } Chris@16: return *this; Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: const_iterator1 &operator -- () { Chris@16: if (rank_ == 1 && layout_type::fast_i ()) Chris@16: -- it_; Chris@16: else { Chris@16: const self_type &m = (*this) (); Chris@16: if (rank_ == 0) { Chris@16: -- itv_; Chris@16: i_ = itv_->first; Chris@16: } else { Chris@16: i_ = index1 () - 1; Chris@16: } Chris@16: // FIXME: this expression should never become true! Chris@16: if (rank_ == 1 && -- itv_ == m.end1 ().itv_) Chris@16: *this = m.find1 (rank_, i_, j_, -1); Chris@16: else if (rank_ == 1) { Chris@16: it_ = (*itv_).second.begin (); Chris@16: if (it_ == (*itv_).second.end () || index2 () != j_) Chris@16: *this = m.find1 (rank_, i_, j_, -1); Chris@16: } Chris@16: } Chris@16: return *this; Chris@16: } Chris@16: Chris@16: // Dereference Chris@16: BOOST_UBLAS_INLINE Chris@16: const_reference operator * () const { Chris@16: BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ()); Chris@16: BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ()); Chris@16: if (rank_ == 1) { Chris@16: return (*it_).second; Chris@16: } else { Chris@16: return (*this) () (i_, j_); Chris@16: } Chris@16: } Chris@16: Chris@16: #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION Chris@16: BOOST_UBLAS_INLINE Chris@16: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@16: typename self_type:: Chris@16: #endif Chris@16: const_iterator2 begin () const { Chris@16: const self_type &m = (*this) (); Chris@16: return m.find2 (1, index1 (), 0); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@16: typename self_type:: Chris@16: #endif Chris@101: const_iterator2 cbegin () const { Chris@101: return begin (); Chris@101: } Chris@101: BOOST_UBLAS_INLINE Chris@101: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@101: typename self_type:: Chris@101: #endif Chris@16: const_iterator2 end () const { Chris@16: const self_type &m = (*this) (); Chris@16: return m.find2 (1, index1 (), m.size2 ()); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@16: typename self_type:: Chris@16: #endif Chris@101: const_iterator2 cend () const { Chris@101: return end (); Chris@101: } Chris@101: BOOST_UBLAS_INLINE Chris@101: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@101: typename self_type:: Chris@101: #endif Chris@16: const_reverse_iterator2 rbegin () const { Chris@16: return const_reverse_iterator2 (end ()); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@16: typename self_type:: Chris@16: #endif Chris@101: const_reverse_iterator2 crbegin () const { Chris@101: return rbegin (); Chris@101: } Chris@101: BOOST_UBLAS_INLINE Chris@101: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@101: typename self_type:: Chris@101: #endif Chris@16: const_reverse_iterator2 rend () const { Chris@16: return const_reverse_iterator2 (begin ()); Chris@16: } Chris@101: BOOST_UBLAS_INLINE Chris@101: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@101: typename self_type:: Chris@101: #endif Chris@101: const_reverse_iterator2 crend () const { Chris@101: return rend (); Chris@101: } Chris@16: #endif Chris@16: Chris@16: // Indices Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type index1 () const { Chris@16: BOOST_UBLAS_CHECK (*this != (*this) ().find1 (0, (*this) ().size1 (), j_), bad_index ()); Chris@16: if (rank_ == 1) { Chris@16: BOOST_UBLAS_CHECK (layout_type::index_M ((*itv_).first, (*it_).first) < (*this) ().size1 (), bad_index ()); Chris@16: return layout_type::index_M ((*itv_).first, (*it_).first); Chris@16: } else { Chris@16: return i_; Chris@16: } Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type index2 () const { Chris@16: if (rank_ == 1) { Chris@16: BOOST_UBLAS_CHECK (layout_type::index_m ((*itv_).first, (*it_).first) < (*this) ().size2 (), bad_index ()); Chris@16: return layout_type::index_m ((*itv_).first, (*it_).first); Chris@16: } else { Chris@16: return j_; Chris@16: } Chris@16: } Chris@16: Chris@16: // Assignment Chris@16: BOOST_UBLAS_INLINE Chris@16: const_iterator1 &operator = (const const_iterator1 &it) { Chris@16: container_const_reference::assign (&it ()); Chris@16: rank_ = it.rank_; Chris@16: i_ = it.i_; Chris@16: j_ = it.j_; Chris@16: itv_ = it.itv_; Chris@16: it_ = it.it_; Chris@16: return *this; Chris@16: } Chris@16: Chris@16: // Comparison Chris@16: BOOST_UBLAS_INLINE Chris@16: bool operator == (const const_iterator1 &it) const { Chris@16: BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); Chris@16: // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ()); Chris@16: if (rank_ == 1 || it.rank_ == 1) { Chris@16: return it_ == it.it_; Chris@16: } else { Chris@16: return i_ == it.i_ && j_ == it.j_; Chris@16: } Chris@16: } Chris@16: Chris@16: private: Chris@16: int rank_; Chris@16: size_type i_; Chris@16: size_type j_; Chris@16: vector_const_subiterator_type itv_; Chris@16: const_subiterator_type it_; Chris@16: }; Chris@16: Chris@16: BOOST_UBLAS_INLINE Chris@16: const_iterator1 begin1 () const { Chris@16: return find1 (0, 0, 0); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@101: const_iterator1 cbegin1 () const { Chris@101: return begin1 (); Chris@101: } Chris@101: BOOST_UBLAS_INLINE Chris@16: const_iterator1 end1 () const { Chris@16: return find1 (0, size1_, 0); Chris@16: } Chris@101: BOOST_UBLAS_INLINE Chris@101: const_iterator1 cend1 () const { Chris@101: return end1 (); Chris@101: } Chris@16: Chris@16: class iterator1: Chris@16: public container_reference, Chris@16: public bidirectional_iterator_base { Chris@16: public: Chris@16: typedef typename mapped_vector_of_mapped_vector::value_type value_type; Chris@16: typedef typename mapped_vector_of_mapped_vector::difference_type difference_type; Chris@16: typedef typename mapped_vector_of_mapped_vector::true_reference reference; Chris@16: typedef typename mapped_vector_of_mapped_vector::pointer pointer; Chris@16: Chris@16: typedef iterator2 dual_iterator_type; Chris@16: typedef reverse_iterator2 dual_reverse_iterator_type; Chris@16: Chris@16: // Construction and destruction Chris@16: BOOST_UBLAS_INLINE Chris@16: iterator1 (): Chris@16: container_reference (), rank_ (), i_ (), j_ (), itv_ (), it_ () {} Chris@16: BOOST_UBLAS_INLINE Chris@16: iterator1 (self_type &m, int rank, size_type i, size_type j, const vector_subiterator_type &itv, const subiterator_type &it): Chris@16: container_reference (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {} Chris@16: Chris@16: // Arithmetic Chris@16: BOOST_UBLAS_INLINE Chris@16: iterator1 &operator ++ () { Chris@16: if (rank_ == 1 && layout_type::fast_i ()) Chris@16: ++ it_; Chris@16: else { Chris@16: self_type &m = (*this) (); Chris@16: if (rank_ == 0) { Chris@16: ++ itv_; Chris@16: i_ = itv_->first; Chris@16: } else { Chris@16: i_ = index1 () + 1; Chris@16: } Chris@16: if (rank_ == 1 && ++ itv_ == m.end1 ().itv_) Chris@16: *this = m.find1 (rank_, i_, j_, 1); Chris@16: else if (rank_ == 1) { Chris@16: it_ = (*itv_).second.begin (); Chris@16: if (it_ == (*itv_).second.end () || index2 () != j_) Chris@16: *this = m.find1 (rank_, i_, j_, 1); Chris@16: } Chris@16: } Chris@16: return *this; Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: iterator1 &operator -- () { Chris@16: if (rank_ == 1 && layout_type::fast_i ()) Chris@16: -- it_; Chris@16: else { Chris@16: self_type &m = (*this) (); Chris@16: if (rank_ == 0) { Chris@16: -- itv_; Chris@16: i_ = itv_->first; Chris@16: } else { Chris@16: i_ = index1 () - 1; Chris@16: } Chris@16: // FIXME: this expression should never become true! Chris@16: if (rank_ == 1 && -- itv_ == m.end1 ().itv_) Chris@16: *this = m.find1 (rank_, i_, j_, -1); Chris@16: else if (rank_ == 1) { Chris@16: it_ = (*itv_).second.begin (); Chris@16: if (it_ == (*itv_).second.end () || index2 () != j_) Chris@16: *this = m.find1 (rank_, i_, j_, -1); Chris@16: } Chris@16: } Chris@16: return *this; Chris@16: } Chris@16: Chris@16: // Dereference Chris@16: BOOST_UBLAS_INLINE Chris@16: reference operator * () const { Chris@16: BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ()); Chris@16: BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ()); Chris@16: if (rank_ == 1) { Chris@16: return (*it_).second; Chris@16: } else { Chris@16: return (*this) ().at_element (i_, j_); Chris@16: } Chris@16: } Chris@16: Chris@16: #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION Chris@16: BOOST_UBLAS_INLINE Chris@16: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@16: typename self_type:: Chris@16: #endif Chris@16: iterator2 begin () const { Chris@16: self_type &m = (*this) (); Chris@16: return m.find2 (1, index1 (), 0); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@16: typename self_type:: Chris@16: #endif Chris@16: iterator2 end () const { Chris@16: self_type &m = (*this) (); Chris@16: return m.find2 (1, index1 (), m.size2 ()); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@16: typename self_type:: Chris@16: #endif Chris@16: reverse_iterator2 rbegin () const { Chris@16: return reverse_iterator2 (end ()); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@16: typename self_type:: Chris@16: #endif Chris@16: reverse_iterator2 rend () const { Chris@16: return reverse_iterator2 (begin ()); Chris@16: } Chris@16: #endif Chris@16: Chris@16: // Indices Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type index1 () const { Chris@16: BOOST_UBLAS_CHECK (*this != (*this) ().find1 (0, (*this) ().size1 (), j_), bad_index ()); Chris@16: if (rank_ == 1) { Chris@16: BOOST_UBLAS_CHECK (layout_type::index_M ((*itv_).first, (*it_).first) < (*this) ().size1 (), bad_index ()); Chris@16: return layout_type::index_M ((*itv_).first, (*it_).first); Chris@16: } else { Chris@16: return i_; Chris@16: } Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type index2 () const { Chris@16: if (rank_ == 1) { Chris@16: BOOST_UBLAS_CHECK (layout_type::index_m ((*itv_).first, (*it_).first) < (*this) ().size2 (), bad_index ()); Chris@16: return layout_type::index_m ((*itv_).first, (*it_).first); Chris@16: } else { Chris@16: return j_; Chris@16: } Chris@16: } Chris@16: Chris@16: // Assignment Chris@16: BOOST_UBLAS_INLINE Chris@16: iterator1 &operator = (const iterator1 &it) { Chris@16: container_reference::assign (&it ()); Chris@16: rank_ = it.rank_; Chris@16: i_ = it.i_; Chris@16: j_ = it.j_; Chris@16: itv_ = it.itv_; Chris@16: it_ = it.it_; Chris@16: return *this; Chris@16: } Chris@16: Chris@16: // Comparison Chris@16: BOOST_UBLAS_INLINE Chris@16: bool operator == (const iterator1 &it) const { Chris@16: BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); Chris@16: // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ()); Chris@16: if (rank_ == 1 || it.rank_ == 1) { Chris@16: return it_ == it.it_; Chris@16: } else { Chris@16: return i_ == it.i_ && j_ == it.j_; Chris@16: } Chris@16: } Chris@16: Chris@16: private: Chris@16: int rank_; Chris@16: size_type i_; Chris@16: size_type j_; Chris@16: vector_subiterator_type itv_; Chris@16: subiterator_type it_; Chris@16: Chris@16: friend class const_iterator1; Chris@16: }; Chris@16: Chris@16: BOOST_UBLAS_INLINE Chris@16: iterator1 begin1 () { Chris@16: return find1 (0, 0, 0); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: iterator1 end1 () { Chris@16: return find1 (0, size1_, 0); Chris@16: } Chris@16: Chris@16: class const_iterator2: Chris@16: public container_const_reference, Chris@16: public bidirectional_iterator_base { Chris@16: public: Chris@16: typedef typename mapped_vector_of_mapped_vector::value_type value_type; Chris@16: typedef typename mapped_vector_of_mapped_vector::difference_type difference_type; Chris@16: typedef typename mapped_vector_of_mapped_vector::const_reference reference; Chris@16: typedef const typename mapped_vector_of_mapped_vector::pointer pointer; Chris@16: Chris@16: typedef const_iterator1 dual_iterator_type; Chris@16: typedef const_reverse_iterator1 dual_reverse_iterator_type; Chris@16: Chris@16: // Construction and destruction Chris@16: BOOST_UBLAS_INLINE Chris@16: const_iterator2 (): Chris@16: container_const_reference (), rank_ (), i_ (), j_ (), itv_ (), it_ () {} Chris@16: BOOST_UBLAS_INLINE Chris@16: const_iterator2 (const self_type &m, int rank, size_type i, size_type j, const vector_const_subiterator_type &itv, const const_subiterator_type &it): Chris@16: container_const_reference (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {} Chris@16: BOOST_UBLAS_INLINE Chris@16: const_iterator2 (const iterator2 &it): Chris@16: container_const_reference (it ()), rank_ (it.rank_), i_ (it.i_), j_ (it.j_), itv_ (it.itv_), it_ (it.it_) {} Chris@16: Chris@16: // Arithmetic Chris@16: BOOST_UBLAS_INLINE Chris@16: const_iterator2 &operator ++ () { Chris@16: if (rank_ == 1 && layout_type::fast_j ()) Chris@16: ++ it_; Chris@16: else { Chris@16: const self_type &m = (*this) (); Chris@16: if (rank_ == 0) { Chris@16: ++ itv_; Chris@16: j_ = itv_->first; Chris@16: } else { Chris@16: j_ = index2 () + 1; Chris@16: } Chris@16: if (rank_ == 1 && ++ itv_ == m.end2 ().itv_) Chris@16: *this = m.find2 (rank_, i_, j_, 1); Chris@16: else if (rank_ == 1) { Chris@16: it_ = (*itv_).second.begin (); Chris@16: if (it_ == (*itv_).second.end () || index1 () != i_) Chris@16: *this = m.find2 (rank_, i_, j_, 1); Chris@16: } Chris@16: } Chris@16: return *this; Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: const_iterator2 &operator -- () { Chris@16: if (rank_ == 1 && layout_type::fast_j ()) Chris@16: -- it_; Chris@16: else { Chris@16: const self_type &m = (*this) (); Chris@16: if (rank_ == 0) { Chris@16: -- itv_; Chris@16: j_ = itv_->first; Chris@16: } else { Chris@16: j_ = index2 () - 1; Chris@16: } Chris@16: // FIXME: this expression should never become true! Chris@16: if (rank_ == 1 && -- itv_ == m.end2 ().itv_) Chris@16: *this = m.find2 (rank_, i_, j_, -1); Chris@16: else if (rank_ == 1) { Chris@16: it_ = (*itv_).second.begin (); Chris@16: if (it_ == (*itv_).second.end () || index1 () != i_) Chris@16: *this = m.find2 (rank_, i_, j_, -1); Chris@16: } Chris@16: } Chris@16: return *this; Chris@16: } Chris@16: Chris@16: // Dereference Chris@16: BOOST_UBLAS_INLINE Chris@16: const_reference operator * () const { Chris@16: BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ()); Chris@16: BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ()); Chris@16: if (rank_ == 1) { Chris@16: return (*it_).second; Chris@16: } else { Chris@16: return (*this) () (i_, j_); Chris@16: } Chris@16: } Chris@16: Chris@16: #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION Chris@16: BOOST_UBLAS_INLINE Chris@16: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@16: typename self_type:: Chris@16: #endif Chris@16: const_iterator1 begin () const { Chris@16: const self_type &m = (*this) (); Chris@16: return m.find1 (1, 0, index2 ()); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@16: typename self_type:: Chris@16: #endif Chris@101: const_iterator1 cbegin () const { Chris@101: return begin (); Chris@101: } Chris@101: BOOST_UBLAS_INLINE Chris@101: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@101: typename self_type:: Chris@101: #endif Chris@16: const_iterator1 end () const { Chris@16: const self_type &m = (*this) (); Chris@16: return m.find1 (1, m.size1 (), index2 ()); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@16: typename self_type:: Chris@16: #endif Chris@101: const_iterator1 cend () const { Chris@101: return end (); Chris@101: } Chris@101: BOOST_UBLAS_INLINE Chris@101: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@101: typename self_type:: Chris@101: #endif Chris@16: const_reverse_iterator1 rbegin () const { Chris@16: return const_reverse_iterator1 (end ()); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@16: typename self_type:: Chris@16: #endif Chris@101: const_reverse_iterator1 crbegin () const { Chris@101: return rbegin (); Chris@101: } Chris@101: BOOST_UBLAS_INLINE Chris@101: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@101: typename self_type:: Chris@101: #endif Chris@16: const_reverse_iterator1 rend () const { Chris@16: return const_reverse_iterator1 (begin ()); Chris@16: } Chris@101: BOOST_UBLAS_INLINE Chris@101: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@101: typename self_type:: Chris@101: #endif Chris@101: const_reverse_iterator1 crend () const { Chris@101: return rend (); Chris@101: } Chris@16: #endif Chris@16: Chris@16: // Indices Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type index1 () const { Chris@16: if (rank_ == 1) { Chris@16: BOOST_UBLAS_CHECK (layout_type::index_M ((*itv_).first, (*it_).first) < (*this) ().size1 (), bad_index ()); Chris@16: return layout_type::index_M ((*itv_).first, (*it_).first); Chris@16: } else { Chris@16: return i_; Chris@16: } Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type index2 () const { Chris@16: BOOST_UBLAS_CHECK (*this != (*this) ().find2 (0, i_, (*this) ().size2 ()), bad_index ()); Chris@16: if (rank_ == 1) { Chris@16: BOOST_UBLAS_CHECK (layout_type::index_m ((*itv_).first, (*it_).first) < (*this) ().size2 (), bad_index ()); Chris@16: return layout_type::index_m ((*itv_).first, (*it_).first); Chris@16: } else { Chris@16: return j_; Chris@16: } Chris@16: } Chris@16: Chris@16: // Assignment Chris@16: BOOST_UBLAS_INLINE Chris@16: const_iterator2 &operator = (const const_iterator2 &it) { Chris@16: container_const_reference::assign (&it ()); Chris@16: rank_ = it.rank_; Chris@16: i_ = it.i_; Chris@16: j_ = it.j_; Chris@16: itv_ = it.itv_; Chris@16: it_ = it.it_; Chris@16: return *this; Chris@16: } Chris@16: Chris@16: // Comparison Chris@16: BOOST_UBLAS_INLINE Chris@16: bool operator == (const const_iterator2 &it) const { Chris@16: BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); Chris@16: // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ()); Chris@16: if (rank_ == 1 || it.rank_ == 1) { Chris@16: return it_ == it.it_; Chris@16: } else { Chris@16: return i_ == it.i_ && j_ == it.j_; Chris@16: } Chris@16: } Chris@16: Chris@16: private: Chris@16: int rank_; Chris@16: size_type i_; Chris@16: size_type j_; Chris@16: vector_const_subiterator_type itv_; Chris@16: const_subiterator_type it_; Chris@16: }; Chris@16: Chris@16: BOOST_UBLAS_INLINE Chris@16: const_iterator2 begin2 () const { Chris@16: return find2 (0, 0, 0); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@101: const_iterator2 cbegin2 () const { Chris@101: return begin2 (); Chris@101: } Chris@101: BOOST_UBLAS_INLINE Chris@16: const_iterator2 end2 () const { Chris@16: return find2 (0, 0, size2_); Chris@16: } Chris@101: BOOST_UBLAS_INLINE Chris@101: const_iterator2 cend2 () const { Chris@101: return end2 (); Chris@101: } Chris@16: Chris@16: class iterator2: Chris@16: public container_reference, Chris@16: public bidirectional_iterator_base { Chris@16: public: Chris@16: typedef typename mapped_vector_of_mapped_vector::value_type value_type; Chris@16: typedef typename mapped_vector_of_mapped_vector::difference_type difference_type; Chris@16: typedef typename mapped_vector_of_mapped_vector::true_reference reference; Chris@16: typedef typename mapped_vector_of_mapped_vector::pointer pointer; Chris@16: Chris@16: typedef iterator1 dual_iterator_type; Chris@16: typedef reverse_iterator1 dual_reverse_iterator_type; Chris@16: Chris@16: // Construction and destruction Chris@16: BOOST_UBLAS_INLINE Chris@16: iterator2 (): Chris@16: container_reference (), rank_ (), i_ (), j_ (), itv_ (), it_ () {} Chris@16: BOOST_UBLAS_INLINE Chris@16: iterator2 (self_type &m, int rank, size_type i, size_type j, const vector_subiterator_type &itv, const subiterator_type &it): Chris@16: container_reference (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {} Chris@16: Chris@16: // Arithmetic Chris@16: BOOST_UBLAS_INLINE Chris@16: iterator2 &operator ++ () { Chris@16: if (rank_ == 1 && layout_type::fast_j ()) Chris@16: ++ it_; Chris@16: else { Chris@16: self_type &m = (*this) (); Chris@16: if (rank_ == 0) { Chris@16: ++ itv_; Chris@16: j_ = itv_->first; Chris@16: } else { Chris@16: j_ = index2 () + 1; Chris@16: } Chris@16: if (rank_ == 1 && ++ itv_ == m.end2 ().itv_) Chris@16: *this = m.find2 (rank_, i_, j_, 1); Chris@16: else if (rank_ == 1) { Chris@16: it_ = (*itv_).second.begin (); Chris@16: if (it_ == (*itv_).second.end () || index1 () != i_) Chris@16: *this = m.find2 (rank_, i_, j_, 1); Chris@16: } Chris@16: } Chris@16: return *this; Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: iterator2 &operator -- () { Chris@16: if (rank_ == 1 && layout_type::fast_j ()) Chris@16: -- it_; Chris@16: else { Chris@16: self_type &m = (*this) (); Chris@16: if (rank_ == 0) { Chris@16: -- itv_; Chris@16: j_ = itv_->first; Chris@16: } else { Chris@16: j_ = index2 () - 1; Chris@16: } Chris@16: // FIXME: this expression should never become true! Chris@16: if (rank_ == 1 && -- itv_ == m.end2 ().itv_) Chris@16: *this = m.find2 (rank_, i_, j_, -1); Chris@16: else if (rank_ == 1) { Chris@16: it_ = (*itv_).second.begin (); Chris@16: if (it_ == (*itv_).second.end () || index1 () != i_) Chris@16: *this = m.find2 (rank_, i_, j_, -1); Chris@16: } Chris@16: } Chris@16: return *this; Chris@16: } Chris@16: Chris@16: // Dereference Chris@16: BOOST_UBLAS_INLINE Chris@16: reference operator * () const { Chris@16: BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ()); Chris@16: BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ()); Chris@16: if (rank_ == 1) { Chris@16: return (*it_).second; Chris@16: } else { Chris@16: return (*this) ().at_element (i_, j_); Chris@16: } Chris@16: } Chris@16: Chris@16: #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION Chris@16: BOOST_UBLAS_INLINE Chris@16: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@16: typename self_type:: Chris@16: #endif Chris@16: iterator1 begin () const { Chris@16: self_type &m = (*this) (); Chris@16: return m.find1 (1, 0, index2 ()); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@16: typename self_type:: Chris@16: #endif Chris@16: iterator1 end () const { Chris@16: self_type &m = (*this) (); Chris@16: return m.find1 (1, m.size1 (), index2 ()); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@16: typename self_type:: Chris@16: #endif Chris@16: reverse_iterator1 rbegin () const { Chris@16: return reverse_iterator1 (end ()); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@16: typename self_type:: Chris@16: #endif Chris@16: reverse_iterator1 rend () const { Chris@16: return reverse_iterator1 (begin ()); Chris@16: } Chris@16: #endif Chris@16: Chris@16: // Indices Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type index1 () const { Chris@16: if (rank_ == 1) { Chris@16: BOOST_UBLAS_CHECK (layout_type::index_M ((*itv_).first, (*it_).first) < (*this) ().size1 (), bad_index ()); Chris@16: return layout_type::index_M ((*itv_).first, (*it_).first); Chris@16: } else { Chris@16: return i_; Chris@16: } Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type index2 () const { Chris@16: BOOST_UBLAS_CHECK (*this != (*this) ().find2 (0, i_, (*this) ().size2 ()), bad_index ()); Chris@16: if (rank_ == 1) { Chris@16: BOOST_UBLAS_CHECK (layout_type::index_m ((*itv_).first, (*it_).first) < (*this) ().size2 (), bad_index ()); Chris@16: return layout_type::index_m ((*itv_).first, (*it_).first); Chris@16: } else { Chris@16: return j_; Chris@16: } Chris@16: } Chris@16: Chris@16: // Assignment Chris@16: BOOST_UBLAS_INLINE Chris@16: iterator2 &operator = (const iterator2 &it) { Chris@16: container_reference::assign (&it ()); Chris@16: rank_ = it.rank_; Chris@16: i_ = it.i_; Chris@16: j_ = it.j_; Chris@16: itv_ = it.itv_; Chris@16: it_ = it.it_; Chris@16: return *this; Chris@16: } Chris@16: Chris@16: // Comparison Chris@16: BOOST_UBLAS_INLINE Chris@16: bool operator == (const iterator2 &it) const { Chris@16: BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); Chris@16: // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ()); Chris@16: if (rank_ == 1 || it.rank_ == 1) { Chris@16: return it_ == it.it_; Chris@16: } else { Chris@16: return i_ == it.i_ && j_ == it.j_; Chris@16: } Chris@16: } Chris@16: Chris@16: private: Chris@16: int rank_; Chris@16: size_type i_; Chris@16: size_type j_; Chris@16: vector_subiterator_type itv_; Chris@16: subiterator_type it_; Chris@16: Chris@16: friend class const_iterator2; Chris@16: }; Chris@16: Chris@16: BOOST_UBLAS_INLINE Chris@16: iterator2 begin2 () { Chris@16: return find2 (0, 0, 0); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: iterator2 end2 () { Chris@16: return find2 (0, 0, size2_); Chris@16: } Chris@16: Chris@16: // Reverse iterators Chris@16: Chris@16: BOOST_UBLAS_INLINE Chris@16: const_reverse_iterator1 rbegin1 () const { Chris@16: return const_reverse_iterator1 (end1 ()); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@101: const_reverse_iterator1 crbegin1 () const { Chris@101: return rbegin1 (); Chris@101: } Chris@101: BOOST_UBLAS_INLINE Chris@16: const_reverse_iterator1 rend1 () const { Chris@16: return const_reverse_iterator1 (begin1 ()); Chris@16: } Chris@101: BOOST_UBLAS_INLINE Chris@101: const_reverse_iterator1 crend1 () const { Chris@101: return rend1 (); Chris@101: } Chris@16: Chris@16: BOOST_UBLAS_INLINE Chris@16: reverse_iterator1 rbegin1 () { Chris@16: return reverse_iterator1 (end1 ()); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: reverse_iterator1 rend1 () { Chris@16: return reverse_iterator1 (begin1 ()); Chris@16: } Chris@16: Chris@16: BOOST_UBLAS_INLINE Chris@16: const_reverse_iterator2 rbegin2 () const { Chris@16: return const_reverse_iterator2 (end2 ()); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@101: const_reverse_iterator2 crbegin2 () const { Chris@101: return rbegin2 (); Chris@101: } Chris@101: BOOST_UBLAS_INLINE Chris@16: const_reverse_iterator2 rend2 () const { Chris@16: return const_reverse_iterator2 (begin2 ()); Chris@16: } Chris@101: BOOST_UBLAS_INLINE Chris@101: const_reverse_iterator2 crend2 () const { Chris@101: return rend2 (); Chris@101: } Chris@16: Chris@16: BOOST_UBLAS_INLINE Chris@16: reverse_iterator2 rbegin2 () { Chris@16: return reverse_iterator2 (end2 ()); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: reverse_iterator2 rend2 () { Chris@16: return reverse_iterator2 (begin2 ()); Chris@16: } Chris@16: Chris@16: // Serialization Chris@16: template Chris@16: void serialize(Archive & ar, const unsigned int /* file_version */){ Chris@16: serialization::collection_size_type s1 (size1_); Chris@16: serialization::collection_size_type s2 (size2_); Chris@16: ar & serialization::make_nvp("size1",s1); Chris@16: ar & serialization::make_nvp("size2",s2); Chris@16: if (Archive::is_loading::value) { Chris@16: size1_ = s1; Chris@16: size2_ = s2; Chris@16: } Chris@16: ar & serialization::make_nvp("data", data_); Chris@16: } Chris@16: Chris@16: private: Chris@16: size_type size1_; Chris@16: size_type size2_; Chris@16: array_type data_; Chris@16: static const value_type zero_; Chris@16: }; Chris@16: Chris@16: template Chris@16: const typename mapped_vector_of_mapped_vector::value_type mapped_vector_of_mapped_vector::zero_ = value_type/*zero*/(); Chris@16: Chris@16: Chris@16: // Comperssed array based sparse matrix class Chris@16: // Thanks to Kresimir Fresl for extending this to cover different index bases. Chris@16: template Chris@16: class compressed_matrix: Chris@16: public matrix_container > { Chris@16: Chris@16: typedef T &true_reference; Chris@16: typedef T *pointer; Chris@16: typedef const T *const_pointer; Chris@16: typedef L layout_type; Chris@16: typedef compressed_matrix self_type; Chris@16: public: Chris@16: #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS Chris@16: using matrix_container::operator (); Chris@16: #endif Chris@16: // ISSUE require type consistency check Chris@16: // is_convertable (IA::size_type, TA::size_type) Chris@16: typedef typename IA::value_type size_type; Chris@16: // size_type for the data arrays. Chris@16: typedef typename IA::size_type array_size_type; Chris@16: // FIXME difference type for sparse storage iterators should it be in the container? Chris@16: typedef typename IA::difference_type difference_type; Chris@16: typedef T value_type; Chris@16: typedef const T &const_reference; Chris@16: #ifndef BOOST_UBLAS_STRICT_MATRIX_SPARSE Chris@16: typedef T &reference; Chris@16: #else Chris@16: typedef sparse_matrix_element reference; Chris@16: #endif Chris@16: typedef IA index_array_type; Chris@16: typedef TA value_array_type; Chris@16: typedef const matrix_reference const_closure_type; Chris@16: typedef matrix_reference closure_type; Chris@16: typedef compressed_vector vector_temporary_type; Chris@16: typedef self_type matrix_temporary_type; Chris@16: typedef sparse_tag storage_category; Chris@16: typedef typename L::orientation_category orientation_category; Chris@16: Chris@16: // Construction and destruction Chris@16: BOOST_UBLAS_INLINE Chris@16: compressed_matrix (): Chris@16: matrix_container (), Chris@16: size1_ (0), size2_ (0), capacity_ (restrict_capacity (0)), Chris@16: filled1_ (1), filled2_ (0), Chris@16: index1_data_ (layout_type::size_M (size1_, size2_) + 1), index2_data_ (capacity_), value_data_ (capacity_) { Chris@16: index1_data_ [filled1_ - 1] = k_based (filled2_); Chris@16: storage_invariants (); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: compressed_matrix (size_type size1, size_type size2, size_type non_zeros = 0): Chris@16: matrix_container (), Chris@16: size1_ (size1), size2_ (size2), capacity_ (restrict_capacity (non_zeros)), Chris@16: filled1_ (1), filled2_ (0), Chris@16: index1_data_ (layout_type::size_M (size1_, size2_) + 1), index2_data_ (capacity_), value_data_ (capacity_) { Chris@16: index1_data_ [filled1_ - 1] = k_based (filled2_); Chris@16: storage_invariants (); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: compressed_matrix (const compressed_matrix &m): Chris@16: matrix_container (), Chris@16: size1_ (m.size1_), size2_ (m.size2_), capacity_ (m.capacity_), Chris@16: filled1_ (m.filled1_), filled2_ (m.filled2_), Chris@16: index1_data_ (m.index1_data_), index2_data_ (m.index2_data_), value_data_ (m.value_data_) { Chris@16: storage_invariants (); Chris@16: } Chris@16: Chris@16: BOOST_UBLAS_INLINE Chris@16: compressed_matrix (const coordinate_matrix &m): Chris@16: matrix_container (), Chris@16: size1_ (m.size1()), size2_ (m.size2()), Chris@16: index1_data_ (layout_type::size_M (size1_, size2_) + 1) Chris@16: { Chris@16: m.sort(); Chris@16: reserve(m.nnz(), false); Chris@16: filled2_ = m.nnz(); Chris@16: const_subiterator_type i_start = m.index1_data().begin(); Chris@16: const_subiterator_type i_end = (i_start + filled2_); Chris@16: const_subiterator_type i = i_start; Chris@16: size_type r = 1; Chris@16: for (; (r < layout_type::size_M (size1_, size2_)) && (i != i_end); ++r) { Chris@16: i = std::lower_bound(i, i_end, r); Chris@16: index1_data_[r] = k_based( i - i_start ); Chris@16: } Chris@16: filled1_ = r + 1; Chris@16: std::copy( m.index2_data().begin(), m.index2_data().begin() + filled2_, index2_data_.begin()); Chris@16: std::copy( m.value_data().begin(), m.value_data().begin() + filled2_, value_data_.begin()); Chris@16: index1_data_ [filled1_ - 1] = k_based(filled2_); Chris@16: storage_invariants (); Chris@16: } Chris@16: Chris@16: template Chris@16: BOOST_UBLAS_INLINE Chris@16: compressed_matrix (const matrix_expression &ae, size_type non_zeros = 0): Chris@16: matrix_container (), Chris@16: size1_ (ae ().size1 ()), size2_ (ae ().size2 ()), capacity_ (restrict_capacity (non_zeros)), Chris@16: filled1_ (1), filled2_ (0), Chris@16: index1_data_ (layout_type::size_M (ae ().size1 (), ae ().size2 ()) + 1), Chris@16: index2_data_ (capacity_), value_data_ (capacity_) { Chris@16: index1_data_ [filled1_ - 1] = k_based (filled2_); Chris@16: storage_invariants (); Chris@16: matrix_assign (*this, ae); Chris@16: } Chris@16: Chris@16: // Accessors Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type size1 () const { Chris@16: return size1_; Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type size2 () const { Chris@16: return size2_; Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type nnz_capacity () const { Chris@16: return capacity_; Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type nnz () const { Chris@16: return filled2_; Chris@16: } Chris@16: Chris@16: // Storage accessors Chris@16: BOOST_UBLAS_INLINE Chris@16: static size_type index_base () { Chris@16: return IB; Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: array_size_type filled1 () const { Chris@16: return filled1_; Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: array_size_type filled2 () const { Chris@16: return filled2_; Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: const index_array_type &index1_data () const { Chris@16: return index1_data_; Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: const index_array_type &index2_data () const { Chris@16: return index2_data_; Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: const value_array_type &value_data () const { Chris@16: return value_data_; Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: void set_filled (const array_size_type& filled1, const array_size_type& filled2) { Chris@16: filled1_ = filled1; Chris@16: filled2_ = filled2; Chris@16: storage_invariants (); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: index_array_type &index1_data () { Chris@16: return index1_data_; Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: index_array_type &index2_data () { Chris@16: return index2_data_; Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: value_array_type &value_data () { Chris@16: return value_data_; Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: void complete_index1_data () { Chris@16: while (filled1_ <= layout_type::size_M (size1_, size2_)) { Chris@16: this->index1_data_ [filled1_] = k_based (filled2_); Chris@16: ++ this->filled1_; Chris@16: } Chris@16: } Chris@16: Chris@16: // Resizing Chris@16: private: Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type restrict_capacity (size_type non_zeros) const { Chris@16: non_zeros = (std::max) (non_zeros, (std::min) (size1_, size2_)); Chris@16: // Guarding against overflow - Thanks to Alexei Novakov for the hint. Chris@16: // non_zeros = (std::min) (non_zeros, size1_ * size2_); Chris@16: if (size1_ > 0 && non_zeros / size1_ >= size2_) Chris@16: non_zeros = size1_ * size2_; Chris@16: return non_zeros; Chris@16: } Chris@16: public: Chris@16: BOOST_UBLAS_INLINE Chris@16: void resize (size_type size1, size_type size2, bool preserve = true) { Chris@16: // FIXME preserve unimplemented Chris@16: BOOST_UBLAS_CHECK (!preserve, internal_logic ()); Chris@16: size1_ = size1; Chris@16: size2_ = size2; Chris@16: capacity_ = restrict_capacity (capacity_); Chris@16: filled1_ = 1; Chris@16: filled2_ = 0; Chris@16: index1_data_.resize (layout_type::size_M (size1_, size2_) + 1); Chris@16: index2_data_.resize (capacity_); Chris@16: value_data_.resize (capacity_); Chris@16: index1_data_ [filled1_ - 1] = k_based (filled2_); Chris@16: storage_invariants (); Chris@16: } Chris@16: Chris@16: // Reserving Chris@16: BOOST_UBLAS_INLINE Chris@16: void reserve (size_type non_zeros, bool preserve = true) { Chris@16: capacity_ = restrict_capacity (non_zeros); Chris@16: if (preserve) { Chris@16: index2_data_.resize (capacity_, size_type ()); Chris@16: value_data_.resize (capacity_, value_type ()); Chris@16: filled2_ = (std::min) (capacity_, filled2_); Chris@16: } Chris@16: else { Chris@16: index2_data_.resize (capacity_); Chris@16: value_data_.resize (capacity_); Chris@16: filled1_ = 1; Chris@16: filled2_ = 0; Chris@16: index1_data_ [filled1_ - 1] = k_based (filled2_); Chris@16: } Chris@16: storage_invariants (); Chris@16: } Chris@16: Chris@16: // Element support Chris@16: BOOST_UBLAS_INLINE Chris@16: pointer find_element (size_type i, size_type j) { Chris@16: return const_cast (const_cast(*this).find_element (i, j)); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: const_pointer find_element (size_type i, size_type j) const { Chris@16: size_type element1 (layout_type::index_M (i, j)); Chris@16: size_type element2 (layout_type::index_m (i, j)); Chris@16: if (filled1_ <= element1 + 1) Chris@16: return 0; Chris@16: vector_const_subiterator_type itv (index1_data_.begin () + element1); Chris@16: const_subiterator_type it_begin (index2_data_.begin () + zero_based (*itv)); Chris@16: const_subiterator_type it_end (index2_data_.begin () + zero_based (*(itv + 1))); Chris@16: const_subiterator_type it (detail::lower_bound (it_begin, it_end, k_based (element2), std::less ())); Chris@16: if (it == it_end || *it != k_based (element2)) Chris@16: return 0; Chris@16: return &value_data_ [it - index2_data_.begin ()]; Chris@16: } Chris@16: Chris@16: // Element access Chris@16: BOOST_UBLAS_INLINE Chris@16: const_reference operator () (size_type i, size_type j) const { Chris@16: const_pointer p = find_element (i, j); Chris@16: if (p) Chris@16: return *p; Chris@16: else Chris@16: return zero_; Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: reference operator () (size_type i, size_type j) { Chris@16: #ifndef BOOST_UBLAS_STRICT_MATRIX_SPARSE Chris@16: size_type element1 (layout_type::index_M (i, j)); Chris@16: size_type element2 (layout_type::index_m (i, j)); Chris@16: if (filled1_ <= element1 + 1) Chris@16: return insert_element (i, j, value_type/*zero*/()); Chris@16: pointer p = find_element (i, j); Chris@16: if (p) Chris@16: return *p; Chris@16: else Chris@16: return insert_element (i, j, value_type/*zero*/()); Chris@16: #else Chris@16: return reference (*this, i, j); Chris@16: #endif Chris@16: } Chris@16: Chris@16: // Element assignment Chris@16: BOOST_UBLAS_INLINE Chris@16: true_reference insert_element (size_type i, size_type j, const_reference t) { Chris@16: BOOST_UBLAS_CHECK (!find_element (i, j), bad_index ()); // duplicate element Chris@16: if (filled2_ >= capacity_) Chris@16: reserve (2 * filled2_, true); Chris@16: BOOST_UBLAS_CHECK (filled2_ < capacity_, internal_logic ()); Chris@16: size_type element1 = layout_type::index_M (i, j); Chris@16: size_type element2 = layout_type::index_m (i, j); Chris@16: while (filled1_ <= element1 + 1) { Chris@16: index1_data_ [filled1_] = k_based (filled2_); Chris@16: ++ filled1_; Chris@16: } Chris@16: vector_subiterator_type itv (index1_data_.begin () + element1); Chris@16: subiterator_type it_begin (index2_data_.begin () + zero_based (*itv)); Chris@16: subiterator_type it_end (index2_data_.begin () + zero_based (*(itv + 1))); Chris@16: subiterator_type it (detail::lower_bound (it_begin, it_end, k_based (element2), std::less ())); Chris@16: typename std::iterator_traits::difference_type n = it - index2_data_.begin (); Chris@16: BOOST_UBLAS_CHECK (it == it_end || *it != k_based (element2), internal_logic ()); // duplicate bound by lower_bound Chris@16: ++ filled2_; Chris@16: it = index2_data_.begin () + n; Chris@16: std::copy_backward (it, index2_data_.begin () + filled2_ - 1, index2_data_.begin () + filled2_); Chris@16: *it = k_based (element2); Chris@16: typename value_array_type::iterator itt (value_data_.begin () + n); Chris@16: std::copy_backward (itt, value_data_.begin () + filled2_ - 1, value_data_.begin () + filled2_); Chris@16: *itt = t; Chris@16: while (element1 + 1 < filled1_) { Chris@16: ++ index1_data_ [element1 + 1]; Chris@16: ++ element1; Chris@16: } Chris@16: storage_invariants (); Chris@16: return *itt; Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: void erase_element (size_type i, size_type j) { Chris@16: size_type element1 = layout_type::index_M (i, j); Chris@16: size_type element2 = layout_type::index_m (i, j); Chris@16: if (element1 + 1 >= filled1_) Chris@16: return; Chris@16: vector_subiterator_type itv (index1_data_.begin () + element1); Chris@16: subiterator_type it_begin (index2_data_.begin () + zero_based (*itv)); Chris@16: subiterator_type it_end (index2_data_.begin () + zero_based (*(itv + 1))); Chris@16: subiterator_type it (detail::lower_bound (it_begin, it_end, k_based (element2), std::less ())); Chris@16: if (it != it_end && *it == k_based (element2)) { Chris@16: typename std::iterator_traits::difference_type n = it - index2_data_.begin (); Chris@16: std::copy (it + 1, index2_data_.begin () + filled2_, it); Chris@16: typename value_array_type::iterator itt (value_data_.begin () + n); Chris@16: std::copy (itt + 1, value_data_.begin () + filled2_, itt); Chris@16: -- filled2_; Chris@16: while (index1_data_ [filled1_ - 2] > k_based (filled2_)) { Chris@16: index1_data_ [filled1_ - 1] = 0; Chris@16: -- filled1_; Chris@16: } Chris@16: while (element1 + 1 < filled1_) { Chris@16: -- index1_data_ [element1 + 1]; Chris@16: ++ element1; Chris@16: } Chris@16: } Chris@16: storage_invariants (); Chris@16: } Chris@16: Chris@16: // Zeroing Chris@16: BOOST_UBLAS_INLINE Chris@16: void clear () { Chris@16: filled1_ = 1; Chris@16: filled2_ = 0; Chris@16: index1_data_ [filled1_ - 1] = k_based (filled2_); Chris@16: storage_invariants (); Chris@16: } Chris@16: Chris@16: // Assignment Chris@16: BOOST_UBLAS_INLINE Chris@16: compressed_matrix &operator = (const compressed_matrix &m) { Chris@16: if (this != &m) { Chris@16: size1_ = m.size1_; Chris@16: size2_ = m.size2_; Chris@16: capacity_ = m.capacity_; Chris@16: filled1_ = m.filled1_; Chris@16: filled2_ = m.filled2_; Chris@16: index1_data_ = m.index1_data_; Chris@16: index2_data_ = m.index2_data_; Chris@16: value_data_ = m.value_data_; Chris@16: } Chris@16: storage_invariants (); Chris@16: return *this; Chris@16: } Chris@16: template // Container assignment without temporary Chris@16: BOOST_UBLAS_INLINE Chris@16: compressed_matrix &operator = (const matrix_container &m) { Chris@16: resize (m ().size1 (), m ().size2 (), false); Chris@16: assign (m); Chris@16: return *this; Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: compressed_matrix &assign_temporary (compressed_matrix &m) { Chris@16: swap (m); Chris@16: return *this; Chris@16: } Chris@16: template Chris@16: BOOST_UBLAS_INLINE Chris@16: compressed_matrix &operator = (const matrix_expression &ae) { Chris@16: self_type temporary (ae, capacity_); Chris@16: return assign_temporary (temporary); Chris@16: } Chris@16: template Chris@16: BOOST_UBLAS_INLINE Chris@16: compressed_matrix &assign (const matrix_expression &ae) { Chris@16: matrix_assign (*this, ae); Chris@16: return *this; Chris@16: } Chris@16: template Chris@16: BOOST_UBLAS_INLINE Chris@16: compressed_matrix& operator += (const matrix_expression &ae) { Chris@16: self_type temporary (*this + ae, capacity_); Chris@16: return assign_temporary (temporary); Chris@16: } Chris@16: template // Container assignment without temporary Chris@16: BOOST_UBLAS_INLINE Chris@16: compressed_matrix &operator += (const matrix_container &m) { Chris@16: plus_assign (m); Chris@16: return *this; Chris@16: } Chris@16: template Chris@16: BOOST_UBLAS_INLINE Chris@16: compressed_matrix &plus_assign (const matrix_expression &ae) { Chris@16: matrix_assign (*this, ae); Chris@16: return *this; Chris@16: } Chris@16: template Chris@16: BOOST_UBLAS_INLINE Chris@16: compressed_matrix& operator -= (const matrix_expression &ae) { Chris@16: self_type temporary (*this - ae, capacity_); Chris@16: return assign_temporary (temporary); Chris@16: } Chris@16: template // Container assignment without temporary Chris@16: BOOST_UBLAS_INLINE Chris@16: compressed_matrix &operator -= (const matrix_container &m) { Chris@16: minus_assign (m); Chris@16: return *this; Chris@16: } Chris@16: template Chris@16: BOOST_UBLAS_INLINE Chris@16: compressed_matrix &minus_assign (const matrix_expression &ae) { Chris@16: matrix_assign (*this, ae); Chris@16: return *this; Chris@16: } Chris@16: template Chris@16: BOOST_UBLAS_INLINE Chris@16: compressed_matrix& operator *= (const AT &at) { Chris@16: matrix_assign_scalar (*this, at); Chris@16: return *this; Chris@16: } Chris@16: template Chris@16: BOOST_UBLAS_INLINE Chris@16: compressed_matrix& operator /= (const AT &at) { Chris@16: matrix_assign_scalar (*this, at); Chris@16: return *this; Chris@16: } Chris@16: Chris@16: // Swapping Chris@16: BOOST_UBLAS_INLINE Chris@16: void swap (compressed_matrix &m) { Chris@16: if (this != &m) { Chris@16: std::swap (size1_, m.size1_); Chris@16: std::swap (size2_, m.size2_); Chris@16: std::swap (capacity_, m.capacity_); Chris@16: std::swap (filled1_, m.filled1_); Chris@16: std::swap (filled2_, m.filled2_); Chris@16: index1_data_.swap (m.index1_data_); Chris@16: index2_data_.swap (m.index2_data_); Chris@16: value_data_.swap (m.value_data_); Chris@16: } Chris@16: storage_invariants (); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: friend void swap (compressed_matrix &m1, compressed_matrix &m2) { Chris@16: m1.swap (m2); Chris@16: } Chris@16: Chris@16: // Back element insertion and erasure Chris@16: BOOST_UBLAS_INLINE Chris@16: void push_back (size_type i, size_type j, const_reference t) { Chris@16: if (filled2_ >= capacity_) Chris@16: reserve (2 * filled2_, true); Chris@16: BOOST_UBLAS_CHECK (filled2_ < capacity_, internal_logic ()); Chris@16: size_type element1 = layout_type::index_M (i, j); Chris@16: size_type element2 = layout_type::index_m (i, j); Chris@16: while (filled1_ < element1 + 2) { Chris@16: index1_data_ [filled1_] = k_based (filled2_); Chris@16: ++ filled1_; Chris@16: } Chris@16: // must maintain sort order Chris@16: BOOST_UBLAS_CHECK ((filled1_ == element1 + 2 && Chris@16: (filled2_ == zero_based (index1_data_ [filled1_ - 2]) || Chris@16: index2_data_ [filled2_ - 1] < k_based (element2))), external_logic ()); Chris@16: ++ filled2_; Chris@16: index1_data_ [filled1_ - 1] = k_based (filled2_); Chris@16: index2_data_ [filled2_ - 1] = k_based (element2); Chris@16: value_data_ [filled2_ - 1] = t; Chris@16: storage_invariants (); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: void pop_back () { Chris@16: BOOST_UBLAS_CHECK (filled1_ > 0 && filled2_ > 0, external_logic ()); Chris@16: -- filled2_; Chris@16: while (index1_data_ [filled1_ - 2] > k_based (filled2_)) { Chris@16: index1_data_ [filled1_ - 1] = 0; Chris@16: -- filled1_; Chris@16: } Chris@16: -- index1_data_ [filled1_ - 1]; Chris@16: storage_invariants (); Chris@16: } Chris@16: Chris@16: // Iterator types Chris@16: private: Chris@16: // Use index array iterator Chris@16: typedef typename IA::const_iterator vector_const_subiterator_type; Chris@16: typedef typename IA::iterator vector_subiterator_type; Chris@16: typedef typename IA::const_iterator const_subiterator_type; Chris@16: typedef typename IA::iterator subiterator_type; Chris@16: Chris@16: BOOST_UBLAS_INLINE Chris@16: true_reference at_element (size_type i, size_type j) { Chris@16: pointer p = find_element (i, j); Chris@16: BOOST_UBLAS_CHECK (p, bad_index ()); Chris@16: return *p; Chris@16: } Chris@16: Chris@16: public: Chris@16: class const_iterator1; Chris@16: class iterator1; Chris@16: class const_iterator2; Chris@16: class iterator2; Chris@16: typedef reverse_iterator_base1 const_reverse_iterator1; Chris@16: typedef reverse_iterator_base1 reverse_iterator1; Chris@16: typedef reverse_iterator_base2 const_reverse_iterator2; Chris@16: typedef reverse_iterator_base2 reverse_iterator2; Chris@16: Chris@16: // Element lookup Chris@16: // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it. Chris@16: const_iterator1 find1 (int rank, size_type i, size_type j, int direction = 1) const { Chris@16: for (;;) { Chris@16: array_size_type address1 (layout_type::index_M (i, j)); Chris@16: array_size_type address2 (layout_type::index_m (i, j)); Chris@16: vector_const_subiterator_type itv (index1_data_.begin () + (std::min) (filled1_ - 1, address1)); Chris@16: if (filled1_ <= address1 + 1) Chris@16: return const_iterator1 (*this, rank, i, j, itv, index2_data_.begin () + filled2_); Chris@16: Chris@16: const_subiterator_type it_begin (index2_data_.begin () + zero_based (*itv)); Chris@16: const_subiterator_type it_end (index2_data_.begin () + zero_based (*(itv + 1))); Chris@16: Chris@16: const_subiterator_type it (detail::lower_bound (it_begin, it_end, k_based (address2), std::less ())); Chris@16: if (rank == 0) Chris@16: return const_iterator1 (*this, rank, i, j, itv, it); Chris@16: if (it != it_end && zero_based (*it) == address2) Chris@16: return const_iterator1 (*this, rank, i, j, itv, it); Chris@16: if (direction > 0) { Chris@16: if (layout_type::fast_i ()) { Chris@16: if (it == it_end) Chris@16: return const_iterator1 (*this, rank, i, j, itv, it); Chris@16: i = zero_based (*it); Chris@16: } else { Chris@16: if (i >= size1_) Chris@16: return const_iterator1 (*this, rank, i, j, itv, it); Chris@16: ++ i; Chris@16: } Chris@16: } else /* if (direction < 0) */ { Chris@16: if (layout_type::fast_i ()) { Chris@16: if (it == index2_data_.begin () + zero_based (*itv)) Chris@16: return const_iterator1 (*this, rank, i, j, itv, it); Chris@16: i = zero_based (*(it - 1)); Chris@16: } else { Chris@16: if (i == 0) Chris@16: return const_iterator1 (*this, rank, i, j, itv, it); Chris@16: -- i; Chris@16: } Chris@16: } Chris@16: } Chris@16: } Chris@16: // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it. Chris@16: iterator1 find1 (int rank, size_type i, size_type j, int direction = 1) { Chris@16: for (;;) { Chris@16: array_size_type address1 (layout_type::index_M (i, j)); Chris@16: array_size_type address2 (layout_type::index_m (i, j)); Chris@16: vector_subiterator_type itv (index1_data_.begin () + (std::min) (filled1_ - 1, address1)); Chris@16: if (filled1_ <= address1 + 1) Chris@16: return iterator1 (*this, rank, i, j, itv, index2_data_.begin () + filled2_); Chris@16: Chris@16: subiterator_type it_begin (index2_data_.begin () + zero_based (*itv)); Chris@16: subiterator_type it_end (index2_data_.begin () + zero_based (*(itv + 1))); Chris@16: Chris@16: subiterator_type it (detail::lower_bound (it_begin, it_end, k_based (address2), std::less ())); Chris@16: if (rank == 0) Chris@16: return iterator1 (*this, rank, i, j, itv, it); Chris@16: if (it != it_end && zero_based (*it) == address2) Chris@16: return iterator1 (*this, rank, i, j, itv, it); Chris@16: if (direction > 0) { Chris@16: if (layout_type::fast_i ()) { Chris@16: if (it == it_end) Chris@16: return iterator1 (*this, rank, i, j, itv, it); Chris@16: i = zero_based (*it); Chris@16: } else { Chris@16: if (i >= size1_) Chris@16: return iterator1 (*this, rank, i, j, itv, it); Chris@16: ++ i; Chris@16: } Chris@16: } else /* if (direction < 0) */ { Chris@16: if (layout_type::fast_i ()) { Chris@16: if (it == index2_data_.begin () + zero_based (*itv)) Chris@16: return iterator1 (*this, rank, i, j, itv, it); Chris@16: i = zero_based (*(it - 1)); Chris@16: } else { Chris@16: if (i == 0) Chris@16: return iterator1 (*this, rank, i, j, itv, it); Chris@16: -- i; Chris@16: } Chris@16: } Chris@16: } Chris@16: } Chris@16: // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it. Chris@16: const_iterator2 find2 (int rank, size_type i, size_type j, int direction = 1) const { Chris@16: for (;;) { Chris@16: array_size_type address1 (layout_type::index_M (i, j)); Chris@16: array_size_type address2 (layout_type::index_m (i, j)); Chris@16: vector_const_subiterator_type itv (index1_data_.begin () + (std::min) (filled1_ - 1, address1)); Chris@16: if (filled1_ <= address1 + 1) Chris@16: return const_iterator2 (*this, rank, i, j, itv, index2_data_.begin () + filled2_); Chris@16: Chris@16: const_subiterator_type it_begin (index2_data_.begin () + zero_based (*itv)); Chris@16: const_subiterator_type it_end (index2_data_.begin () + zero_based (*(itv + 1))); Chris@16: Chris@16: const_subiterator_type it (detail::lower_bound (it_begin, it_end, k_based (address2), std::less ())); Chris@16: if (rank == 0) Chris@16: return const_iterator2 (*this, rank, i, j, itv, it); Chris@16: if (it != it_end && zero_based (*it) == address2) Chris@16: return const_iterator2 (*this, rank, i, j, itv, it); Chris@16: if (direction > 0) { Chris@16: if (layout_type::fast_j ()) { Chris@16: if (it == it_end) Chris@16: return const_iterator2 (*this, rank, i, j, itv, it); Chris@16: j = zero_based (*it); Chris@16: } else { Chris@16: if (j >= size2_) Chris@16: return const_iterator2 (*this, rank, i, j, itv, it); Chris@16: ++ j; Chris@16: } Chris@16: } else /* if (direction < 0) */ { Chris@16: if (layout_type::fast_j ()) { Chris@16: if (it == index2_data_.begin () + zero_based (*itv)) Chris@16: return const_iterator2 (*this, rank, i, j, itv, it); Chris@16: j = zero_based (*(it - 1)); Chris@16: } else { Chris@16: if (j == 0) Chris@16: return const_iterator2 (*this, rank, i, j, itv, it); Chris@16: -- j; Chris@16: } Chris@16: } Chris@16: } Chris@16: } Chris@16: // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it. Chris@16: iterator2 find2 (int rank, size_type i, size_type j, int direction = 1) { Chris@16: for (;;) { Chris@16: array_size_type address1 (layout_type::index_M (i, j)); Chris@16: array_size_type address2 (layout_type::index_m (i, j)); Chris@16: vector_subiterator_type itv (index1_data_.begin () + (std::min) (filled1_ - 1, address1)); Chris@16: if (filled1_ <= address1 + 1) Chris@16: return iterator2 (*this, rank, i, j, itv, index2_data_.begin () + filled2_); Chris@16: Chris@16: subiterator_type it_begin (index2_data_.begin () + zero_based (*itv)); Chris@16: subiterator_type it_end (index2_data_.begin () + zero_based (*(itv + 1))); Chris@16: Chris@16: subiterator_type it (detail::lower_bound (it_begin, it_end, k_based (address2), std::less ())); Chris@16: if (rank == 0) Chris@16: return iterator2 (*this, rank, i, j, itv, it); Chris@16: if (it != it_end && zero_based (*it) == address2) Chris@16: return iterator2 (*this, rank, i, j, itv, it); Chris@16: if (direction > 0) { Chris@16: if (layout_type::fast_j ()) { Chris@16: if (it == it_end) Chris@16: return iterator2 (*this, rank, i, j, itv, it); Chris@16: j = zero_based (*it); Chris@16: } else { Chris@16: if (j >= size2_) Chris@16: return iterator2 (*this, rank, i, j, itv, it); Chris@16: ++ j; Chris@16: } Chris@16: } else /* if (direction < 0) */ { Chris@16: if (layout_type::fast_j ()) { Chris@16: if (it == index2_data_.begin () + zero_based (*itv)) Chris@16: return iterator2 (*this, rank, i, j, itv, it); Chris@16: j = zero_based (*(it - 1)); Chris@16: } else { Chris@16: if (j == 0) Chris@16: return iterator2 (*this, rank, i, j, itv, it); Chris@16: -- j; Chris@16: } Chris@16: } Chris@16: } Chris@16: } Chris@16: Chris@16: Chris@16: class const_iterator1: Chris@16: public container_const_reference, Chris@16: public bidirectional_iterator_base { Chris@16: public: Chris@16: typedef typename compressed_matrix::value_type value_type; Chris@16: typedef typename compressed_matrix::difference_type difference_type; Chris@16: typedef typename compressed_matrix::const_reference reference; Chris@16: typedef const typename compressed_matrix::pointer pointer; Chris@16: Chris@16: typedef const_iterator2 dual_iterator_type; Chris@16: typedef const_reverse_iterator2 dual_reverse_iterator_type; Chris@16: Chris@16: // Construction and destruction Chris@16: BOOST_UBLAS_INLINE Chris@16: const_iterator1 (): Chris@16: container_const_reference (), rank_ (), i_ (), j_ (), itv_ (), it_ () {} Chris@16: BOOST_UBLAS_INLINE Chris@16: const_iterator1 (const self_type &m, int rank, size_type i, size_type j, const vector_const_subiterator_type &itv, const const_subiterator_type &it): Chris@16: container_const_reference (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {} Chris@16: BOOST_UBLAS_INLINE Chris@16: const_iterator1 (const iterator1 &it): Chris@16: container_const_reference (it ()), rank_ (it.rank_), i_ (it.i_), j_ (it.j_), itv_ (it.itv_), it_ (it.it_) {} Chris@16: Chris@16: // Arithmetic Chris@16: BOOST_UBLAS_INLINE Chris@16: const_iterator1 &operator ++ () { Chris@16: if (rank_ == 1 && layout_type::fast_i ()) Chris@16: ++ it_; Chris@16: else { Chris@16: i_ = index1 () + 1; Chris@16: if (rank_ == 1) Chris@16: *this = (*this) ().find1 (rank_, i_, j_, 1); Chris@16: } Chris@16: return *this; Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: const_iterator1 &operator -- () { Chris@16: if (rank_ == 1 && layout_type::fast_i ()) Chris@16: -- it_; Chris@16: else { Chris@16: --i_; Chris@16: if (rank_ == 1) Chris@16: *this = (*this) ().find1 (rank_, i_, j_, -1); Chris@16: } Chris@16: return *this; Chris@16: } Chris@16: Chris@16: // Dereference Chris@16: BOOST_UBLAS_INLINE Chris@16: const_reference operator * () const { Chris@16: BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ()); Chris@16: BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ()); Chris@16: if (rank_ == 1) { Chris@16: return (*this) ().value_data_ [it_ - (*this) ().index2_data_.begin ()]; Chris@16: } else { Chris@16: return (*this) () (i_, j_); Chris@16: } Chris@16: } Chris@16: Chris@16: #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION Chris@16: BOOST_UBLAS_INLINE Chris@16: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@16: typename self_type:: Chris@16: #endif Chris@16: const_iterator2 begin () const { Chris@16: const self_type &m = (*this) (); Chris@16: return m.find2 (1, index1 (), 0); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@16: typename self_type:: Chris@16: #endif Chris@101: const_iterator2 cbegin () const { Chris@101: return begin (); Chris@101: } Chris@101: BOOST_UBLAS_INLINE Chris@101: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@101: typename self_type:: Chris@101: #endif Chris@16: const_iterator2 end () const { Chris@16: const self_type &m = (*this) (); Chris@16: return m.find2 (1, index1 (), m.size2 ()); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@16: typename self_type:: Chris@16: #endif Chris@101: const_iterator2 cend () const { Chris@101: return end (); Chris@101: } Chris@101: BOOST_UBLAS_INLINE Chris@101: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@101: typename self_type:: Chris@101: #endif Chris@16: const_reverse_iterator2 rbegin () const { Chris@16: return const_reverse_iterator2 (end ()); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@16: typename self_type:: Chris@16: #endif Chris@101: const_reverse_iterator2 crbegin () const { Chris@101: return rbegin (); Chris@101: } Chris@101: BOOST_UBLAS_INLINE Chris@101: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@101: typename self_type:: Chris@101: #endif Chris@16: const_reverse_iterator2 rend () const { Chris@16: return const_reverse_iterator2 (begin ()); Chris@16: } Chris@101: BOOST_UBLAS_INLINE Chris@101: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@101: typename self_type:: Chris@101: #endif Chris@101: const_reverse_iterator2 crend () const { Chris@101: return rend (); Chris@101: } Chris@16: #endif Chris@16: Chris@16: // Indices Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type index1 () const { Chris@16: BOOST_UBLAS_CHECK (*this != (*this) ().find1 (0, (*this) ().size1 (), j_), bad_index ()); Chris@16: if (rank_ == 1) { Chris@16: BOOST_UBLAS_CHECK (layout_type::index_M (itv_ - (*this) ().index1_data_.begin (), (*this) ().zero_based (*it_)) < (*this) ().size1 (), bad_index ()); Chris@16: return layout_type::index_M (itv_ - (*this) ().index1_data_.begin (), (*this) ().zero_based (*it_)); Chris@16: } else { Chris@16: return i_; Chris@16: } Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type index2 () const { Chris@16: if (rank_ == 1) { Chris@16: BOOST_UBLAS_CHECK (layout_type::index_m (itv_ - (*this) ().index1_data_.begin (), (*this) ().zero_based (*it_)) < (*this) ().size2 (), bad_index ()); Chris@16: return layout_type::index_m (itv_ - (*this) ().index1_data_.begin (), (*this) ().zero_based (*it_)); Chris@16: } else { Chris@16: return j_; Chris@16: } Chris@16: } Chris@16: Chris@16: // Assignment Chris@16: BOOST_UBLAS_INLINE Chris@16: const_iterator1 &operator = (const const_iterator1 &it) { Chris@16: container_const_reference::assign (&it ()); Chris@16: rank_ = it.rank_; Chris@16: i_ = it.i_; Chris@16: j_ = it.j_; Chris@16: itv_ = it.itv_; Chris@16: it_ = it.it_; Chris@16: return *this; Chris@16: } Chris@16: Chris@16: // Comparison Chris@16: BOOST_UBLAS_INLINE Chris@16: bool operator == (const const_iterator1 &it) const { Chris@16: BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); Chris@16: // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ()); Chris@16: if (rank_ == 1 || it.rank_ == 1) { Chris@16: return it_ == it.it_; Chris@16: } else { Chris@16: return i_ == it.i_ && j_ == it.j_; Chris@16: } Chris@16: } Chris@16: Chris@16: private: Chris@16: int rank_; Chris@16: size_type i_; Chris@16: size_type j_; Chris@16: vector_const_subiterator_type itv_; Chris@16: const_subiterator_type it_; Chris@16: }; Chris@16: Chris@16: BOOST_UBLAS_INLINE Chris@16: const_iterator1 begin1 () const { Chris@16: return find1 (0, 0, 0); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@101: const_iterator1 cbegin1 () const { Chris@101: return begin1 (); Chris@101: } Chris@101: BOOST_UBLAS_INLINE Chris@16: const_iterator1 end1 () const { Chris@16: return find1 (0, size1_, 0); Chris@16: } Chris@101: BOOST_UBLAS_INLINE Chris@101: const_iterator1 cend1 () const { Chris@101: return end1 (); Chris@101: } Chris@16: Chris@16: class iterator1: Chris@16: public container_reference, Chris@16: public bidirectional_iterator_base { Chris@16: public: Chris@16: typedef typename compressed_matrix::value_type value_type; Chris@16: typedef typename compressed_matrix::difference_type difference_type; Chris@16: typedef typename compressed_matrix::true_reference reference; Chris@16: typedef typename compressed_matrix::pointer pointer; Chris@16: Chris@16: typedef iterator2 dual_iterator_type; Chris@16: typedef reverse_iterator2 dual_reverse_iterator_type; Chris@16: Chris@16: // Construction and destruction Chris@16: BOOST_UBLAS_INLINE Chris@16: iterator1 (): Chris@16: container_reference (), rank_ (), i_ (), j_ (), itv_ (), it_ () {} Chris@16: BOOST_UBLAS_INLINE Chris@16: iterator1 (self_type &m, int rank, size_type i, size_type j, const vector_subiterator_type &itv, const subiterator_type &it): Chris@16: container_reference (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {} Chris@16: Chris@16: // Arithmetic Chris@16: BOOST_UBLAS_INLINE Chris@16: iterator1 &operator ++ () { Chris@16: if (rank_ == 1 && layout_type::fast_i ()) Chris@16: ++ it_; Chris@16: else { Chris@16: i_ = index1 () + 1; Chris@16: if (rank_ == 1) Chris@16: *this = (*this) ().find1 (rank_, i_, j_, 1); Chris@16: } Chris@16: return *this; Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: iterator1 &operator -- () { Chris@16: if (rank_ == 1 && layout_type::fast_i ()) Chris@16: -- it_; Chris@16: else { Chris@16: --i_; Chris@16: if (rank_ == 1) Chris@16: *this = (*this) ().find1 (rank_, i_, j_, -1); Chris@16: } Chris@16: return *this; Chris@16: } Chris@16: Chris@16: // Dereference Chris@16: BOOST_UBLAS_INLINE Chris@16: reference operator * () const { Chris@16: BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ()); Chris@16: BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ()); Chris@16: if (rank_ == 1) { Chris@16: return (*this) ().value_data_ [it_ - (*this) ().index2_data_.begin ()]; Chris@16: } else { Chris@16: return (*this) ().at_element (i_, j_); Chris@16: } Chris@16: } Chris@16: Chris@16: #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION Chris@16: BOOST_UBLAS_INLINE Chris@16: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@16: typename self_type:: Chris@16: #endif Chris@16: iterator2 begin () const { Chris@16: self_type &m = (*this) (); Chris@16: return m.find2 (1, index1 (), 0); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@16: typename self_type:: Chris@16: #endif Chris@16: iterator2 end () const { Chris@16: self_type &m = (*this) (); Chris@16: return m.find2 (1, index1 (), m.size2 ()); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@16: typename self_type:: Chris@16: #endif Chris@16: reverse_iterator2 rbegin () const { Chris@16: return reverse_iterator2 (end ()); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@16: typename self_type:: Chris@16: #endif Chris@16: reverse_iterator2 rend () const { Chris@16: return reverse_iterator2 (begin ()); Chris@16: } Chris@16: #endif Chris@16: Chris@16: // Indices Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type index1 () const { Chris@16: BOOST_UBLAS_CHECK (*this != (*this) ().find1 (0, (*this) ().size1 (), j_), bad_index ()); Chris@16: if (rank_ == 1) { Chris@16: BOOST_UBLAS_CHECK (layout_type::index_M (itv_ - (*this) ().index1_data_.begin (), (*this) ().zero_based (*it_)) < (*this) ().size1 (), bad_index ()); Chris@16: return layout_type::index_M (itv_ - (*this) ().index1_data_.begin (), (*this) ().zero_based (*it_)); Chris@16: } else { Chris@16: return i_; Chris@16: } Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type index2 () const { Chris@16: if (rank_ == 1) { Chris@16: BOOST_UBLAS_CHECK (layout_type::index_m (itv_ - (*this) ().index1_data_.begin (), (*this) ().zero_based (*it_)) < (*this) ().size2 (), bad_index ()); Chris@16: return layout_type::index_m (itv_ - (*this) ().index1_data_.begin (), (*this) ().zero_based (*it_)); Chris@16: } else { Chris@16: return j_; Chris@16: } Chris@16: } Chris@16: Chris@16: // Assignment Chris@16: BOOST_UBLAS_INLINE Chris@16: iterator1 &operator = (const iterator1 &it) { Chris@16: container_reference::assign (&it ()); Chris@16: rank_ = it.rank_; Chris@16: i_ = it.i_; Chris@16: j_ = it.j_; Chris@16: itv_ = it.itv_; Chris@16: it_ = it.it_; Chris@16: return *this; Chris@16: } Chris@16: Chris@16: // Comparison Chris@16: BOOST_UBLAS_INLINE Chris@16: bool operator == (const iterator1 &it) const { Chris@16: BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); Chris@16: // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ()); Chris@16: if (rank_ == 1 || it.rank_ == 1) { Chris@16: return it_ == it.it_; Chris@16: } else { Chris@16: return i_ == it.i_ && j_ == it.j_; Chris@16: } Chris@16: } Chris@16: Chris@16: private: Chris@16: int rank_; Chris@16: size_type i_; Chris@16: size_type j_; Chris@16: vector_subiterator_type itv_; Chris@16: subiterator_type it_; Chris@16: Chris@16: friend class const_iterator1; Chris@16: }; Chris@16: Chris@16: BOOST_UBLAS_INLINE Chris@16: iterator1 begin1 () { Chris@16: return find1 (0, 0, 0); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: iterator1 end1 () { Chris@16: return find1 (0, size1_, 0); Chris@16: } Chris@16: Chris@16: class const_iterator2: Chris@16: public container_const_reference, Chris@16: public bidirectional_iterator_base { Chris@16: public: Chris@16: typedef typename compressed_matrix::value_type value_type; Chris@16: typedef typename compressed_matrix::difference_type difference_type; Chris@16: typedef typename compressed_matrix::const_reference reference; Chris@16: typedef const typename compressed_matrix::pointer pointer; Chris@16: Chris@16: typedef const_iterator1 dual_iterator_type; Chris@16: typedef const_reverse_iterator1 dual_reverse_iterator_type; Chris@16: Chris@16: // Construction and destruction Chris@16: BOOST_UBLAS_INLINE Chris@16: const_iterator2 (): Chris@16: container_const_reference (), rank_ (), i_ (), j_ (), itv_ (), it_ () {} Chris@16: BOOST_UBLAS_INLINE Chris@16: const_iterator2 (const self_type &m, int rank, size_type i, size_type j, const vector_const_subiterator_type itv, const const_subiterator_type &it): Chris@16: container_const_reference (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {} Chris@16: BOOST_UBLAS_INLINE Chris@16: const_iterator2 (const iterator2 &it): Chris@16: container_const_reference (it ()), rank_ (it.rank_), i_ (it.i_), j_ (it.j_), itv_ (it.itv_), it_ (it.it_) {} Chris@16: Chris@16: // Arithmetic Chris@16: BOOST_UBLAS_INLINE Chris@16: const_iterator2 &operator ++ () { Chris@16: if (rank_ == 1 && layout_type::fast_j ()) Chris@16: ++ it_; Chris@16: else { Chris@16: j_ = index2 () + 1; Chris@16: if (rank_ == 1) Chris@16: *this = (*this) ().find2 (rank_, i_, j_, 1); Chris@16: } Chris@16: return *this; Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: const_iterator2 &operator -- () { Chris@16: if (rank_ == 1 && layout_type::fast_j ()) Chris@16: -- it_; Chris@16: else { Chris@16: --j_; Chris@16: if (rank_ == 1) Chris@16: *this = (*this) ().find2 (rank_, i_, j_, -1); Chris@16: } Chris@16: return *this; Chris@16: } Chris@16: Chris@16: // Dereference Chris@16: BOOST_UBLAS_INLINE Chris@16: const_reference operator * () const { Chris@16: BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ()); Chris@16: BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ()); Chris@16: if (rank_ == 1) { Chris@16: return (*this) ().value_data_ [it_ - (*this) ().index2_data_.begin ()]; Chris@16: } else { Chris@16: return (*this) () (i_, j_); Chris@16: } Chris@16: } Chris@16: Chris@16: #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION Chris@16: BOOST_UBLAS_INLINE Chris@16: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@16: typename self_type:: Chris@16: #endif Chris@16: const_iterator1 begin () const { Chris@16: const self_type &m = (*this) (); Chris@16: return m.find1 (1, 0, index2 ()); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@16: typename self_type:: Chris@16: #endif Chris@101: const_iterator1 cbegin () const { Chris@101: return begin (); Chris@101: } Chris@101: BOOST_UBLAS_INLINE Chris@101: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@101: typename self_type:: Chris@101: #endif Chris@16: const_iterator1 end () const { Chris@16: const self_type &m = (*this) (); Chris@16: return m.find1 (1, m.size1 (), index2 ()); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@16: typename self_type:: Chris@16: #endif Chris@101: const_iterator1 cend () const { Chris@101: return end (); Chris@101: } Chris@101: BOOST_UBLAS_INLINE Chris@101: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@101: typename self_type:: Chris@101: #endif Chris@16: const_reverse_iterator1 rbegin () const { Chris@16: return const_reverse_iterator1 (end ()); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@16: typename self_type:: Chris@16: #endif Chris@101: const_reverse_iterator1 crbegin () const { Chris@101: return rbegin (); Chris@101: } Chris@101: BOOST_UBLAS_INLINE Chris@101: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@101: typename self_type:: Chris@101: #endif Chris@16: const_reverse_iterator1 rend () const { Chris@16: return const_reverse_iterator1 (begin ()); Chris@16: } Chris@101: BOOST_UBLAS_INLINE Chris@101: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@101: typename self_type:: Chris@101: #endif Chris@101: const_reverse_iterator1 crend () const { Chris@101: return rend (); Chris@101: } Chris@16: #endif Chris@16: Chris@16: // Indices Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type index1 () const { Chris@16: if (rank_ == 1) { Chris@16: BOOST_UBLAS_CHECK (layout_type::index_M (itv_ - (*this) ().index1_data_.begin (), (*this) ().zero_based (*it_)) < (*this) ().size1 (), bad_index ()); Chris@16: return layout_type::index_M (itv_ - (*this) ().index1_data_.begin (), (*this) ().zero_based (*it_)); Chris@16: } else { Chris@16: return i_; Chris@16: } Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type index2 () const { Chris@16: BOOST_UBLAS_CHECK (*this != (*this) ().find2 (0, i_, (*this) ().size2 ()), bad_index ()); Chris@16: if (rank_ == 1) { Chris@16: BOOST_UBLAS_CHECK (layout_type::index_m (itv_ - (*this) ().index1_data_.begin (), (*this) ().zero_based (*it_)) < (*this) ().size2 (), bad_index ()); Chris@16: return layout_type::index_m (itv_ - (*this) ().index1_data_.begin (), (*this) ().zero_based (*it_)); Chris@16: } else { Chris@16: return j_; Chris@16: } Chris@16: } Chris@16: Chris@16: // Assignment Chris@16: BOOST_UBLAS_INLINE Chris@16: const_iterator2 &operator = (const const_iterator2 &it) { Chris@16: container_const_reference::assign (&it ()); Chris@16: rank_ = it.rank_; Chris@16: i_ = it.i_; Chris@16: j_ = it.j_; Chris@16: itv_ = it.itv_; Chris@16: it_ = it.it_; Chris@16: return *this; Chris@16: } Chris@16: Chris@16: // Comparison Chris@16: BOOST_UBLAS_INLINE Chris@16: bool operator == (const const_iterator2 &it) const { Chris@16: BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); Chris@16: // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ()); Chris@16: if (rank_ == 1 || it.rank_ == 1) { Chris@16: return it_ == it.it_; Chris@16: } else { Chris@16: return i_ == it.i_ && j_ == it.j_; Chris@16: } Chris@16: } Chris@16: Chris@16: private: Chris@16: int rank_; Chris@16: size_type i_; Chris@16: size_type j_; Chris@16: vector_const_subiterator_type itv_; Chris@16: const_subiterator_type it_; Chris@16: }; Chris@16: Chris@16: BOOST_UBLAS_INLINE Chris@16: const_iterator2 begin2 () const { Chris@16: return find2 (0, 0, 0); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@101: const_iterator2 cbegin2 () const { Chris@101: return begin2 (); Chris@101: } Chris@101: BOOST_UBLAS_INLINE Chris@16: const_iterator2 end2 () const { Chris@16: return find2 (0, 0, size2_); Chris@16: } Chris@101: BOOST_UBLAS_INLINE Chris@101: const_iterator2 cend2 () const { Chris@101: return end2 (); Chris@101: } Chris@16: Chris@16: class iterator2: Chris@16: public container_reference, Chris@16: public bidirectional_iterator_base { Chris@16: public: Chris@16: typedef typename compressed_matrix::value_type value_type; Chris@16: typedef typename compressed_matrix::difference_type difference_type; Chris@16: typedef typename compressed_matrix::true_reference reference; Chris@16: typedef typename compressed_matrix::pointer pointer; Chris@16: Chris@16: typedef iterator1 dual_iterator_type; Chris@16: typedef reverse_iterator1 dual_reverse_iterator_type; Chris@16: Chris@16: // Construction and destruction Chris@16: BOOST_UBLAS_INLINE Chris@16: iterator2 (): Chris@16: container_reference (), rank_ (), i_ (), j_ (), itv_ (), it_ () {} Chris@16: BOOST_UBLAS_INLINE Chris@16: iterator2 (self_type &m, int rank, size_type i, size_type j, const vector_subiterator_type &itv, const subiterator_type &it): Chris@16: container_reference (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {} Chris@16: Chris@16: // Arithmetic Chris@16: BOOST_UBLAS_INLINE Chris@16: iterator2 &operator ++ () { Chris@16: if (rank_ == 1 && layout_type::fast_j ()) Chris@16: ++ it_; Chris@16: else { Chris@16: j_ = index2 () + 1; Chris@16: if (rank_ == 1) Chris@16: *this = (*this) ().find2 (rank_, i_, j_, 1); Chris@16: } Chris@16: return *this; Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: iterator2 &operator -- () { Chris@16: if (rank_ == 1 && layout_type::fast_j ()) Chris@16: -- it_; Chris@16: else { Chris@16: --j_; Chris@16: if (rank_ == 1) Chris@16: *this = (*this) ().find2 (rank_, i_, j_, -1); Chris@16: } Chris@16: return *this; Chris@16: } Chris@16: Chris@16: // Dereference Chris@16: BOOST_UBLAS_INLINE Chris@16: reference operator * () const { Chris@16: BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ()); Chris@16: BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ()); Chris@16: if (rank_ == 1) { Chris@16: return (*this) ().value_data_ [it_ - (*this) ().index2_data_.begin ()]; Chris@16: } else { Chris@16: return (*this) ().at_element (i_, j_); Chris@16: } Chris@16: } Chris@16: Chris@16: #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION Chris@16: BOOST_UBLAS_INLINE Chris@16: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@16: typename self_type:: Chris@16: #endif Chris@16: iterator1 begin () const { Chris@16: self_type &m = (*this) (); Chris@16: return m.find1 (1, 0, index2 ()); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@16: typename self_type:: Chris@16: #endif Chris@16: iterator1 end () const { Chris@16: self_type &m = (*this) (); Chris@16: return m.find1 (1, m.size1 (), index2 ()); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@16: typename self_type:: Chris@16: #endif Chris@16: reverse_iterator1 rbegin () const { Chris@16: return reverse_iterator1 (end ()); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@16: typename self_type:: Chris@16: #endif Chris@16: reverse_iterator1 rend () const { Chris@16: return reverse_iterator1 (begin ()); Chris@16: } Chris@16: #endif Chris@16: Chris@16: // Indices Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type index1 () const { Chris@16: if (rank_ == 1) { Chris@16: BOOST_UBLAS_CHECK (layout_type::index_M (itv_ - (*this) ().index1_data_.begin (), (*this) ().zero_based (*it_)) < (*this) ().size1 (), bad_index ()); Chris@16: return layout_type::index_M (itv_ - (*this) ().index1_data_.begin (), (*this) ().zero_based (*it_)); Chris@16: } else { Chris@16: return i_; Chris@16: } Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type index2 () const { Chris@16: BOOST_UBLAS_CHECK (*this != (*this) ().find2 (0, i_, (*this) ().size2 ()), bad_index ()); Chris@16: if (rank_ == 1) { Chris@16: BOOST_UBLAS_CHECK (layout_type::index_m (itv_ - (*this) ().index1_data_.begin (), (*this) ().zero_based (*it_)) < (*this) ().size2 (), bad_index ()); Chris@16: return layout_type::index_m (itv_ - (*this) ().index1_data_.begin (), (*this) ().zero_based (*it_)); Chris@16: } else { Chris@16: return j_; Chris@16: } Chris@16: } Chris@16: Chris@16: // Assignment Chris@16: BOOST_UBLAS_INLINE Chris@16: iterator2 &operator = (const iterator2 &it) { Chris@16: container_reference::assign (&it ()); Chris@16: rank_ = it.rank_; Chris@16: i_ = it.i_; Chris@16: j_ = it.j_; Chris@16: itv_ = it.itv_; Chris@16: it_ = it.it_; Chris@16: return *this; Chris@16: } Chris@16: Chris@16: // Comparison Chris@16: BOOST_UBLAS_INLINE Chris@16: bool operator == (const iterator2 &it) const { Chris@16: BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); Chris@16: // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ()); Chris@16: if (rank_ == 1 || it.rank_ == 1) { Chris@16: return it_ == it.it_; Chris@16: } else { Chris@16: return i_ == it.i_ && j_ == it.j_; Chris@16: } Chris@16: } Chris@16: Chris@16: private: Chris@16: int rank_; Chris@16: size_type i_; Chris@16: size_type j_; Chris@16: vector_subiterator_type itv_; Chris@16: subiterator_type it_; Chris@16: Chris@16: friend class const_iterator2; Chris@16: }; Chris@16: Chris@16: BOOST_UBLAS_INLINE Chris@16: iterator2 begin2 () { Chris@16: return find2 (0, 0, 0); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: iterator2 end2 () { Chris@16: return find2 (0, 0, size2_); Chris@16: } Chris@16: Chris@16: // Reverse iterators Chris@16: Chris@16: BOOST_UBLAS_INLINE Chris@16: const_reverse_iterator1 rbegin1 () const { Chris@16: return const_reverse_iterator1 (end1 ()); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@101: const_reverse_iterator1 crbegin1 () const { Chris@101: return rbegin1 (); Chris@101: } Chris@101: BOOST_UBLAS_INLINE Chris@16: const_reverse_iterator1 rend1 () const { Chris@16: return const_reverse_iterator1 (begin1 ()); Chris@16: } Chris@101: BOOST_UBLAS_INLINE Chris@101: const_reverse_iterator1 crend1 () const { Chris@101: return rend1 (); Chris@101: } Chris@16: Chris@16: BOOST_UBLAS_INLINE Chris@16: reverse_iterator1 rbegin1 () { Chris@16: return reverse_iterator1 (end1 ()); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: reverse_iterator1 rend1 () { Chris@16: return reverse_iterator1 (begin1 ()); Chris@16: } Chris@16: Chris@16: BOOST_UBLAS_INLINE Chris@16: const_reverse_iterator2 rbegin2 () const { Chris@16: return const_reverse_iterator2 (end2 ()); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@101: const_reverse_iterator2 crbegin2 () const { Chris@101: return rbegin2 (); Chris@101: } Chris@101: BOOST_UBLAS_INLINE Chris@16: const_reverse_iterator2 rend2 () const { Chris@16: return const_reverse_iterator2 (begin2 ()); Chris@16: } Chris@101: BOOST_UBLAS_INLINE Chris@101: const_reverse_iterator2 crend2 () const { Chris@101: return rend2 (); Chris@101: } Chris@16: Chris@16: BOOST_UBLAS_INLINE Chris@16: reverse_iterator2 rbegin2 () { Chris@16: return reverse_iterator2 (end2 ()); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: reverse_iterator2 rend2 () { Chris@16: return reverse_iterator2 (begin2 ()); Chris@16: } Chris@16: Chris@16: // Serialization Chris@16: template Chris@16: void serialize(Archive & ar, const unsigned int /* file_version */){ Chris@16: serialization::collection_size_type s1 (size1_); Chris@16: serialization::collection_size_type s2 (size2_); Chris@16: ar & serialization::make_nvp("size1",s1); Chris@16: ar & serialization::make_nvp("size2",s2); Chris@16: if (Archive::is_loading::value) { Chris@16: size1_ = s1; Chris@16: size2_ = s2; Chris@16: } Chris@16: ar & serialization::make_nvp("capacity", capacity_); Chris@16: ar & serialization::make_nvp("filled1", filled1_); Chris@16: ar & serialization::make_nvp("filled2", filled2_); Chris@16: ar & serialization::make_nvp("index1_data", index1_data_); Chris@16: ar & serialization::make_nvp("index2_data", index2_data_); Chris@16: ar & serialization::make_nvp("value_data", value_data_); Chris@16: storage_invariants(); Chris@16: } Chris@16: Chris@16: private: Chris@16: void storage_invariants () const { Chris@16: BOOST_UBLAS_CHECK (layout_type::size_M (size1_, size2_) + 1 == index1_data_.size (), internal_logic ()); Chris@16: BOOST_UBLAS_CHECK (capacity_ == index2_data_.size (), internal_logic ()); Chris@16: BOOST_UBLAS_CHECK (capacity_ == value_data_.size (), internal_logic ()); Chris@16: BOOST_UBLAS_CHECK (filled1_ > 0 && filled1_ <= layout_type::size_M (size1_, size2_) + 1, internal_logic ()); Chris@16: BOOST_UBLAS_CHECK (filled2_ <= capacity_, internal_logic ()); Chris@16: BOOST_UBLAS_CHECK (index1_data_ [filled1_ - 1] == k_based (filled2_), internal_logic ()); Chris@16: } Chris@16: Chris@16: size_type size1_; Chris@16: size_type size2_; Chris@16: array_size_type capacity_; Chris@16: array_size_type filled1_; Chris@16: array_size_type filled2_; Chris@16: index_array_type index1_data_; Chris@16: index_array_type index2_data_; Chris@16: value_array_type value_data_; Chris@16: static const value_type zero_; Chris@16: Chris@16: BOOST_UBLAS_INLINE Chris@16: static size_type zero_based (size_type k_based_index) { Chris@16: return k_based_index - IB; Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: static size_type k_based (size_type zero_based_index) { Chris@16: return zero_based_index + IB; Chris@16: } Chris@16: Chris@16: friend class iterator1; Chris@16: friend class iterator2; Chris@16: friend class const_iterator1; Chris@16: friend class const_iterator2; Chris@16: }; Chris@16: Chris@16: template Chris@16: const typename compressed_matrix::value_type compressed_matrix::zero_ = value_type/*zero*/(); Chris@16: Chris@16: Chris@16: // Coordinate array based sparse matrix class Chris@16: // Thanks to Kresimir Fresl for extending this to cover different index bases. Chris@16: template Chris@16: class coordinate_matrix: Chris@16: public matrix_container > { Chris@16: Chris@16: typedef T &true_reference; Chris@16: typedef T *pointer; Chris@16: typedef const T *const_pointer; Chris@16: typedef L layout_type; Chris@16: typedef coordinate_matrix self_type; Chris@16: public: Chris@16: #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS Chris@16: using matrix_container::operator (); Chris@16: #endif Chris@16: // ISSUE require type consistency check, is_convertable (IA::size_type, TA::size_type) Chris@16: typedef typename IA::value_type size_type; Chris@16: // ISSUE difference_type cannot be deduced for sparse indices, we only know the value_type Chris@16: typedef std::ptrdiff_t difference_type; Chris@16: // size_type for the data arrays. Chris@16: typedef typename IA::size_type array_size_type; Chris@16: typedef T value_type; Chris@16: typedef const T &const_reference; Chris@16: #ifndef BOOST_UBLAS_STRICT_MATRIX_SPARSE Chris@16: typedef T &reference; Chris@16: #else Chris@16: typedef sparse_matrix_element reference; Chris@16: #endif Chris@16: typedef IA index_array_type; Chris@16: typedef TA value_array_type; Chris@16: typedef const matrix_reference const_closure_type; Chris@16: typedef matrix_reference closure_type; Chris@16: typedef coordinate_vector vector_temporary_type; Chris@16: typedef self_type matrix_temporary_type; Chris@16: typedef sparse_tag storage_category; Chris@16: typedef typename L::orientation_category orientation_category; Chris@16: Chris@16: // Construction and destruction Chris@16: BOOST_UBLAS_INLINE Chris@16: coordinate_matrix (): Chris@16: matrix_container (), Chris@16: size1_ (0), size2_ (0), capacity_ (restrict_capacity (0)), Chris@16: filled_ (0), sorted_filled_ (filled_), sorted_ (true), Chris@16: index1_data_ (capacity_), index2_data_ (capacity_), value_data_ (capacity_) { Chris@16: storage_invariants (); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: coordinate_matrix (size_type size1, size_type size2, array_size_type non_zeros = 0): Chris@16: matrix_container (), Chris@16: size1_ (size1), size2_ (size2), capacity_ (restrict_capacity (non_zeros)), Chris@16: filled_ (0), sorted_filled_ (filled_), sorted_ (true), Chris@16: index1_data_ (capacity_), index2_data_ (capacity_), value_data_ (capacity_) { Chris@16: storage_invariants (); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: coordinate_matrix (const coordinate_matrix &m): Chris@16: matrix_container (), Chris@16: size1_ (m.size1_), size2_ (m.size2_), capacity_ (m.capacity_), Chris@16: filled_ (m.filled_), sorted_filled_ (m.sorted_filled_), sorted_ (m.sorted_), Chris@16: index1_data_ (m.index1_data_), index2_data_ (m.index2_data_), value_data_ (m.value_data_) { Chris@16: storage_invariants (); Chris@16: } Chris@16: template Chris@16: BOOST_UBLAS_INLINE Chris@16: coordinate_matrix (const matrix_expression &ae, array_size_type non_zeros = 0): Chris@16: matrix_container (), Chris@16: size1_ (ae ().size1 ()), size2_ (ae ().size2 ()), capacity_ (restrict_capacity (non_zeros)), Chris@16: filled_ (0), sorted_filled_ (filled_), sorted_ (true), Chris@16: index1_data_ (capacity_), index2_data_ (capacity_), value_data_ (capacity_) { Chris@16: storage_invariants (); Chris@16: matrix_assign (*this, ae); Chris@16: } Chris@16: Chris@16: // Accessors Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type size1 () const { Chris@16: return size1_; Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type size2 () const { Chris@16: return size2_; Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type nnz_capacity () const { Chris@16: return capacity_; Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type nnz () const { Chris@16: return filled_; Chris@16: } Chris@16: Chris@16: // Storage accessors Chris@16: BOOST_UBLAS_INLINE Chris@16: static size_type index_base () { Chris@16: return IB; Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: array_size_type filled () const { Chris@16: return filled_; Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: const index_array_type &index1_data () const { Chris@16: return index1_data_; Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: const index_array_type &index2_data () const { Chris@16: return index2_data_; Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: const value_array_type &value_data () const { Chris@16: return value_data_; Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: void set_filled (const array_size_type &filled) { Chris@16: // Make sure that storage_invariants() succeeds Chris@16: if (sorted_ && filled < filled_) Chris@16: sorted_filled_ = filled; Chris@16: else Chris@16: sorted_ = (sorted_filled_ == filled); Chris@16: filled_ = filled; Chris@16: storage_invariants (); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: index_array_type &index1_data () { Chris@16: return index1_data_; Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: index_array_type &index2_data () { Chris@16: return index2_data_; Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: value_array_type &value_data () { Chris@16: return value_data_; Chris@16: } Chris@16: Chris@16: // Resizing Chris@16: private: Chris@16: BOOST_UBLAS_INLINE Chris@16: array_size_type restrict_capacity (array_size_type non_zeros) const { Chris@16: // minimum non_zeros Chris@16: non_zeros = (std::max) (non_zeros, array_size_type((std::min) (size1_, size2_))); Chris@16: // ISSUE no maximum as coordinate may contain inserted duplicates Chris@16: return non_zeros; Chris@16: } Chris@16: public: Chris@16: BOOST_UBLAS_INLINE Chris@16: void resize (size_type size1, size_type size2, bool preserve = true) { Chris@16: // FIXME preserve unimplemented Chris@16: BOOST_UBLAS_CHECK (!preserve, internal_logic ()); Chris@16: size1_ = size1; Chris@16: size2_ = size2; Chris@16: capacity_ = restrict_capacity (capacity_); Chris@16: index1_data_.resize (capacity_); Chris@16: index2_data_.resize (capacity_); Chris@16: value_data_.resize (capacity_); Chris@16: filled_ = 0; Chris@16: sorted_filled_ = filled_; Chris@16: sorted_ = true; Chris@16: storage_invariants (); Chris@16: } Chris@16: Chris@16: // Reserving Chris@16: BOOST_UBLAS_INLINE Chris@16: void reserve (array_size_type non_zeros, bool preserve = true) { Chris@16: sort (); // remove duplicate elements Chris@16: capacity_ = restrict_capacity (non_zeros); Chris@16: if (preserve) { Chris@16: index1_data_.resize (capacity_, size_type ()); Chris@16: index2_data_.resize (capacity_, size_type ()); Chris@16: value_data_.resize (capacity_, value_type ()); Chris@16: filled_ = (std::min) (capacity_, filled_); Chris@16: } Chris@16: else { Chris@16: index1_data_.resize (capacity_); Chris@16: index2_data_.resize (capacity_); Chris@16: value_data_.resize (capacity_); Chris@16: filled_ = 0; Chris@16: } Chris@16: sorted_filled_ = filled_; Chris@16: storage_invariants (); Chris@16: } Chris@16: Chris@16: // Element support Chris@16: BOOST_UBLAS_INLINE Chris@16: pointer find_element (size_type i, size_type j) { Chris@16: return const_cast (const_cast(*this).find_element (i, j)); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: const_pointer find_element (size_type i, size_type j) const { Chris@16: sort (); Chris@16: size_type element1 (layout_type::index_M (i, j)); Chris@16: size_type element2 (layout_type::index_m (i, j)); Chris@16: vector_const_subiterator_type itv_begin (detail::lower_bound (index1_data_.begin (), index1_data_.begin () + filled_, k_based (element1), std::less ())); Chris@16: vector_const_subiterator_type itv_end (detail::upper_bound (index1_data_.begin (), index1_data_.begin () + filled_, k_based (element1), std::less ())); Chris@16: if (itv_begin == itv_end) Chris@16: return 0; Chris@16: const_subiterator_type it_begin (index2_data_.begin () + (itv_begin - index1_data_.begin ())); Chris@16: const_subiterator_type it_end (index2_data_.begin () + (itv_end - index1_data_.begin ())); Chris@16: const_subiterator_type it (detail::lower_bound (it_begin, it_end, k_based (element2), std::less ())); Chris@16: if (it == it_end || *it != k_based (element2)) Chris@16: return 0; Chris@16: return &value_data_ [it - index2_data_.begin ()]; Chris@16: } Chris@16: Chris@16: // Element access Chris@16: BOOST_UBLAS_INLINE Chris@16: const_reference operator () (size_type i, size_type j) const { Chris@16: const_pointer p = find_element (i, j); Chris@16: if (p) Chris@16: return *p; Chris@16: else Chris@16: return zero_; Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: reference operator () (size_type i, size_type j) { Chris@16: #ifndef BOOST_UBLAS_STRICT_MATRIX_SPARSE Chris@16: pointer p = find_element (i, j); Chris@16: if (p) Chris@16: return *p; Chris@16: else Chris@16: return insert_element (i, j, value_type/*zero*/()); Chris@16: #else Chris@16: return reference (*this, i, j); Chris@16: #endif Chris@16: } Chris@16: Chris@16: // Element assignment Chris@16: BOOST_UBLAS_INLINE Chris@16: void append_element (size_type i, size_type j, const_reference t) { Chris@16: if (filled_ >= capacity_) Chris@16: reserve (2 * filled_, true); Chris@16: BOOST_UBLAS_CHECK (filled_ < capacity_, internal_logic ()); Chris@16: size_type element1 = layout_type::index_M (i, j); Chris@16: size_type element2 = layout_type::index_m (i, j); Chris@16: index1_data_ [filled_] = k_based (element1); Chris@16: index2_data_ [filled_] = k_based (element2); Chris@16: value_data_ [filled_] = t; Chris@16: ++ filled_; Chris@16: sorted_ = false; Chris@16: storage_invariants (); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: true_reference insert_element (size_type i, size_type j, const_reference t) { Chris@16: BOOST_UBLAS_CHECK (!find_element (i, j), bad_index ()); // duplicate element Chris@16: append_element (i, j, t); Chris@16: return value_data_ [filled_ - 1]; Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: void erase_element (size_type i, size_type j) { Chris@16: size_type element1 = layout_type::index_M (i, j); Chris@16: size_type element2 = layout_type::index_m (i, j); Chris@16: sort (); Chris@16: vector_subiterator_type itv_begin (detail::lower_bound (index1_data_.begin (), index1_data_.begin () + filled_, k_based (element1), std::less ())); Chris@16: vector_subiterator_type itv_end (detail::upper_bound (index1_data_.begin (), index1_data_.begin () + filled_, k_based (element1), std::less ())); Chris@16: subiterator_type it_begin (index2_data_.begin () + (itv_begin - index1_data_.begin ())); Chris@16: subiterator_type it_end (index2_data_.begin () + (itv_end - index1_data_.begin ())); Chris@16: subiterator_type it (detail::lower_bound (it_begin, it_end, k_based (element2), std::less ())); Chris@16: if (it != it_end && *it == k_based (element2)) { Chris@16: typename std::iterator_traits::difference_type n = it - index2_data_.begin (); Chris@16: vector_subiterator_type itv (index1_data_.begin () + n); Chris@16: std::copy (itv + 1, index1_data_.begin () + filled_, itv); Chris@16: std::copy (it + 1, index2_data_.begin () + filled_, it); Chris@16: typename value_array_type::iterator itt (value_data_.begin () + n); Chris@16: std::copy (itt + 1, value_data_.begin () + filled_, itt); Chris@16: -- filled_; Chris@16: sorted_filled_ = filled_; Chris@16: } Chris@16: storage_invariants (); Chris@16: } Chris@16: Chris@16: // Zeroing Chris@16: BOOST_UBLAS_INLINE Chris@16: void clear () { Chris@16: filled_ = 0; Chris@16: sorted_filled_ = filled_; Chris@16: sorted_ = true; Chris@16: storage_invariants (); Chris@16: } Chris@16: Chris@16: // Assignment Chris@16: BOOST_UBLAS_INLINE Chris@16: coordinate_matrix &operator = (const coordinate_matrix &m) { Chris@16: if (this != &m) { Chris@16: size1_ = m.size1_; Chris@16: size2_ = m.size2_; Chris@16: capacity_ = m.capacity_; Chris@16: filled_ = m.filled_; Chris@16: sorted_filled_ = m.sorted_filled_; Chris@16: sorted_ = m.sorted_; Chris@16: index1_data_ = m.index1_data_; Chris@16: index2_data_ = m.index2_data_; Chris@16: value_data_ = m.value_data_; Chris@16: BOOST_UBLAS_CHECK (capacity_ == index1_data_.size (), internal_logic ()); Chris@16: BOOST_UBLAS_CHECK (capacity_ == index2_data_.size (), internal_logic ()); Chris@16: BOOST_UBLAS_CHECK (capacity_ == value_data_.size (), internal_logic ()); Chris@16: } Chris@16: storage_invariants (); Chris@16: return *this; Chris@16: } Chris@16: template // Container assignment without temporary Chris@16: BOOST_UBLAS_INLINE Chris@16: coordinate_matrix &operator = (const matrix_container &m) { Chris@16: resize (m ().size1 (), m ().size2 (), false); Chris@16: assign (m); Chris@16: return *this; Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: coordinate_matrix &assign_temporary (coordinate_matrix &m) { Chris@16: swap (m); Chris@16: return *this; Chris@16: } Chris@16: template Chris@16: BOOST_UBLAS_INLINE Chris@16: coordinate_matrix &operator = (const matrix_expression &ae) { Chris@16: self_type temporary (ae, capacity_); Chris@16: return assign_temporary (temporary); Chris@16: } Chris@16: template Chris@16: BOOST_UBLAS_INLINE Chris@16: coordinate_matrix &assign (const matrix_expression &ae) { Chris@16: matrix_assign (*this, ae); Chris@16: return *this; Chris@16: } Chris@16: template Chris@16: BOOST_UBLAS_INLINE Chris@16: coordinate_matrix& operator += (const matrix_expression &ae) { Chris@16: self_type temporary (*this + ae, capacity_); Chris@16: return assign_temporary (temporary); Chris@16: } Chris@16: template // Container assignment without temporary Chris@16: BOOST_UBLAS_INLINE Chris@16: coordinate_matrix &operator += (const matrix_container &m) { Chris@16: plus_assign (m); Chris@16: return *this; Chris@16: } Chris@16: template Chris@16: BOOST_UBLAS_INLINE Chris@16: coordinate_matrix &plus_assign (const matrix_expression &ae) { Chris@16: matrix_assign (*this, ae); Chris@16: return *this; Chris@16: } Chris@16: template Chris@16: BOOST_UBLAS_INLINE Chris@16: coordinate_matrix& operator -= (const matrix_expression &ae) { Chris@16: self_type temporary (*this - ae, capacity_); Chris@16: return assign_temporary (temporary); Chris@16: } Chris@16: template // Container assignment without temporary Chris@16: BOOST_UBLAS_INLINE Chris@16: coordinate_matrix &operator -= (const matrix_container &m) { Chris@16: minus_assign (m); Chris@16: return *this; Chris@16: } Chris@16: template Chris@16: BOOST_UBLAS_INLINE Chris@16: coordinate_matrix &minus_assign (const matrix_expression &ae) { Chris@16: matrix_assign (*this, ae); Chris@16: return *this; Chris@16: } Chris@16: template Chris@16: BOOST_UBLAS_INLINE Chris@16: coordinate_matrix& operator *= (const AT &at) { Chris@16: matrix_assign_scalar (*this, at); Chris@16: return *this; Chris@16: } Chris@16: template Chris@16: BOOST_UBLAS_INLINE Chris@16: coordinate_matrix& operator /= (const AT &at) { Chris@16: matrix_assign_scalar (*this, at); Chris@16: return *this; Chris@16: } Chris@16: Chris@16: // Swapping Chris@16: BOOST_UBLAS_INLINE Chris@16: void swap (coordinate_matrix &m) { Chris@16: if (this != &m) { Chris@16: std::swap (size1_, m.size1_); Chris@16: std::swap (size2_, m.size2_); Chris@16: std::swap (capacity_, m.capacity_); Chris@16: std::swap (filled_, m.filled_); Chris@16: std::swap (sorted_filled_, m.sorted_filled_); Chris@16: std::swap (sorted_, m.sorted_); Chris@16: index1_data_.swap (m.index1_data_); Chris@16: index2_data_.swap (m.index2_data_); Chris@16: value_data_.swap (m.value_data_); Chris@16: } Chris@16: storage_invariants (); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: friend void swap (coordinate_matrix &m1, coordinate_matrix &m2) { Chris@16: m1.swap (m2); Chris@16: } Chris@16: Chris@16: // replacement if STL lower bound algorithm for use of inplace_merge Chris@16: array_size_type lower_bound (array_size_type beg, array_size_type end, array_size_type target) const { Chris@16: while (end > beg) { Chris@16: array_size_type mid = (beg + end) / 2; Chris@16: if (((index1_data_[mid] < index1_data_[target]) || Chris@16: ((index1_data_[mid] == index1_data_[target]) && Chris@16: (index2_data_[mid] < index2_data_[target])))) { Chris@16: beg = mid + 1; Chris@16: } else { Chris@16: end = mid; Chris@16: } Chris@16: } Chris@16: return beg; Chris@16: } Chris@16: Chris@16: // specialized replacement of STL inplace_merge to avoid compilation Chris@16: // problems with respect to the array_triple iterator Chris@16: void inplace_merge (array_size_type beg, array_size_type mid, array_size_type end) const { Chris@16: array_size_type len_lef = mid - beg; Chris@16: array_size_type len_rig = end - mid; Chris@16: Chris@16: if (len_lef == 1 && len_rig == 1) { Chris@16: if ((index1_data_[mid] < index1_data_[beg]) || Chris@16: ((index1_data_[mid] == index1_data_[beg]) && (index2_data_[mid] < index2_data_[beg]))) Chris@16: { Chris@16: std::swap(index1_data_[beg], index1_data_[mid]); Chris@16: std::swap(index2_data_[beg], index2_data_[mid]); Chris@16: std::swap(value_data_[beg], value_data_[mid]); Chris@16: } Chris@16: } else if (len_lef > 0 && len_rig > 0) { Chris@16: array_size_type lef_mid, rig_mid; Chris@16: if (len_lef >= len_rig) { Chris@16: lef_mid = (beg + mid) / 2; Chris@16: rig_mid = lower_bound(mid, end, lef_mid); Chris@16: } else { Chris@16: rig_mid = (mid + end) / 2; Chris@16: lef_mid = lower_bound(beg, mid, rig_mid); Chris@16: } Chris@16: std::rotate(&index1_data_[0] + lef_mid, &index1_data_[0] + mid, &index1_data_[0] + rig_mid); Chris@16: std::rotate(&index2_data_[0] + lef_mid, &index2_data_[0] + mid, &index2_data_[0] + rig_mid); Chris@16: std::rotate(&value_data_[0] + lef_mid, &value_data_[0] + mid, &value_data_[0] + rig_mid); Chris@16: Chris@16: array_size_type new_mid = lef_mid + rig_mid - mid; Chris@16: inplace_merge(beg, lef_mid, new_mid); Chris@16: inplace_merge(new_mid, rig_mid, end); Chris@16: } Chris@16: } Chris@16: Chris@16: // Sorting and summation of duplicates Chris@16: BOOST_UBLAS_INLINE Chris@16: void sort () const { Chris@16: if (! sorted_ && filled_ > 0) { Chris@16: typedef index_triple_array array_triple; Chris@16: array_triple ita (filled_, index1_data_, index2_data_, value_data_); Chris@16: #ifndef BOOST_UBLAS_COO_ALWAYS_DO_FULL_SORT Chris@16: const typename array_triple::iterator iunsorted = ita.begin () + sorted_filled_; Chris@16: // sort new elements and merge Chris@16: std::sort (iunsorted, ita.end ()); Chris@16: inplace_merge(0, sorted_filled_, filled_); Chris@16: #else Chris@16: const typename array_triple::iterator iunsorted = ita.begin (); Chris@16: std::sort (iunsorted, ita.end ()); Chris@16: #endif Chris@16: // sum duplicates with += and remove Chris@16: array_size_type filled = 0; Chris@16: for (array_size_type i = 1; i < filled_; ++ i) { Chris@16: if (index1_data_ [filled] != index1_data_ [i] || Chris@16: index2_data_ [filled] != index2_data_ [i]) { Chris@16: ++ filled; Chris@16: if (filled != i) { Chris@16: index1_data_ [filled] = index1_data_ [i]; Chris@16: index2_data_ [filled] = index2_data_ [i]; Chris@16: value_data_ [filled] = value_data_ [i]; Chris@16: } Chris@16: } else { Chris@16: value_data_ [filled] += value_data_ [i]; Chris@16: } Chris@16: } Chris@16: filled_ = filled + 1; Chris@16: sorted_filled_ = filled_; Chris@16: sorted_ = true; Chris@16: storage_invariants (); Chris@16: } Chris@16: } Chris@16: Chris@16: // Back element insertion and erasure Chris@16: BOOST_UBLAS_INLINE Chris@16: void push_back (size_type i, size_type j, const_reference t) { Chris@16: size_type element1 = layout_type::index_M (i, j); Chris@16: size_type element2 = layout_type::index_m (i, j); Chris@16: // must maintain sort order Chris@16: BOOST_UBLAS_CHECK (sorted_ && Chris@16: (filled_ == 0 || Chris@16: index1_data_ [filled_ - 1] < k_based (element1) || Chris@16: (index1_data_ [filled_ - 1] == k_based (element1) && index2_data_ [filled_ - 1] < k_based (element2))) Chris@16: , external_logic ()); Chris@16: if (filled_ >= capacity_) Chris@16: reserve (2 * filled_, true); Chris@16: BOOST_UBLAS_CHECK (filled_ < capacity_, internal_logic ()); Chris@16: index1_data_ [filled_] = k_based (element1); Chris@16: index2_data_ [filled_] = k_based (element2); Chris@16: value_data_ [filled_] = t; Chris@16: ++ filled_; Chris@16: sorted_filled_ = filled_; Chris@16: storage_invariants (); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: void pop_back () { Chris@16: // ISSUE invariants could be simpilfied if sorted required as precondition Chris@16: BOOST_UBLAS_CHECK (filled_ > 0, external_logic ()); Chris@16: -- filled_; Chris@16: sorted_filled_ = (std::min) (sorted_filled_, filled_); Chris@16: sorted_ = sorted_filled_ = filled_; Chris@16: storage_invariants (); Chris@16: } Chris@16: Chris@16: // Iterator types Chris@16: private: Chris@16: // Use index array iterator Chris@16: typedef typename IA::const_iterator vector_const_subiterator_type; Chris@16: typedef typename IA::iterator vector_subiterator_type; Chris@16: typedef typename IA::const_iterator const_subiterator_type; Chris@16: typedef typename IA::iterator subiterator_type; Chris@16: Chris@16: BOOST_UBLAS_INLINE Chris@16: true_reference at_element (size_type i, size_type j) { Chris@16: pointer p = find_element (i, j); Chris@16: BOOST_UBLAS_CHECK (p, bad_index ()); Chris@16: return *p; Chris@16: } Chris@16: Chris@16: public: Chris@16: class const_iterator1; Chris@16: class iterator1; Chris@16: class const_iterator2; Chris@16: class iterator2; Chris@16: typedef reverse_iterator_base1 const_reverse_iterator1; Chris@16: typedef reverse_iterator_base1 reverse_iterator1; Chris@16: typedef reverse_iterator_base2 const_reverse_iterator2; Chris@16: typedef reverse_iterator_base2 reverse_iterator2; Chris@16: Chris@16: // Element lookup Chris@16: // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it. Chris@16: const_iterator1 find1 (int rank, size_type i, size_type j, int direction = 1) const { Chris@16: sort (); Chris@16: for (;;) { Chris@16: size_type address1 (layout_type::index_M (i, j)); Chris@16: size_type address2 (layout_type::index_m (i, j)); Chris@16: vector_const_subiterator_type itv_begin (detail::lower_bound (index1_data_.begin (), index1_data_.begin () + filled_, k_based (address1), std::less ())); Chris@16: vector_const_subiterator_type itv_end (detail::upper_bound (index1_data_.begin (), index1_data_.begin () + filled_, k_based (address1), std::less ())); Chris@16: Chris@16: const_subiterator_type it_begin (index2_data_.begin () + (itv_begin - index1_data_.begin ())); Chris@16: const_subiterator_type it_end (index2_data_.begin () + (itv_end - index1_data_.begin ())); Chris@16: Chris@16: const_subiterator_type it (detail::lower_bound (it_begin, it_end, k_based (address2), std::less ())); Chris@16: vector_const_subiterator_type itv (index1_data_.begin () + (it - index2_data_.begin ())); Chris@16: if (rank == 0) Chris@16: return const_iterator1 (*this, rank, i, j, itv, it); Chris@16: if (it != it_end && zero_based (*it) == address2) Chris@16: return const_iterator1 (*this, rank, i, j, itv, it); Chris@16: if (direction > 0) { Chris@16: if (layout_type::fast_i ()) { Chris@16: if (it == it_end) Chris@16: return const_iterator1 (*this, rank, i, j, itv, it); Chris@16: i = zero_based (*it); Chris@16: } else { Chris@16: if (i >= size1_) Chris@16: return const_iterator1 (*this, rank, i, j, itv, it); Chris@16: ++ i; Chris@16: } Chris@16: } else /* if (direction < 0) */ { Chris@16: if (layout_type::fast_i ()) { Chris@16: if (it == index2_data_.begin () + array_size_type (zero_based (*itv))) Chris@16: return const_iterator1 (*this, rank, i, j, itv, it); Chris@16: i = zero_based (*(it - 1)); Chris@16: } else { Chris@16: if (i == 0) Chris@16: return const_iterator1 (*this, rank, i, j, itv, it); Chris@16: -- i; Chris@16: } Chris@16: } Chris@16: } Chris@16: } Chris@16: // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it. Chris@16: iterator1 find1 (int rank, size_type i, size_type j, int direction = 1) { Chris@16: sort (); Chris@16: for (;;) { Chris@16: size_type address1 (layout_type::index_M (i, j)); Chris@16: size_type address2 (layout_type::index_m (i, j)); Chris@16: vector_subiterator_type itv_begin (detail::lower_bound (index1_data_.begin (), index1_data_.begin () + filled_, k_based (address1), std::less ())); Chris@16: vector_subiterator_type itv_end (detail::upper_bound (index1_data_.begin (), index1_data_.begin () + filled_, k_based (address1), std::less ())); Chris@16: Chris@16: subiterator_type it_begin (index2_data_.begin () + (itv_begin - index1_data_.begin ())); Chris@16: subiterator_type it_end (index2_data_.begin () + (itv_end - index1_data_.begin ())); Chris@16: Chris@16: subiterator_type it (detail::lower_bound (it_begin, it_end, k_based (address2), std::less ())); Chris@16: vector_subiterator_type itv (index1_data_.begin () + (it - index2_data_.begin ())); Chris@16: if (rank == 0) Chris@16: return iterator1 (*this, rank, i, j, itv, it); Chris@16: if (it != it_end && zero_based (*it) == address2) Chris@16: return iterator1 (*this, rank, i, j, itv, it); Chris@16: if (direction > 0) { Chris@16: if (layout_type::fast_i ()) { Chris@16: if (it == it_end) Chris@16: return iterator1 (*this, rank, i, j, itv, it); Chris@16: i = zero_based (*it); Chris@16: } else { Chris@16: if (i >= size1_) Chris@16: return iterator1 (*this, rank, i, j, itv, it); Chris@16: ++ i; Chris@16: } Chris@16: } else /* if (direction < 0) */ { Chris@16: if (layout_type::fast_i ()) { Chris@16: if (it == index2_data_.begin () + array_size_type (zero_based (*itv))) Chris@16: return iterator1 (*this, rank, i, j, itv, it); Chris@16: i = zero_based (*(it - 1)); Chris@16: } else { Chris@16: if (i == 0) Chris@16: return iterator1 (*this, rank, i, j, itv, it); Chris@16: -- i; Chris@16: } Chris@16: } Chris@16: } Chris@16: } Chris@16: // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it. Chris@16: const_iterator2 find2 (int rank, size_type i, size_type j, int direction = 1) const { Chris@16: sort (); Chris@16: for (;;) { Chris@16: size_type address1 (layout_type::index_M (i, j)); Chris@16: size_type address2 (layout_type::index_m (i, j)); Chris@16: vector_const_subiterator_type itv_begin (detail::lower_bound (index1_data_.begin (), index1_data_.begin () + filled_, k_based (address1), std::less ())); Chris@16: vector_const_subiterator_type itv_end (detail::upper_bound (index1_data_.begin (), index1_data_.begin () + filled_, k_based (address1), std::less ())); Chris@16: Chris@16: const_subiterator_type it_begin (index2_data_.begin () + (itv_begin - index1_data_.begin ())); Chris@16: const_subiterator_type it_end (index2_data_.begin () + (itv_end - index1_data_.begin ())); Chris@16: Chris@16: const_subiterator_type it (detail::lower_bound (it_begin, it_end, k_based (address2), std::less ())); Chris@16: vector_const_subiterator_type itv (index1_data_.begin () + (it - index2_data_.begin ())); Chris@16: if (rank == 0) Chris@16: return const_iterator2 (*this, rank, i, j, itv, it); Chris@16: if (it != it_end && zero_based (*it) == address2) Chris@16: return const_iterator2 (*this, rank, i, j, itv, it); Chris@16: if (direction > 0) { Chris@16: if (layout_type::fast_j ()) { Chris@16: if (it == it_end) Chris@16: return const_iterator2 (*this, rank, i, j, itv, it); Chris@16: j = zero_based (*it); Chris@16: } else { Chris@16: if (j >= size2_) Chris@16: return const_iterator2 (*this, rank, i, j, itv, it); Chris@16: ++ j; Chris@16: } Chris@16: } else /* if (direction < 0) */ { Chris@16: if (layout_type::fast_j ()) { Chris@16: if (it == index2_data_.begin () + array_size_type (zero_based (*itv))) Chris@16: return const_iterator2 (*this, rank, i, j, itv, it); Chris@16: j = zero_based (*(it - 1)); Chris@16: } else { Chris@16: if (j == 0) Chris@16: return const_iterator2 (*this, rank, i, j, itv, it); Chris@16: -- j; Chris@16: } Chris@16: } Chris@16: } Chris@16: } Chris@16: // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it. Chris@16: iterator2 find2 (int rank, size_type i, size_type j, int direction = 1) { Chris@16: sort (); Chris@16: for (;;) { Chris@16: size_type address1 (layout_type::index_M (i, j)); Chris@16: size_type address2 (layout_type::index_m (i, j)); Chris@16: vector_subiterator_type itv_begin (detail::lower_bound (index1_data_.begin (), index1_data_.begin () + filled_, k_based (address1), std::less ())); Chris@16: vector_subiterator_type itv_end (detail::upper_bound (index1_data_.begin (), index1_data_.begin () + filled_, k_based (address1), std::less ())); Chris@16: Chris@16: subiterator_type it_begin (index2_data_.begin () + (itv_begin - index1_data_.begin ())); Chris@16: subiterator_type it_end (index2_data_.begin () + (itv_end - index1_data_.begin ())); Chris@16: Chris@16: subiterator_type it (detail::lower_bound (it_begin, it_end, k_based (address2), std::less ())); Chris@16: vector_subiterator_type itv (index1_data_.begin () + (it - index2_data_.begin ())); Chris@16: if (rank == 0) Chris@16: return iterator2 (*this, rank, i, j, itv, it); Chris@16: if (it != it_end && zero_based (*it) == address2) Chris@16: return iterator2 (*this, rank, i, j, itv, it); Chris@16: if (direction > 0) { Chris@16: if (layout_type::fast_j ()) { Chris@16: if (it == it_end) Chris@16: return iterator2 (*this, rank, i, j, itv, it); Chris@16: j = zero_based (*it); Chris@16: } else { Chris@16: if (j >= size2_) Chris@16: return iterator2 (*this, rank, i, j, itv, it); Chris@16: ++ j; Chris@16: } Chris@16: } else /* if (direction < 0) */ { Chris@16: if (layout_type::fast_j ()) { Chris@16: if (it == index2_data_.begin () + array_size_type (zero_based (*itv))) Chris@16: return iterator2 (*this, rank, i, j, itv, it); Chris@16: j = zero_based (*(it - 1)); Chris@16: } else { Chris@16: if (j == 0) Chris@16: return iterator2 (*this, rank, i, j, itv, it); Chris@16: -- j; Chris@16: } Chris@16: } Chris@16: } Chris@16: } Chris@16: Chris@16: Chris@16: class const_iterator1: Chris@16: public container_const_reference, Chris@16: public bidirectional_iterator_base { Chris@16: public: Chris@16: typedef typename coordinate_matrix::value_type value_type; Chris@16: typedef typename coordinate_matrix::difference_type difference_type; Chris@16: typedef typename coordinate_matrix::const_reference reference; Chris@16: typedef const typename coordinate_matrix::pointer pointer; Chris@16: Chris@16: typedef const_iterator2 dual_iterator_type; Chris@16: typedef const_reverse_iterator2 dual_reverse_iterator_type; Chris@16: Chris@16: // Construction and destruction Chris@16: BOOST_UBLAS_INLINE Chris@16: const_iterator1 (): Chris@16: container_const_reference (), rank_ (), i_ (), j_ (), itv_ (), it_ () {} Chris@16: BOOST_UBLAS_INLINE Chris@16: const_iterator1 (const self_type &m, int rank, size_type i, size_type j, const vector_const_subiterator_type &itv, const const_subiterator_type &it): Chris@16: container_const_reference (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {} Chris@16: BOOST_UBLAS_INLINE Chris@16: const_iterator1 (const iterator1 &it): Chris@16: container_const_reference (it ()), rank_ (it.rank_), i_ (it.i_), j_ (it.j_), itv_ (it.itv_), it_ (it.it_) {} Chris@16: Chris@16: // Arithmetic Chris@16: BOOST_UBLAS_INLINE Chris@16: const_iterator1 &operator ++ () { Chris@16: if (rank_ == 1 && layout_type::fast_i ()) Chris@16: ++ it_; Chris@16: else { Chris@16: i_ = index1 () + 1; Chris@16: if (rank_ == 1) Chris@16: *this = (*this) ().find1 (rank_, i_, j_, 1); Chris@16: } Chris@16: return *this; Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: const_iterator1 &operator -- () { Chris@16: if (rank_ == 1 && layout_type::fast_i ()) Chris@16: -- it_; Chris@16: else { Chris@16: i_ = index1 () - 1; Chris@16: if (rank_ == 1) Chris@16: *this = (*this) ().find1 (rank_, i_, j_, -1); Chris@16: } Chris@16: return *this; Chris@16: } Chris@16: Chris@16: // Dereference Chris@16: BOOST_UBLAS_INLINE Chris@16: const_reference operator * () const { Chris@16: BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ()); Chris@16: BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ()); Chris@16: if (rank_ == 1) { Chris@16: return (*this) ().value_data_ [it_ - (*this) ().index2_data_.begin ()]; Chris@16: } else { Chris@16: return (*this) () (i_, j_); Chris@16: } Chris@16: } Chris@16: Chris@16: #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION Chris@16: BOOST_UBLAS_INLINE Chris@16: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@16: typename self_type:: Chris@16: #endif Chris@16: const_iterator2 begin () const { Chris@16: const self_type &m = (*this) (); Chris@16: return m.find2 (1, index1 (), 0); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@16: typename self_type:: Chris@16: #endif Chris@101: const_iterator2 cbegin () const { Chris@101: return begin (); Chris@101: } Chris@101: BOOST_UBLAS_INLINE Chris@101: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@101: typename self_type:: Chris@101: #endif Chris@16: const_iterator2 end () const { Chris@16: const self_type &m = (*this) (); Chris@16: return m.find2 (1, index1 (), m.size2 ()); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@16: typename self_type:: Chris@16: #endif Chris@101: const_iterator2 cend () const { Chris@101: return end (); Chris@101: } Chris@101: BOOST_UBLAS_INLINE Chris@101: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@101: typename self_type:: Chris@101: #endif Chris@16: const_reverse_iterator2 rbegin () const { Chris@16: return const_reverse_iterator2 (end ()); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@16: typename self_type:: Chris@16: #endif Chris@101: const_reverse_iterator2 crbegin () const { Chris@101: return rbegin (); Chris@101: } Chris@101: BOOST_UBLAS_INLINE Chris@101: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@101: typename self_type:: Chris@101: #endif Chris@16: const_reverse_iterator2 rend () const { Chris@16: return const_reverse_iterator2 (begin ()); Chris@16: } Chris@101: BOOST_UBLAS_INLINE Chris@101: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@101: typename self_type:: Chris@101: #endif Chris@101: const_reverse_iterator2 crend () const { Chris@101: return rend (); Chris@101: } Chris@16: #endif Chris@16: Chris@16: // Indices Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type index1 () const { Chris@16: BOOST_UBLAS_CHECK (*this != (*this) ().find1 (0, (*this) ().size1 (), j_), bad_index ()); Chris@16: if (rank_ == 1) { Chris@16: BOOST_UBLAS_CHECK (layout_type::index_M ((*this) ().zero_based (*itv_), (*this) ().zero_based (*it_)) < (*this) ().size1 (), bad_index ()); Chris@16: return layout_type::index_M ((*this) ().zero_based (*itv_), (*this) ().zero_based (*it_)); Chris@16: } else { Chris@16: return i_; Chris@16: } Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type index2 () const { Chris@16: if (rank_ == 1) { Chris@16: BOOST_UBLAS_CHECK (layout_type::index_m ((*this) ().zero_based (*itv_), (*this) ().zero_based (*it_)) < (*this) ().size2 (), bad_index ()); Chris@16: return layout_type::index_m ((*this) ().zero_based (*itv_), (*this) ().zero_based (*it_)); Chris@16: } else { Chris@16: return j_; Chris@16: } Chris@16: } Chris@16: Chris@16: // Assignment Chris@16: BOOST_UBLAS_INLINE Chris@16: const_iterator1 &operator = (const const_iterator1 &it) { Chris@16: container_const_reference::assign (&it ()); Chris@16: rank_ = it.rank_; Chris@16: i_ = it.i_; Chris@16: j_ = it.j_; Chris@16: itv_ = it.itv_; Chris@16: it_ = it.it_; Chris@16: return *this; Chris@16: } Chris@16: Chris@16: // Comparison Chris@16: BOOST_UBLAS_INLINE Chris@16: bool operator == (const const_iterator1 &it) const { Chris@16: BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); Chris@16: // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ()); Chris@16: if (rank_ == 1 || it.rank_ == 1) { Chris@16: return it_ == it.it_; Chris@16: } else { Chris@16: return i_ == it.i_ && j_ == it.j_; Chris@16: } Chris@16: } Chris@16: Chris@16: private: Chris@16: int rank_; Chris@16: size_type i_; Chris@16: size_type j_; Chris@16: vector_const_subiterator_type itv_; Chris@16: const_subiterator_type it_; Chris@16: }; Chris@16: Chris@16: BOOST_UBLAS_INLINE Chris@16: const_iterator1 begin1 () const { Chris@16: return find1 (0, 0, 0); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@101: const_iterator1 cbegin1 () const { Chris@101: return begin1 (); Chris@101: } Chris@101: BOOST_UBLAS_INLINE Chris@16: const_iterator1 end1 () const { Chris@16: return find1 (0, size1_, 0); Chris@16: } Chris@101: BOOST_UBLAS_INLINE Chris@101: const_iterator1 cend1 () const { Chris@101: return end1 (); Chris@101: } Chris@16: Chris@16: class iterator1: Chris@16: public container_reference, Chris@16: public bidirectional_iterator_base { Chris@16: public: Chris@16: typedef typename coordinate_matrix::value_type value_type; Chris@16: typedef typename coordinate_matrix::difference_type difference_type; Chris@16: typedef typename coordinate_matrix::true_reference reference; Chris@16: typedef typename coordinate_matrix::pointer pointer; Chris@16: Chris@16: typedef iterator2 dual_iterator_type; Chris@16: typedef reverse_iterator2 dual_reverse_iterator_type; Chris@16: Chris@16: // Construction and destruction Chris@16: BOOST_UBLAS_INLINE Chris@16: iterator1 (): Chris@16: container_reference (), rank_ (), i_ (), j_ (), itv_ (), it_ () {} Chris@16: BOOST_UBLAS_INLINE Chris@16: iterator1 (self_type &m, int rank, size_type i, size_type j, const vector_subiterator_type &itv, const subiterator_type &it): Chris@16: container_reference (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {} Chris@16: Chris@16: // Arithmetic Chris@16: BOOST_UBLAS_INLINE Chris@16: iterator1 &operator ++ () { Chris@16: if (rank_ == 1 && layout_type::fast_i ()) Chris@16: ++ it_; Chris@16: else { Chris@16: i_ = index1 () + 1; Chris@16: if (rank_ == 1) Chris@16: *this = (*this) ().find1 (rank_, i_, j_, 1); Chris@16: } Chris@16: return *this; Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: iterator1 &operator -- () { Chris@16: if (rank_ == 1 && layout_type::fast_i ()) Chris@16: -- it_; Chris@16: else { Chris@16: i_ = index1 () - 1; Chris@16: if (rank_ == 1) Chris@16: *this = (*this) ().find1 (rank_, i_, j_, -1); Chris@16: } Chris@16: return *this; Chris@16: } Chris@16: Chris@16: // Dereference Chris@16: BOOST_UBLAS_INLINE Chris@16: reference operator * () const { Chris@16: BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ()); Chris@16: BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ()); Chris@16: if (rank_ == 1) { Chris@16: return (*this) ().value_data_ [it_ - (*this) ().index2_data_.begin ()]; Chris@16: } else { Chris@16: return (*this) ().at_element (i_, j_); Chris@16: } Chris@16: } Chris@16: Chris@16: #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION Chris@16: BOOST_UBLAS_INLINE Chris@16: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@16: typename self_type:: Chris@16: #endif Chris@16: iterator2 begin () const { Chris@16: self_type &m = (*this) (); Chris@16: return m.find2 (1, index1 (), 0); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@16: typename self_type:: Chris@16: #endif Chris@16: iterator2 end () const { Chris@16: self_type &m = (*this) (); Chris@16: return m.find2 (1, index1 (), m.size2 ()); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@16: typename self_type:: Chris@16: #endif Chris@16: reverse_iterator2 rbegin () const { Chris@16: return reverse_iterator2 (end ()); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@16: typename self_type:: Chris@16: #endif Chris@16: reverse_iterator2 rend () const { Chris@16: return reverse_iterator2 (begin ()); Chris@16: } Chris@16: #endif Chris@16: Chris@16: // Indices Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type index1 () const { Chris@16: BOOST_UBLAS_CHECK (*this != (*this) ().find1 (0, (*this) ().size1 (), j_), bad_index ()); Chris@16: if (rank_ == 1) { Chris@16: BOOST_UBLAS_CHECK (layout_type::index_M ((*this) ().zero_based (*itv_), (*this) ().zero_based (*it_)) < (*this) ().size1 (), bad_index ()); Chris@16: return layout_type::index_M ((*this) ().zero_based (*itv_), (*this) ().zero_based (*it_)); Chris@16: } else { Chris@16: return i_; Chris@16: } Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type index2 () const { Chris@16: if (rank_ == 1) { Chris@16: BOOST_UBLAS_CHECK (layout_type::index_m ((*this) ().zero_based (*itv_), (*this) ().zero_based (*it_)) < (*this) ().size2 (), bad_index ()); Chris@16: return layout_type::index_m ((*this) ().zero_based (*itv_), (*this) ().zero_based (*it_)); Chris@16: } else { Chris@16: return j_; Chris@16: } Chris@16: } Chris@16: Chris@16: // Assignment Chris@16: BOOST_UBLAS_INLINE Chris@16: iterator1 &operator = (const iterator1 &it) { Chris@16: container_reference::assign (&it ()); Chris@16: rank_ = it.rank_; Chris@16: i_ = it.i_; Chris@16: j_ = it.j_; Chris@16: itv_ = it.itv_; Chris@16: it_ = it.it_; Chris@16: return *this; Chris@16: } Chris@16: Chris@16: // Comparison Chris@16: BOOST_UBLAS_INLINE Chris@16: bool operator == (const iterator1 &it) const { Chris@16: BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); Chris@16: // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ()); Chris@16: if (rank_ == 1 || it.rank_ == 1) { Chris@16: return it_ == it.it_; Chris@16: } else { Chris@16: return i_ == it.i_ && j_ == it.j_; Chris@16: } Chris@16: } Chris@16: Chris@16: private: Chris@16: int rank_; Chris@16: size_type i_; Chris@16: size_type j_; Chris@16: vector_subiterator_type itv_; Chris@16: subiterator_type it_; Chris@16: Chris@16: friend class const_iterator1; Chris@16: }; Chris@16: Chris@16: BOOST_UBLAS_INLINE Chris@16: iterator1 begin1 () { Chris@16: return find1 (0, 0, 0); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: iterator1 end1 () { Chris@16: return find1 (0, size1_, 0); Chris@16: } Chris@16: Chris@16: class const_iterator2: Chris@16: public container_const_reference, Chris@16: public bidirectional_iterator_base { Chris@16: public: Chris@16: typedef typename coordinate_matrix::value_type value_type; Chris@16: typedef typename coordinate_matrix::difference_type difference_type; Chris@16: typedef typename coordinate_matrix::const_reference reference; Chris@16: typedef const typename coordinate_matrix::pointer pointer; Chris@16: Chris@16: typedef const_iterator1 dual_iterator_type; Chris@16: typedef const_reverse_iterator1 dual_reverse_iterator_type; Chris@16: Chris@16: // Construction and destruction Chris@16: BOOST_UBLAS_INLINE Chris@16: const_iterator2 (): Chris@16: container_const_reference (), rank_ (), i_ (), j_ (), itv_ (), it_ () {} Chris@16: BOOST_UBLAS_INLINE Chris@16: const_iterator2 (const self_type &m, int rank, size_type i, size_type j, const vector_const_subiterator_type itv, const const_subiterator_type &it): Chris@16: container_const_reference (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {} Chris@16: BOOST_UBLAS_INLINE Chris@16: const_iterator2 (const iterator2 &it): Chris@16: container_const_reference (it ()), rank_ (it.rank_), i_ (it.i_), j_ (it.j_), itv_ (it.itv_), it_ (it.it_) {} Chris@16: Chris@16: // Arithmetic Chris@16: BOOST_UBLAS_INLINE Chris@16: const_iterator2 &operator ++ () { Chris@16: if (rank_ == 1 && layout_type::fast_j ()) Chris@16: ++ it_; Chris@16: else { Chris@16: j_ = index2 () + 1; Chris@16: if (rank_ == 1) Chris@16: *this = (*this) ().find2 (rank_, i_, j_, 1); Chris@16: } Chris@16: return *this; Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: const_iterator2 &operator -- () { Chris@16: if (rank_ == 1 && layout_type::fast_j ()) Chris@16: -- it_; Chris@16: else { Chris@16: j_ = index2 () - 1; Chris@16: if (rank_ == 1) Chris@16: *this = (*this) ().find2 (rank_, i_, j_, -1); Chris@16: } Chris@16: return *this; Chris@16: } Chris@16: Chris@16: // Dereference Chris@16: BOOST_UBLAS_INLINE Chris@16: const_reference operator * () const { Chris@16: BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ()); Chris@16: BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ()); Chris@16: if (rank_ == 1) { Chris@16: return (*this) ().value_data_ [it_ - (*this) ().index2_data_.begin ()]; Chris@16: } else { Chris@16: return (*this) () (i_, j_); Chris@16: } Chris@16: } Chris@16: Chris@16: #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION Chris@16: BOOST_UBLAS_INLINE Chris@16: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@16: typename self_type:: Chris@16: #endif Chris@16: const_iterator1 begin () const { Chris@16: const self_type &m = (*this) (); Chris@16: return m.find1 (1, 0, index2 ()); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@16: typename self_type:: Chris@16: #endif Chris@101: const_iterator1 cbegin () const { Chris@101: return begin (); Chris@101: } Chris@101: BOOST_UBLAS_INLINE Chris@101: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@101: typename self_type:: Chris@101: #endif Chris@16: const_iterator1 end () const { Chris@16: const self_type &m = (*this) (); Chris@16: return m.find1 (1, m.size1 (), index2 ()); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@16: typename self_type:: Chris@16: #endif Chris@101: const_iterator1 cend () const { Chris@101: return end (); Chris@101: } Chris@101: BOOST_UBLAS_INLINE Chris@101: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@101: typename self_type:: Chris@101: #endif Chris@16: const_reverse_iterator1 rbegin () const { Chris@16: return const_reverse_iterator1 (end ()); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@16: typename self_type:: Chris@16: #endif Chris@101: const_reverse_iterator1 crbegin () const { Chris@101: return rbegin (); Chris@101: } Chris@101: BOOST_UBLAS_INLINE Chris@101: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@101: typename self_type:: Chris@101: #endif Chris@16: const_reverse_iterator1 rend () const { Chris@16: return const_reverse_iterator1 (begin ()); Chris@16: } Chris@101: BOOST_UBLAS_INLINE Chris@101: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@101: typename self_type:: Chris@101: #endif Chris@101: const_reverse_iterator1 crend () const { Chris@101: return rend (); Chris@101: } Chris@16: #endif Chris@16: Chris@16: // Indices Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type index1 () const { Chris@16: if (rank_ == 1) { Chris@16: BOOST_UBLAS_CHECK (layout_type::index_M ((*this) ().zero_based (*itv_), (*this) ().zero_based (*it_)) < (*this) ().size1 (), bad_index ()); Chris@16: return layout_type::index_M ((*this) ().zero_based (*itv_), (*this) ().zero_based (*it_)); Chris@16: } else { Chris@16: return i_; Chris@16: } Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type index2 () const { Chris@16: BOOST_UBLAS_CHECK (*this != (*this) ().find2 (0, i_, (*this) ().size2 ()), bad_index ()); Chris@16: if (rank_ == 1) { Chris@16: BOOST_UBLAS_CHECK (layout_type::index_m ((*this) ().zero_based (*itv_), (*this) ().zero_based (*it_)) < (*this) ().size2 (), bad_index ()); Chris@16: return layout_type::index_m ((*this) ().zero_based (*itv_), (*this) ().zero_based (*it_)); Chris@16: } else { Chris@16: return j_; Chris@16: } Chris@16: } Chris@16: Chris@16: // Assignment Chris@16: BOOST_UBLAS_INLINE Chris@16: const_iterator2 &operator = (const const_iterator2 &it) { Chris@16: container_const_reference::assign (&it ()); Chris@16: rank_ = it.rank_; Chris@16: i_ = it.i_; Chris@16: j_ = it.j_; Chris@16: itv_ = it.itv_; Chris@16: it_ = it.it_; Chris@16: return *this; Chris@16: } Chris@16: Chris@16: // Comparison Chris@16: BOOST_UBLAS_INLINE Chris@16: bool operator == (const const_iterator2 &it) const { Chris@16: BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); Chris@16: // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ()); Chris@16: if (rank_ == 1 || it.rank_ == 1) { Chris@16: return it_ == it.it_; Chris@16: } else { Chris@16: return i_ == it.i_ && j_ == it.j_; Chris@16: } Chris@16: } Chris@16: Chris@16: private: Chris@16: int rank_; Chris@16: size_type i_; Chris@16: size_type j_; Chris@16: vector_const_subiterator_type itv_; Chris@16: const_subiterator_type it_; Chris@16: }; Chris@16: Chris@16: BOOST_UBLAS_INLINE Chris@16: const_iterator2 begin2 () const { Chris@16: return find2 (0, 0, 0); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@101: const_iterator2 cbegin2 () const { Chris@101: return begin2 (); Chris@101: } Chris@101: BOOST_UBLAS_INLINE Chris@16: const_iterator2 end2 () const { Chris@16: return find2 (0, 0, size2_); Chris@16: } Chris@101: BOOST_UBLAS_INLINE Chris@101: const_iterator2 cend2 () const { Chris@101: return end2 (); Chris@101: } Chris@16: Chris@16: class iterator2: Chris@16: public container_reference, Chris@16: public bidirectional_iterator_base { Chris@16: public: Chris@16: typedef typename coordinate_matrix::value_type value_type; Chris@16: typedef typename coordinate_matrix::difference_type difference_type; Chris@16: typedef typename coordinate_matrix::true_reference reference; Chris@16: typedef typename coordinate_matrix::pointer pointer; Chris@16: Chris@16: typedef iterator1 dual_iterator_type; Chris@16: typedef reverse_iterator1 dual_reverse_iterator_type; Chris@16: Chris@16: // Construction and destruction Chris@16: BOOST_UBLAS_INLINE Chris@16: iterator2 (): Chris@16: container_reference (), rank_ (), i_ (), j_ (), itv_ (), it_ () {} Chris@16: BOOST_UBLAS_INLINE Chris@16: iterator2 (self_type &m, int rank, size_type i, size_type j, const vector_subiterator_type &itv, const subiterator_type &it): Chris@16: container_reference (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {} Chris@16: Chris@16: // Arithmetic Chris@16: BOOST_UBLAS_INLINE Chris@16: iterator2 &operator ++ () { Chris@16: if (rank_ == 1 && layout_type::fast_j ()) Chris@16: ++ it_; Chris@16: else { Chris@16: j_ = index2 () + 1; Chris@16: if (rank_ == 1) Chris@16: *this = (*this) ().find2 (rank_, i_, j_, 1); Chris@16: } Chris@16: return *this; Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: iterator2 &operator -- () { Chris@16: if (rank_ == 1 && layout_type::fast_j ()) Chris@16: -- it_; Chris@16: else { Chris@16: j_ = index2 (); Chris@16: if (rank_ == 1) Chris@16: *this = (*this) ().find2 (rank_, i_, j_, -1); Chris@16: } Chris@16: return *this; Chris@16: } Chris@16: Chris@16: // Dereference Chris@16: BOOST_UBLAS_INLINE Chris@16: reference operator * () const { Chris@16: BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ()); Chris@16: BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ()); Chris@16: if (rank_ == 1) { Chris@16: return (*this) ().value_data_ [it_ - (*this) ().index2_data_.begin ()]; Chris@16: } else { Chris@16: return (*this) ().at_element (i_, j_); Chris@16: } Chris@16: } Chris@16: Chris@16: #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION Chris@16: BOOST_UBLAS_INLINE Chris@16: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@16: typename self_type:: Chris@16: #endif Chris@16: iterator1 begin () const { Chris@16: self_type &m = (*this) (); Chris@16: return m.find1 (1, 0, index2 ()); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@16: typename self_type:: Chris@16: #endif Chris@16: iterator1 end () const { Chris@16: self_type &m = (*this) (); Chris@16: return m.find1 (1, m.size1 (), index2 ()); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@16: typename self_type:: Chris@16: #endif Chris@16: reverse_iterator1 rbegin () const { Chris@16: return reverse_iterator1 (end ()); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION Chris@16: typename self_type:: Chris@16: #endif Chris@16: reverse_iterator1 rend () const { Chris@16: return reverse_iterator1 (begin ()); Chris@16: } Chris@16: #endif Chris@16: Chris@16: // Indices Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type index1 () const { Chris@16: if (rank_ == 1) { Chris@16: BOOST_UBLAS_CHECK (layout_type::index_M ((*this) ().zero_based (*itv_), (*this) ().zero_based (*it_)) < (*this) ().size1 (), bad_index ()); Chris@16: return layout_type::index_M ((*this) ().zero_based (*itv_), (*this) ().zero_based (*it_)); Chris@16: } else { Chris@16: return i_; Chris@16: } Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: size_type index2 () const { Chris@16: BOOST_UBLAS_CHECK (*this != (*this) ().find2 (0, i_, (*this) ().size2 ()), bad_index ()); Chris@16: if (rank_ == 1) { Chris@16: BOOST_UBLAS_CHECK (layout_type::index_m ((*this) ().zero_based (*itv_), (*this) ().zero_based (*it_)) < (*this) ().size2 (), bad_index ()); Chris@16: return layout_type::index_m ((*this) ().zero_based (*itv_), (*this) ().zero_based (*it_)); Chris@16: } else { Chris@16: return j_; Chris@16: } Chris@16: } Chris@16: Chris@16: // Assignment Chris@16: BOOST_UBLAS_INLINE Chris@16: iterator2 &operator = (const iterator2 &it) { Chris@16: container_reference::assign (&it ()); Chris@16: rank_ = it.rank_; Chris@16: i_ = it.i_; Chris@16: j_ = it.j_; Chris@16: itv_ = it.itv_; Chris@16: it_ = it.it_; Chris@16: return *this; Chris@16: } Chris@16: Chris@16: // Comparison Chris@16: BOOST_UBLAS_INLINE Chris@16: bool operator == (const iterator2 &it) const { Chris@16: BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); Chris@16: // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ()); Chris@16: if (rank_ == 1 || it.rank_ == 1) { Chris@16: return it_ == it.it_; Chris@16: } else { Chris@16: return i_ == it.i_ && j_ == it.j_; Chris@16: } Chris@16: } Chris@16: Chris@16: private: Chris@16: int rank_; Chris@16: size_type i_; Chris@16: size_type j_; Chris@16: vector_subiterator_type itv_; Chris@16: subiterator_type it_; Chris@16: Chris@16: friend class const_iterator2; Chris@16: }; Chris@16: Chris@16: BOOST_UBLAS_INLINE Chris@16: iterator2 begin2 () { Chris@16: return find2 (0, 0, 0); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: iterator2 end2 () { Chris@16: return find2 (0, 0, size2_); Chris@16: } Chris@16: Chris@16: // Reverse iterators Chris@16: Chris@16: BOOST_UBLAS_INLINE Chris@16: const_reverse_iterator1 rbegin1 () const { Chris@16: return const_reverse_iterator1 (end1 ()); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@101: const_reverse_iterator1 crbegin1 () const { Chris@101: return rbegin1 (); Chris@101: } Chris@101: BOOST_UBLAS_INLINE Chris@16: const_reverse_iterator1 rend1 () const { Chris@16: return const_reverse_iterator1 (begin1 ()); Chris@16: } Chris@101: BOOST_UBLAS_INLINE Chris@101: const_reverse_iterator1 crend1 () const { Chris@101: return rend1 (); Chris@101: } Chris@16: Chris@16: BOOST_UBLAS_INLINE Chris@16: reverse_iterator1 rbegin1 () { Chris@16: return reverse_iterator1 (end1 ()); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: reverse_iterator1 rend1 () { Chris@16: return reverse_iterator1 (begin1 ()); Chris@16: } Chris@16: Chris@16: BOOST_UBLAS_INLINE Chris@16: const_reverse_iterator2 rbegin2 () const { Chris@16: return const_reverse_iterator2 (end2 ()); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@101: const_reverse_iterator2 crbegin2 () const { Chris@101: return rbegin2 (); Chris@101: } Chris@101: BOOST_UBLAS_INLINE Chris@16: const_reverse_iterator2 rend2 () const { Chris@16: return const_reverse_iterator2 (begin2 ()); Chris@16: } Chris@101: BOOST_UBLAS_INLINE Chris@101: const_reverse_iterator2 crend2 () const { Chris@101: return rend2 (); Chris@101: } Chris@16: Chris@16: BOOST_UBLAS_INLINE Chris@16: reverse_iterator2 rbegin2 () { Chris@16: return reverse_iterator2 (end2 ()); Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: reverse_iterator2 rend2 () { Chris@16: return reverse_iterator2 (begin2 ()); Chris@16: } Chris@16: Chris@16: // Serialization Chris@16: template Chris@16: void serialize(Archive & ar, const unsigned int /* file_version */){ Chris@16: serialization::collection_size_type s1 (size1_); Chris@16: serialization::collection_size_type s2 (size2_); Chris@16: ar & serialization::make_nvp("size1",s1); Chris@16: ar & serialization::make_nvp("size2",s2); Chris@16: if (Archive::is_loading::value) { Chris@16: size1_ = s1; Chris@16: size2_ = s2; Chris@16: } Chris@16: ar & serialization::make_nvp("capacity", capacity_); Chris@16: ar & serialization::make_nvp("filled", filled_); Chris@16: ar & serialization::make_nvp("sorted_filled", sorted_filled_); Chris@16: ar & serialization::make_nvp("sorted", sorted_); Chris@16: ar & serialization::make_nvp("index1_data", index1_data_); Chris@16: ar & serialization::make_nvp("index2_data", index2_data_); Chris@16: ar & serialization::make_nvp("value_data", value_data_); Chris@16: storage_invariants(); Chris@16: } Chris@16: Chris@16: private: Chris@16: void storage_invariants () const Chris@16: { Chris@16: BOOST_UBLAS_CHECK (capacity_ == index1_data_.size (), internal_logic ()); Chris@16: BOOST_UBLAS_CHECK (capacity_ == index2_data_.size (), internal_logic ()); Chris@16: BOOST_UBLAS_CHECK (capacity_ == value_data_.size (), internal_logic ()); Chris@16: BOOST_UBLAS_CHECK (filled_ <= capacity_, internal_logic ()); Chris@16: BOOST_UBLAS_CHECK (sorted_filled_ <= filled_, internal_logic ()); Chris@16: BOOST_UBLAS_CHECK (sorted_ == (sorted_filled_ == filled_), internal_logic ()); Chris@16: } Chris@16: Chris@16: size_type size1_; Chris@16: size_type size2_; Chris@16: array_size_type capacity_; Chris@16: mutable array_size_type filled_; Chris@16: mutable array_size_type sorted_filled_; Chris@16: mutable bool sorted_; Chris@16: mutable index_array_type index1_data_; Chris@16: mutable index_array_type index2_data_; Chris@16: mutable value_array_type value_data_; Chris@16: static const value_type zero_; Chris@16: Chris@16: BOOST_UBLAS_INLINE Chris@16: static size_type zero_based (size_type k_based_index) { Chris@16: return k_based_index - IB; Chris@16: } Chris@16: BOOST_UBLAS_INLINE Chris@16: static size_type k_based (size_type zero_based_index) { Chris@16: return zero_based_index + IB; Chris@16: } Chris@16: Chris@16: friend class iterator1; Chris@16: friend class iterator2; Chris@16: friend class const_iterator1; Chris@16: friend class const_iterator2; Chris@16: }; Chris@16: Chris@16: template Chris@16: const typename coordinate_matrix::value_type coordinate_matrix::zero_ = value_type/*zero*/(); Chris@16: Chris@16: }}} Chris@16: Chris@16: #endif