x
Yes
No
Do you want to visit DriveHQ English website?
首页
产品服务
价格
免费试用
下载客户端
关于我们
云文件服务
|
云备份服务
|
FTP服务
|
企业邮箱服务
|
网站托管
|
客户端软件
云文件服务
云备份服务
FTP服务
企业级邮箱服务
网站托管
客户端软件
matrix_sparse.hpp - Hosted on DriveHQ Cloud IT Platform
返回上层目录
上传
下载
共享
发布
新建文件夹
新建文件
复制
剪切
删除
粘贴
评论
升级服务
路径: \\game3dprogramming\materials\GameFactory\GameFactoryDemo\references\boost_1_35_0\boost\numeric\ublas\matrix_sparse.hpp
旋转
特效
属性
历史版本
// // Copyright (c) 2000-2007 // Joerg Walter, Mathias Koch, Gunter Winkler // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // // The authors gratefully acknowledge the support of // GeNeSys mbH & Co. KG in producing this work. // #ifndef _BOOST_UBLAS_MATRIX_SPARSE_ #define _BOOST_UBLAS_MATRIX_SPARSE_ #include
#include
#include
#if BOOST_UBLAS_TYPE_CHECK #include
#endif // Iterators based on ideas of Jeremy Siek namespace boost { namespace numeric { namespace ublas { #ifdef BOOST_UBLAS_STRICT_MATRIX_SPARSE template
class sparse_matrix_element: public container_reference
{ public: typedef M matrix_type; typedef typename M::size_type size_type; typedef typename M::value_type value_type; typedef const value_type &const_reference; typedef value_type *pointer; typedef const value_type *const_pointer; private: // Proxied element operations void get_d () const { const_pointer p = (*this) ().find_element (i_, j_); if (p) d_ = *p; else d_ = value_type/*zero*/(); } void set (const value_type &s) const { pointer p = (*this) ().find_element (i_, j_); if (!p) (*this) ().insert_element (i_, j_, s); else *p = s; } public: // Construction and destruction BOOST_UBLAS_INLINE sparse_matrix_element (matrix_type &m, size_type i, size_type j): container_reference
(m), i_ (i), j_ (j) { } BOOST_UBLAS_INLINE sparse_matrix_element (const sparse_matrix_element &p): container_reference
(p), i_ (p.i_), j_ (p.j_) {} BOOST_UBLAS_INLINE ~sparse_matrix_element () { } // Assignment BOOST_UBLAS_INLINE sparse_matrix_element &operator = (const sparse_matrix_element &p) { // Overide the implict copy assignment p.get_d (); set (p.d_); return *this; } template
BOOST_UBLAS_INLINE sparse_matrix_element &operator = (const D &d) { set (d); return *this; } template
BOOST_UBLAS_INLINE sparse_matrix_element &operator += (const D &d) { get_d (); d_ += d; set (d_); return *this; } template
BOOST_UBLAS_INLINE sparse_matrix_element &operator -= (const D &d) { get_d (); d_ -= d; set (d_); return *this; } template
BOOST_UBLAS_INLINE sparse_matrix_element &operator *= (const D &d) { get_d (); d_ *= d; set (d_); return *this; } template
BOOST_UBLAS_INLINE sparse_matrix_element &operator /= (const D &d) { get_d (); d_ /= d; set (d_); return *this; } // Comparison template
BOOST_UBLAS_INLINE bool operator == (const D &d) const { get_d (); return d_ == d; } template
BOOST_UBLAS_INLINE bool operator != (const D &d) const { get_d (); return d_ != d; } // Conversion - weak link in proxy as d_ is not a perfect alias for the element BOOST_UBLAS_INLINE operator const_reference () const { get_d (); return d_; } // Conversion to reference - may be invalidated BOOST_UBLAS_INLINE value_type& ref () const { const pointer p = (*this) ().find_element (i_, j_); if (!p) return (*this) ().insert_element (i_, j_, value_type/*zero*/()); else return *p; } private: size_type i_; size_type j_; mutable value_type d_; }; /* * Generalise explicit reference access */ namespace detail { template
struct element_reference
> { typedef typename V::value_type& reference; static reference get_reference (const sparse_matrix_element
& sve) { return sve.ref (); } }; } template
struct type_traits
> { typedef typename M::value_type element_type; typedef type_traits
> self_type; typedef typename type_traits
::value_type value_type; typedef typename type_traits
::const_reference const_reference; typedef sparse_matrix_element
reference; typedef typename type_traits
::real_type real_type; typedef typename type_traits
::precision_type precision_type; static const unsigned plus_complexity = type_traits
::plus_complexity; static const unsigned multiplies_complexity = type_traits
::multiplies_complexity; static BOOST_UBLAS_INLINE real_type real (const_reference t) { return type_traits
::real (t); } static BOOST_UBLAS_INLINE real_type imag (const_reference t) { return type_traits
::imag (t); } static BOOST_UBLAS_INLINE value_type conj (const_reference t) { return type_traits
::conj (t); } static BOOST_UBLAS_INLINE real_type type_abs (const_reference t) { return type_traits
::type_abs (t); } static BOOST_UBLAS_INLINE value_type type_sqrt (const_reference t) { return type_traits
::type_sqrt (t); } static BOOST_UBLAS_INLINE real_type norm_1 (const_reference t) { return type_traits
::norm_1 (t); } static BOOST_UBLAS_INLINE real_type norm_2 (const_reference t) { return type_traits
::norm_2 (t); } static BOOST_UBLAS_INLINE real_type norm_inf (const_reference t) { return type_traits
::norm_inf (t); } static BOOST_UBLAS_INLINE bool equals (const_reference t1, const_reference t2) { return type_traits
::equals (t1, t2); } }; template
struct promote_traits
, T2> { typedef typename promote_traits
::value_type, T2>::promote_type promote_type; }; template
struct promote_traits
> { typedef typename promote_traits
::value_type>::promote_type promote_type; }; template
struct promote_traits
, sparse_matrix_element
> { typedef typename promote_traits
::value_type, typename sparse_matrix_element
::value_type>::promote_type promote_type; }; #endif // Index map based sparse matrix class template
class mapped_matrix: public matrix_container
> { typedef T &true_reference; typedef T *pointer; typedef const T * const_pointer; typedef L layout_type; typedef mapped_matrix
self_type; public: #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS using matrix_container
::operator (); #endif typedef typename A::size_type size_type; typedef typename A::difference_type difference_type; typedef T value_type; typedef A array_type; typedef const T &const_reference; #ifndef BOOST_UBLAS_STRICT_MATRIX_SPARSE typedef typename detail::map_traits
::reference reference; #else typedef sparse_matrix_element
reference; #endif typedef const matrix_reference
const_closure_type; typedef matrix_reference
closure_type; typedef mapped_vector
vector_temporary_type; typedef self_type matrix_temporary_type; typedef sparse_tag storage_category; typedef typename L::orientation_category orientation_category; // Construction and destruction BOOST_UBLAS_INLINE mapped_matrix (): matrix_container
(), size1_ (0), size2_ (0), data_ () {} BOOST_UBLAS_INLINE mapped_matrix (size_type size1, size_type size2, size_type non_zeros = 0): matrix_container
(), size1_ (size1), size2_ (size2), data_ () { detail::map_reserve (data (), restrict_capacity (non_zeros)); } BOOST_UBLAS_INLINE mapped_matrix (const mapped_matrix &m): matrix_container
(), size1_ (m.size1_), size2_ (m.size2_), data_ (m.data_) {} template
BOOST_UBLAS_INLINE mapped_matrix (const matrix_expression
&ae, size_type non_zeros = 0): matrix_container
(), size1_ (ae ().size1 ()), size2_ (ae ().size2 ()), data_ () { detail::map_reserve (data (), restrict_capacity (non_zeros)); matrix_assign
(*this, ae); } // Accessors BOOST_UBLAS_INLINE size_type size1 () const { return size1_; } BOOST_UBLAS_INLINE size_type size2 () const { return size2_; } BOOST_UBLAS_INLINE size_type nnz_capacity () const { return detail::map_capacity (data ()); } BOOST_UBLAS_INLINE size_type nnz () const { return data (). size (); } // Storage accessors BOOST_UBLAS_INLINE const array_type &data () const { return data_; } BOOST_UBLAS_INLINE array_type &data () { return data_; } // Resizing private: BOOST_UBLAS_INLINE size_type restrict_capacity (size_type non_zeros) const { // Guarding against overflow - thanks to Alexei Novakov for the hint. // non_zeros = (std::min) (non_zeros, size1_ * size2_); if (size1_ > 0 && non_zeros / size1_ >= size2_) non_zeros = size1_ * size2_; return non_zeros; } public: BOOST_UBLAS_INLINE void resize (size_type size1, size_type size2, bool preserve = true) { // FIXME preserve unimplemented BOOST_UBLAS_CHECK (!preserve, internal_logic ()); size1_ = size1; size2_ = size2; data ().clear (); } // Reserving BOOST_UBLAS_INLINE void reserve (size_type non_zeros, bool preserve = true) { detail::map_reserve (data (), restrict_capacity (non_zeros)); } // Element support BOOST_UBLAS_INLINE pointer find_element (size_type i, size_type j) { return const_cast
(const_cast
(*this).find_element (i, j)); } BOOST_UBLAS_INLINE const_pointer find_element (size_type i, size_type j) const { const size_type element = layout_type::element (i, size1_, j, size2_); const_subiterator_type it (data ().find (element)); if (it == data ().end ()) return 0; BOOST_UBLAS_CHECK ((*it).first == element, internal_logic ()); // broken map return &(*it).second; } // Element access BOOST_UBLAS_INLINE const_reference operator () (size_type i, size_type j) const { const size_type element = layout_type::element (i, size1_, j, size2_); const_subiterator_type it (data ().find (element)); if (it == data ().end ()) return zero_; BOOST_UBLAS_CHECK ((*it).first == element, internal_logic ()); // broken map return (*it).second; } BOOST_UBLAS_INLINE reference operator () (size_type i, size_type j) { #ifndef BOOST_UBLAS_STRICT_MATRIX_SPARSE const size_type element = layout_type::element (i, size1_, j, size2_); std::pair
ii (data ().insert (typename array_type::value_type (element, value_type/*zero*/()))); BOOST_UBLAS_CHECK ((ii.first)->first == element, internal_logic ()); // broken map return (ii.first)->second; #else return reference (*this, i, j); #endif } // Element assingment BOOST_UBLAS_INLINE true_reference insert_element (size_type i, size_type j, const_reference t) { BOOST_UBLAS_CHECK (!find_element (i, j), bad_index ()); // duplicate element const size_type element = layout_type::element (i, size1_, j, size2_); std::pair
ii (data ().insert (typename array_type::value_type (element, t))); BOOST_UBLAS_CHECK ((ii.first)->first == element, internal_logic ()); // broken map if (!ii.second) // existing element (ii.first)->second = t; return (ii.first)->second; } BOOST_UBLAS_INLINE void erase_element (size_type i, size_type j) { subiterator_type it = data ().find (layout_type::element (i, size1_, j, size2_)); if (it == data ().end ()) return; data ().erase (it); } // Zeroing BOOST_UBLAS_INLINE void clear () { data ().clear (); } // Assignment BOOST_UBLAS_INLINE mapped_matrix &operator = (const mapped_matrix &m) { if (this != &m) { size1_ = m.size1_; size2_ = m.size2_; data () = m.data (); } return *this; } template
// Container assignment without temporary BOOST_UBLAS_INLINE mapped_matrix &operator = (const matrix_container
&m) { resize (m ().size1 (), m ().size2 (), false); assign (m); return *this; } BOOST_UBLAS_INLINE mapped_matrix &assign_temporary (mapped_matrix &m) { swap (m); return *this; } template
BOOST_UBLAS_INLINE mapped_matrix &operator = (const matrix_expression
&ae) { self_type temporary (ae, detail::map_capacity (data ())); return assign_temporary (temporary); } template
BOOST_UBLAS_INLINE mapped_matrix &assign (const matrix_expression
&ae) { matrix_assign
(*this, ae); return *this; } template
BOOST_UBLAS_INLINE mapped_matrix& operator += (const matrix_expression
&ae) { self_type temporary (*this + ae, detail::map_capacity (data ())); return assign_temporary (temporary); } template
// Container assignment without temporary BOOST_UBLAS_INLINE mapped_matrix &operator += (const matrix_container
&m) { plus_assign (m); return *this; } template
BOOST_UBLAS_INLINE mapped_matrix &plus_assign (const matrix_expression
&ae) { matrix_assign
(*this, ae); return *this; } template
BOOST_UBLAS_INLINE mapped_matrix& operator -= (const matrix_expression
&ae) { self_type temporary (*this - ae, detail::map_capacity (data ())); return assign_temporary (temporary); } template
// Container assignment without temporary BOOST_UBLAS_INLINE mapped_matrix &operator -= (const matrix_container
&m) { minus_assign (m); return *this; } template
BOOST_UBLAS_INLINE mapped_matrix &minus_assign (const matrix_expression
&ae) { matrix_assign
(*this, ae); return *this; } template
BOOST_UBLAS_INLINE mapped_matrix& operator *= (const AT &at) { matrix_assign_scalar
(*this, at); return *this; } template
BOOST_UBLAS_INLINE mapped_matrix& operator /= (const AT &at) { matrix_assign_scalar
(*this, at); return *this; } // Swapping BOOST_UBLAS_INLINE void swap (mapped_matrix &m) { if (this != &m) { std::swap (size1_, m.size1_); std::swap (size2_, m.size2_); data ().swap (m.data ()); } } BOOST_UBLAS_INLINE friend void swap (mapped_matrix &m1, mapped_matrix &m2) { m1.swap (m2); } // Iterator types private: // Use storage iterator typedef typename A::const_iterator const_subiterator_type; typedef typename A::iterator subiterator_type; BOOST_UBLAS_INLINE true_reference at_element (size_type i, size_type j) { const size_type element = layout_type::element (i, size1_, j, size2_); subiterator_type it (data ().find (element)); BOOST_UBLAS_CHECK (it != data ().end(), bad_index ()); BOOST_UBLAS_CHECK ((*it).first == element, internal_logic ()); // broken map return it->second; } public: class const_iterator1; class iterator1; class const_iterator2; class iterator2; typedef reverse_iterator_base1
const_reverse_iterator1; typedef reverse_iterator_base1
reverse_iterator1; typedef reverse_iterator_base2
const_reverse_iterator2; typedef reverse_iterator_base2
reverse_iterator2; // Element lookup // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it. const_iterator1 find1 (int rank, size_type i, size_type j, int direction = 1) const { const_subiterator_type it (data ().lower_bound (layout_type::address (i, size1_, j, size2_))); const_subiterator_type it_end (data ().end ()); size_type index1 = size_type (-1); size_type index2 = size_type (-1); while (rank == 1 && it != it_end) { index1 = layout_type::index_i ((*it).first, size1_, size2_); index2 = layout_type::index_j ((*it).first, size1_, size2_); if (direction > 0) { if ((index1 >= i && index2 == j) || (i >= size1_)) break; ++ i; } else /* if (direction < 0) */ { if ((index1 <= i && index2 == j) || (i == 0)) break; -- i; } it = data ().lower_bound (layout_type::address (i, size1_, j, size2_)); } if (rank == 1 && index2 != j) { if (direction > 0) i = size1_; else /* if (direction < 0) */ i = 0; rank = 0; } return const_iterator1 (*this, rank, i, j, it); } // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it. iterator1 find1 (int rank, size_type i, size_type j, int direction = 1) { subiterator_type it (data ().lower_bound (layout_type::address (i, size1_, j, size2_))); subiterator_type it_end (data ().end ()); size_type index1 = size_type (-1); size_type index2 = size_type (-1); while (rank == 1 && it != it_end) { index1 = layout_type::index_i ((*it).first, size1_, size2_); index2 = layout_type::index_j ((*it).first, size1_, size2_); if (direction > 0) { if ((index1 >= i && index2 == j) || (i >= size1_)) break; ++ i; } else /* if (direction < 0) */ { if ((index1 <= i && index2 == j) || (i == 0)) break; -- i; } it = data ().lower_bound (layout_type::address (i, size1_, j, size2_)); } if (rank == 1 && index2 != j) { if (direction > 0) i = size1_; else /* if (direction < 0) */ i = 0; rank = 0; } return iterator1 (*this, rank, i, j, it); } // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it. const_iterator2 find2 (int rank, size_type i, size_type j, int direction = 1) const { const_subiterator_type it (data ().lower_bound (layout_type::address (i, size1_, j, size2_))); const_subiterator_type it_end (data ().end ()); size_type index1 = size_type (-1); size_type index2 = size_type (-1); while (rank == 1 && it != it_end) { index1 = layout_type::index_i ((*it).first, size1_, size2_); index2 = layout_type::index_j ((*it).first, size1_, size2_); if (direction > 0) { if ((index2 >= j && index1 == i) || (j >= size2_)) break; ++ j; } else /* if (direction < 0) */ { if ((index2 <= j && index1 == i) || (j == 0)) break; -- j; } it = data ().lower_bound (layout_type::address (i, size1_, j, size2_)); } if (rank == 1 && index1 != i) { if (direction > 0) j = size2_; else /* if (direction < 0) */ j = 0; rank = 0; } return const_iterator2 (*this, rank, i, j, it); } // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it. iterator2 find2 (int rank, size_type i, size_type j, int direction = 1) { subiterator_type it (data ().lower_bound (layout_type::address (i, size1_, j, size2_))); subiterator_type it_end (data ().end ()); size_type index1 = size_type (-1); size_type index2 = size_type (-1); while (rank == 1 && it != it_end) { index1 = layout_type::index_i ((*it).first, size1_, size2_); index2 = layout_type::index_j ((*it).first, size1_, size2_); if (direction > 0) { if ((index2 >= j && index1 == i) || (j >= size2_)) break; ++ j; } else /* if (direction < 0) */ { if ((index2 <= j && index1 == i) || (j == 0)) break; -- j; } it = data ().lower_bound (layout_type::address (i, size1_, j, size2_)); } if (rank == 1 && index1 != i) { if (direction > 0) j = size2_; else /* if (direction < 0) */ j = 0; rank = 0; } return iterator2 (*this, rank, i, j, it); } class const_iterator1: public container_const_reference
, public bidirectional_iterator_base
{ public: typedef typename mapped_matrix::value_type value_type; typedef typename mapped_matrix::difference_type difference_type; typedef typename mapped_matrix::const_reference reference; typedef const typename mapped_matrix::pointer pointer; typedef const_iterator2 dual_iterator_type; typedef const_reverse_iterator2 dual_reverse_iterator_type; // Construction and destruction BOOST_UBLAS_INLINE const_iterator1 (): container_const_reference
(), rank_ (), i_ (), j_ (), it_ () {} BOOST_UBLAS_INLINE const_iterator1 (const self_type &m, int rank, size_type i, size_type j, const const_subiterator_type &it): container_const_reference
(m), rank_ (rank), i_ (i), j_ (j), it_ (it) {} BOOST_UBLAS_INLINE const_iterator1 (const iterator1 &it): container_const_reference
(it ()), rank_ (it.rank_), i_ (it.i_), j_ (it.j_), it_ (it.it_) {} // Arithmetic BOOST_UBLAS_INLINE const_iterator1 &operator ++ () { if (rank_ == 1 && layout_type::fast_i ()) ++ it_; else *this = (*this) ().find1 (rank_, index1 () + 1, j_, 1); return *this; } BOOST_UBLAS_INLINE const_iterator1 &operator -- () { if (rank_ == 1 && layout_type::fast_i ()) -- it_; else *this = (*this) ().find1 (rank_, index1 () - 1, j_, -1); return *this; } // Dereference BOOST_UBLAS_INLINE const_reference operator * () const { BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ()); BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ()); if (rank_ == 1) { return (*it_).second; } else { return (*this) () (i_, j_); } } #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_iterator2 begin () const { const self_type &m = (*this) (); return m.find2 (1, index1 (), 0); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_iterator2 end () const { const self_type &m = (*this) (); return m.find2 (1, index1 (), m.size2 ()); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator2 rbegin () const { return const_reverse_iterator2 (end ()); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator2 rend () const { return const_reverse_iterator2 (begin ()); } #endif // Indices BOOST_UBLAS_INLINE size_type index1 () const { BOOST_UBLAS_CHECK (*this != (*this) ().find1 (0, (*this) ().size1 (), j_), bad_index ()); if (rank_ == 1) { const self_type &m = (*this) (); BOOST_UBLAS_CHECK (layout_type::index_i ((*it_).first, m.size1 (), m.size2 ()) < (*this) ().size1 (), bad_index ()); return layout_type::index_i ((*it_).first, m.size1 (), m.size2 ()); } else { return i_; } } BOOST_UBLAS_INLINE size_type index2 () const { if (rank_ == 1) { const self_type &m = (*this) (); BOOST_UBLAS_CHECK (layout_type::index_j ((*it_).first, m.size1 (), m.size2 ()) < (*this) ().size2 (), bad_index ()); return layout_type::index_j ((*it_).first, m.size1 (), m.size2 ()); } else { return j_; } } // Assignment BOOST_UBLAS_INLINE const_iterator1 &operator = (const const_iterator1 &it) { container_const_reference
::assign (&it ()); rank_ = it.rank_; i_ = it.i_; j_ = it.j_; it_ = it.it_; return *this; } // Comparison BOOST_UBLAS_INLINE bool operator == (const const_iterator1 &it) const { BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ()); if (rank_ == 1 || it.rank_ == 1) { return it_ == it.it_; } else { return i_ == it.i_ && j_ == it.j_; } } private: int rank_; size_type i_; size_type j_; const_subiterator_type it_; }; BOOST_UBLAS_INLINE const_iterator1 begin1 () const { return find1 (0, 0, 0); } BOOST_UBLAS_INLINE const_iterator1 end1 () const { return find1 (0, size1_, 0); } class iterator1: public container_reference
, public bidirectional_iterator_base
{ public: typedef typename mapped_matrix::value_type value_type; typedef typename mapped_matrix::difference_type difference_type; typedef typename mapped_matrix::true_reference reference; typedef typename mapped_matrix::pointer pointer; typedef iterator2 dual_iterator_type; typedef reverse_iterator2 dual_reverse_iterator_type; // Construction and destruction BOOST_UBLAS_INLINE iterator1 (): container_reference
(), rank_ (), i_ (), j_ (), it_ () {} BOOST_UBLAS_INLINE iterator1 (self_type &m, int rank, size_type i, size_type j, const subiterator_type &it): container_reference
(m), rank_ (rank), i_ (i), j_ (j), it_ (it) {} // Arithmetic BOOST_UBLAS_INLINE iterator1 &operator ++ () { if (rank_ == 1 && layout_type::fast_i ()) ++ it_; else *this = (*this) ().find1 (rank_, index1 () + 1, j_, 1); return *this; } BOOST_UBLAS_INLINE iterator1 &operator -- () { if (rank_ == 1 && layout_type::fast_i ()) -- it_; else *this = (*this) ().find1 (rank_, index1 () - 1, j_, -1); return *this; } // Dereference BOOST_UBLAS_INLINE reference operator * () const { BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ()); BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ()); if (rank_ == 1) { return (*it_).second; } else { return (*this) ().at_element (i_, j_); } } #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif iterator2 begin () const { self_type &m = (*this) (); return m.find2 (1, index1 (), 0); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif iterator2 end () const { self_type &m = (*this) (); return m.find2 (1, index1 (), m.size2 ()); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif reverse_iterator2 rbegin () const { return reverse_iterator2 (end ()); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif reverse_iterator2 rend () const { return reverse_iterator2 (begin ()); } #endif // Indices BOOST_UBLAS_INLINE size_type index1 () const { BOOST_UBLAS_CHECK (*this != (*this) ().find1 (0, (*this) ().size1 (), j_), bad_index ()); if (rank_ == 1) { const self_type &m = (*this) (); BOOST_UBLAS_CHECK (layout_type::index_i ((*it_).first, m.size1 (), m.size2 ()) < (*this) ().size1 (), bad_index ()); return layout_type::index_i ((*it_).first, m.size1 (), m.size2 ()); } else { return i_; } } BOOST_UBLAS_INLINE size_type index2 () const { if (rank_ == 1) { const self_type &m = (*this) (); BOOST_UBLAS_CHECK (layout_type::index_j ((*it_).first, m.size1 (), m.size2 ()) < (*this) ().size2 (), bad_index ()); return layout_type::index_j ((*it_).first, m.size1 (), m.size2 ()); } else { return j_; } } // Assignment BOOST_UBLAS_INLINE iterator1 &operator = (const iterator1 &it) { container_reference
::assign (&it ()); rank_ = it.rank_; i_ = it.i_; j_ = it.j_; it_ = it.it_; return *this; } // Comparison BOOST_UBLAS_INLINE bool operator == (const iterator1 &it) const { BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ()); if (rank_ == 1 || it.rank_ == 1) { return it_ == it.it_; } else { return i_ == it.i_ && j_ == it.j_; } } private: int rank_; size_type i_; size_type j_; subiterator_type it_; friend class const_iterator1; }; BOOST_UBLAS_INLINE iterator1 begin1 () { return find1 (0, 0, 0); } BOOST_UBLAS_INLINE iterator1 end1 () { return find1 (0, size1_, 0); } class const_iterator2: public container_const_reference
, public bidirectional_iterator_base
{ public: typedef typename mapped_matrix::value_type value_type; typedef typename mapped_matrix::difference_type difference_type; typedef typename mapped_matrix::const_reference reference; typedef const typename mapped_matrix::pointer pointer; typedef const_iterator1 dual_iterator_type; typedef const_reverse_iterator1 dual_reverse_iterator_type; // Construction and destruction BOOST_UBLAS_INLINE const_iterator2 (): container_const_reference
(), rank_ (), i_ (), j_ (), it_ () {} BOOST_UBLAS_INLINE const_iterator2 (const self_type &m, int rank, size_type i, size_type j, const const_subiterator_type &it): container_const_reference
(m), rank_ (rank), i_ (i), j_ (j), it_ (it) {} BOOST_UBLAS_INLINE const_iterator2 (const iterator2 &it): container_const_reference
(it ()), rank_ (it.rank_), i_ (it.i_), j_ (it.j_), it_ (it.it_) {} // Arithmetic BOOST_UBLAS_INLINE const_iterator2 &operator ++ () { if (rank_ == 1 && layout_type::fast_j ()) ++ it_; else *this = (*this) ().find2 (rank_, i_, index2 () + 1, 1); return *this; } BOOST_UBLAS_INLINE const_iterator2 &operator -- () { if (rank_ == 1 && layout_type::fast_j ()) -- it_; else *this = (*this) ().find2 (rank_, i_, index2 () - 1, -1); return *this; } // Dereference BOOST_UBLAS_INLINE const_reference operator * () const { BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ()); BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ()); if (rank_ == 1) { return (*it_).second; } else { return (*this) () (i_, j_); } } #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_iterator1 begin () const { const self_type &m = (*this) (); return m.find1 (1, 0, index2 ()); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_iterator1 end () const { const self_type &m = (*this) (); return m.find1 (1, m.size1 (), index2 ()); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator1 rbegin () const { return const_reverse_iterator1 (end ()); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator1 rend () const { return const_reverse_iterator1 (begin ()); } #endif // Indices BOOST_UBLAS_INLINE size_type index1 () const { if (rank_ == 1) { const self_type &m = (*this) (); BOOST_UBLAS_CHECK (layout_type::index_i ((*it_).first, m.size1 (), m.size2 ()) < (*this) ().size1 (), bad_index ()); return layout_type::index_i ((*it_).first, m.size1 (), m.size2 ()); } else { return i_; } } BOOST_UBLAS_INLINE size_type index2 () const { BOOST_UBLAS_CHECK (*this != (*this) ().find2 (0, i_, (*this) ().size2 ()), bad_index ()); if (rank_ == 1) { const self_type &m = (*this) (); BOOST_UBLAS_CHECK (layout_type::index_j ((*it_).first, m.size1 (), m.size2 ()) < (*this) ().size2 (), bad_index ()); return layout_type::index_j ((*it_).first, m.size1 (), m.size2 ()); } else { return j_; } } // Assignment BOOST_UBLAS_INLINE const_iterator2 &operator = (const const_iterator2 &it) { container_const_reference
::assign (&it ()); rank_ = it.rank_; i_ = it.i_; j_ = it.j_; it_ = it.it_; return *this; } // Comparison BOOST_UBLAS_INLINE bool operator == (const const_iterator2 &it) const { BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ()); if (rank_ == 1 || it.rank_ == 1) { return it_ == it.it_; } else { return i_ == it.i_ && j_ == it.j_; } } private: int rank_; size_type i_; size_type j_; const_subiterator_type it_; }; BOOST_UBLAS_INLINE const_iterator2 begin2 () const { return find2 (0, 0, 0); } BOOST_UBLAS_INLINE const_iterator2 end2 () const { return find2 (0, 0, size2_); } class iterator2: public container_reference
, public bidirectional_iterator_base
{ public: typedef typename mapped_matrix::value_type value_type; typedef typename mapped_matrix::difference_type difference_type; typedef typename mapped_matrix::true_reference reference; typedef typename mapped_matrix::pointer pointer; typedef iterator1 dual_iterator_type; typedef reverse_iterator1 dual_reverse_iterator_type; // Construction and destruction BOOST_UBLAS_INLINE iterator2 (): container_reference
(), rank_ (), i_ (), j_ (), it_ () {} BOOST_UBLAS_INLINE iterator2 (self_type &m, int rank, size_type i, size_type j, const subiterator_type &it): container_reference
(m), rank_ (rank), i_ (i), j_ (j), it_ (it) {} // Arithmetic BOOST_UBLAS_INLINE iterator2 &operator ++ () { if (rank_ == 1 && layout_type::fast_j ()) ++ it_; else *this = (*this) ().find2 (rank_, i_, index2 () + 1, 1); return *this; } BOOST_UBLAS_INLINE iterator2 &operator -- () { if (rank_ == 1 && layout_type::fast_j ()) -- it_; else *this = (*this) ().find2 (rank_, i_, index2 () - 1, -1); return *this; } // Dereference BOOST_UBLAS_INLINE reference operator * () const { BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ()); BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ()); if (rank_ == 1) { return (*it_).second; } else { return (*this) ().at_element (i_, j_); } } #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif iterator1 begin () const { self_type &m = (*this) (); return m.find1 (1, 0, index2 ()); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif iterator1 end () const { self_type &m = (*this) (); return m.find1 (1, m.size1 (), index2 ()); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif reverse_iterator1 rbegin () const { return reverse_iterator1 (end ()); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif reverse_iterator1 rend () const { return reverse_iterator1 (begin ()); } #endif // Indices BOOST_UBLAS_INLINE size_type index1 () const { if (rank_ == 1) { const self_type &m = (*this) (); BOOST_UBLAS_CHECK (layout_type::index_i ((*it_).first, m.size1 (), m.size2 ()) < (*this) ().size1 (), bad_index ()); return layout_type::index_i ((*it_).first, m.size1 (), m.size2 ()); } else { return i_; } } BOOST_UBLAS_INLINE size_type index2 () const { BOOST_UBLAS_CHECK (*this != (*this) ().find2 (0, i_, (*this) ().size2 ()), bad_index ()); if (rank_ == 1) { const self_type &m = (*this) (); BOOST_UBLAS_CHECK (layout_type::index_j ((*it_).first, m.size1 (), m.size2 ()) < (*this) ().size2 (), bad_index ()); return layout_type::index_j ((*it_).first, m.size1 (), m.size2 ()); } else { return j_; } } // Assignment BOOST_UBLAS_INLINE iterator2 &operator = (const iterator2 &it) { container_reference
::assign (&it ()); rank_ = it.rank_; i_ = it.i_; j_ = it.j_; it_ = it.it_; return *this; } // Comparison BOOST_UBLAS_INLINE bool operator == (const iterator2 &it) const { BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ()); if (rank_ == 1 || it.rank_ == 1) { return it_ == it.it_; } else { return i_ == it.i_ && j_ == it.j_; } } private: int rank_; size_type i_; size_type j_; subiterator_type it_; friend class const_iterator2; }; BOOST_UBLAS_INLINE iterator2 begin2 () { return find2 (0, 0, 0); } BOOST_UBLAS_INLINE iterator2 end2 () { return find2 (0, 0, size2_); } // Reverse iterators BOOST_UBLAS_INLINE const_reverse_iterator1 rbegin1 () const { return const_reverse_iterator1 (end1 ()); } BOOST_UBLAS_INLINE const_reverse_iterator1 rend1 () const { return const_reverse_iterator1 (begin1 ()); } BOOST_UBLAS_INLINE reverse_iterator1 rbegin1 () { return reverse_iterator1 (end1 ()); } BOOST_UBLAS_INLINE reverse_iterator1 rend1 () { return reverse_iterator1 (begin1 ()); } BOOST_UBLAS_INLINE const_reverse_iterator2 rbegin2 () const { return const_reverse_iterator2 (end2 ()); } BOOST_UBLAS_INLINE const_reverse_iterator2 rend2 () const { return const_reverse_iterator2 (begin2 ()); } BOOST_UBLAS_INLINE reverse_iterator2 rbegin2 () { return reverse_iterator2 (end2 ()); } BOOST_UBLAS_INLINE reverse_iterator2 rend2 () { return reverse_iterator2 (begin2 ()); } // Serialization template
void serialize(Archive & ar, const unsigned int /* file_version */){ serialization::collection_size_type s1 (size1_); serialization::collection_size_type s2 (size2_); ar & serialization::make_nvp("size1",s1); ar & serialization::make_nvp("size2",s2); if (Archive::is_loading::value) { size1_ = s1; size2_ = s2; } ar & serialization::make_nvp("data", data_); } private: size_type size1_; size_type size2_; array_type data_; static const value_type zero_; }; template
const typename mapped_matrix
::value_type mapped_matrix
::zero_ = value_type/*zero*/(); // Vector index map based sparse matrix class template
class mapped_vector_of_mapped_vector: public matrix_container
> { typedef T &true_reference; typedef T *pointer; typedef const T *const_pointer; typedef A array_type; typedef const A const_array_type; typedef L layout_type; typedef mapped_vector_of_mapped_vector
self_type; public: #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS using matrix_container
::operator (); #endif typedef typename A::size_type size_type; typedef typename A::difference_type difference_type; typedef T value_type; typedef const T &const_reference; #ifndef BOOST_UBLAS_STRICT_MATRIX_SPARSE typedef typename detail::map_traits
::reference reference; #else typedef sparse_matrix_element
reference; #endif typedef const matrix_reference
const_closure_type; typedef matrix_reference
closure_type; typedef mapped_vector
vector_temporary_type; typedef self_type matrix_temporary_type; typedef typename A::value_type::second_type vector_data_value_type; typedef sparse_tag storage_category; typedef typename L::orientation_category orientation_category; // Construction and destruction BOOST_UBLAS_INLINE mapped_vector_of_mapped_vector (): matrix_container
(), size1_ (0), size2_ (0), data_ () { data_ [layout_type::size_M (size1_, size2_)] = vector_data_value_type (); } BOOST_UBLAS_INLINE mapped_vector_of_mapped_vector (size_type size1, size_type size2, size_type non_zeros = 0): matrix_container
(), size1_ (size1), size2_ (size2), data_ () { data_ [layout_type::size_M (size1_, size2_)] = vector_data_value_type (); } BOOST_UBLAS_INLINE mapped_vector_of_mapped_vector (const mapped_vector_of_mapped_vector &m): matrix_container
(), size1_ (m.size1_), size2_ (m.size2_), data_ (m.data_) {} template
BOOST_UBLAS_INLINE mapped_vector_of_mapped_vector (const matrix_expression
&ae, size_type non_zeros = 0): matrix_container
(), size1_ (ae ().size1 ()), size2_ (ae ().size2 ()), data_ () { data_ [layout_type::size_M (size1_, size2_)] = vector_data_value_type (); matrix_assign
(*this, ae); } // Accessors BOOST_UBLAS_INLINE size_type size1 () const { return size1_; } BOOST_UBLAS_INLINE size_type size2 () const { return size2_; } BOOST_UBLAS_INLINE size_type nnz_capacity () const { size_type non_zeros = 0; for (vector_const_subiterator_type itv = data_ ().begin (); itv != data_ ().end (); ++ itv) non_zeros += detail::map_capacity (*itv); return non_zeros; } BOOST_UBLAS_INLINE size_type nnz () const { size_type filled = 0; for (vector_const_subiterator_type itv = data_ ().begin (); itv != data_ ().end (); ++ itv) filled += (*itv).size (); return filled; } // Storage accessors BOOST_UBLAS_INLINE const_array_type &data () const { return data_; } BOOST_UBLAS_INLINE array_type &data () { return data_; } // Resizing BOOST_UBLAS_INLINE void resize (size_type size1, size_type size2, bool preserve = true) { // FIXME preserve unimplemented BOOST_UBLAS_CHECK (!preserve, internal_logic ()); size1_ = size1; size2_ = size2; data ().clear (); data () [layout_type::size_M (size1_, size2_)] = vector_data_value_type (); } // Element support BOOST_UBLAS_INLINE pointer find_element (size_type i, size_type j) { return const_cast
(const_cast
(*this).find_element (i, j)); } BOOST_UBLAS_INLINE const_pointer find_element (size_type i, size_type j) const { const size_type element1 = layout_type::index_M (i, j); const size_type element2 = layout_type::index_m (i, j); vector_const_subiterator_type itv (data ().find (element1)); if (itv == data ().end ()) return 0; BOOST_UBLAS_CHECK ((*itv).first == element1, internal_logic ()); // broken map const_subiterator_type it ((*itv).second.find (element2)); if (it == (*itv).second.end ()) return 0; BOOST_UBLAS_CHECK ((*it).first == element2, internal_logic ()); // broken map return &(*it).second; } // Element access BOOST_UBLAS_INLINE const_reference operator () (size_type i, size_type j) const { const size_type element1 = layout_type::index_M (i, j); const size_type element2 = layout_type::index_m (i, j); vector_const_subiterator_type itv (data ().find (element1)); if (itv == data ().end ()) return zero_; BOOST_UBLAS_CHECK ((*itv).first == element1, internal_logic ()); // broken map const_subiterator_type it ((*itv).second.find (element2)); if (it == (*itv).second.end ()) return zero_; BOOST_UBLAS_CHECK ((*itv).first == element1, internal_logic ()); // broken map return (*it).second; } BOOST_UBLAS_INLINE reference operator () (size_type i, size_type j) { #ifndef BOOST_UBLAS_STRICT_MATRIX_SPARSE const size_type element1 = layout_type::index_M (i, j); const size_type element2 = layout_type::index_m (i, j); vector_data_value_type& vd (data () [element1]); std::pair
ii (vd.insert (typename array_type::value_type::second_type::value_type (element2, value_type/*zero*/()))); BOOST_UBLAS_CHECK ((ii.first)->first == element2, internal_logic ()); // broken map return (ii.first)->second; #else return reference (*this, i, j); #endif } // Element assignment BOOST_UBLAS_INLINE true_reference insert_element (size_type i, size_type j, const_reference t) { BOOST_UBLAS_CHECK (!find_element (i, j), bad_index ()); // duplicate element const size_type element1 = layout_type::index_M (i, j); const size_type element2 = layout_type::index_m (i, j); vector_data_value_type& vd (data () [element1]); std::pair
ii (vd.insert (typename vector_data_value_type::value_type (element2, t))); BOOST_UBLAS_CHECK ((ii.first)->first == element2, internal_logic ()); // broken map if (!ii.second) // existing element (ii.first)->second = t; return (ii.first)->second; } BOOST_UBLAS_INLINE void erase_element (size_type i, size_type j) { vector_subiterator_type itv (data ().find (layout_type::index_M (i, j))); if (itv == data ().end ()) return; subiterator_type it ((*itv).second.find (layout_type::index_m (i, j))); if (it == (*itv).second.end ()) return; (*itv).second.erase (it); } // Zeroing BOOST_UBLAS_INLINE void clear () { data ().clear (); data_ [layout_type::size_M (size1_, size2_)] = vector_data_value_type (); } // Assignment BOOST_UBLAS_INLINE mapped_vector_of_mapped_vector &operator = (const mapped_vector_of_mapped_vector &m) { if (this != &m) { size1_ = m.size1_; size2_ = m.size2_; data () = m.data (); } return *this; } template
// Container assignment without temporary BOOST_UBLAS_INLINE mapped_vector_of_mapped_vector &operator = (const matrix_container
&m) { resize (m ().size1 (), m ().size2 ()); assign (m); return *this; } BOOST_UBLAS_INLINE mapped_vector_of_mapped_vector &assign_temporary (mapped_vector_of_mapped_vector &m) { swap (m); return *this; } template
BOOST_UBLAS_INLINE mapped_vector_of_mapped_vector &operator = (const matrix_expression
&ae) { self_type temporary (ae); return assign_temporary (temporary); } template
BOOST_UBLAS_INLINE mapped_vector_of_mapped_vector &assign (const matrix_expression
&ae) { matrix_assign
(*this, ae); return *this; } template
BOOST_UBLAS_INLINE mapped_vector_of_mapped_vector& operator += (const matrix_expression
&ae) { self_type temporary (*this + ae); return assign_temporary (temporary); } template
// Container assignment without temporary BOOST_UBLAS_INLINE mapped_vector_of_mapped_vector &operator += (const matrix_container
&m) { plus_assign (m); return *this; } template
BOOST_UBLAS_INLINE mapped_vector_of_mapped_vector &plus_assign (const matrix_expression
&ae) { matrix_assign
(*this, ae); return *this; } template
BOOST_UBLAS_INLINE mapped_vector_of_mapped_vector& operator -= (const matrix_expression
&ae) { self_type temporary (*this - ae); return assign_temporary (temporary); } template
// Container assignment without temporary BOOST_UBLAS_INLINE mapped_vector_of_mapped_vector &operator -= (const matrix_container
&m) { minus_assign (m); return *this; } template
BOOST_UBLAS_INLINE mapped_vector_of_mapped_vector &minus_assign (const matrix_expression
&ae) { matrix_assign
(*this, ae); return *this; } template
BOOST_UBLAS_INLINE mapped_vector_of_mapped_vector& operator *= (const AT &at) { matrix_assign_scalar
(*this, at); return *this; } template
BOOST_UBLAS_INLINE mapped_vector_of_mapped_vector& operator /= (const AT &at) { matrix_assign_scalar
(*this, at); return *this; } // Swapping BOOST_UBLAS_INLINE void swap (mapped_vector_of_mapped_vector &m) { if (this != &m) { std::swap (size1_, m.size1_); std::swap (size2_, m.size2_); data ().swap (m.data ()); } } BOOST_UBLAS_INLINE friend void swap (mapped_vector_of_mapped_vector &m1, mapped_vector_of_mapped_vector &m2) { m1.swap (m2); } // Iterator types private: // Use storage iterators typedef typename A::const_iterator vector_const_subiterator_type; typedef typename A::iterator vector_subiterator_type; typedef typename A::value_type::second_type::const_iterator const_subiterator_type; typedef typename A::value_type::second_type::iterator subiterator_type; BOOST_UBLAS_INLINE true_reference at_element (size_type i, size_type j) { const size_type element1 = layout_type::index_M (i, j); const size_type element2 = layout_type::index_m (i, j); vector_subiterator_type itv (data ().find (element1)); BOOST_UBLAS_CHECK (itv != data ().end(), bad_index ()); BOOST_UBLAS_CHECK ((*itv).first == element1, internal_logic ()); // broken map subiterator_type it ((*itv).second.find (element2)); BOOST_UBLAS_CHECK (it != (*itv).second.end (), bad_index ()); BOOST_UBLAS_CHECK ((*it).first == element2, internal_logic ()); // broken map return it->second; } public: class const_iterator1; class iterator1; class const_iterator2; class iterator2; typedef reverse_iterator_base1
const_reverse_iterator1; typedef reverse_iterator_base1
reverse_iterator1; typedef reverse_iterator_base2
const_reverse_iterator2; typedef reverse_iterator_base2
reverse_iterator2; // Element lookup // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it. const_iterator1 find1 (int rank, size_type i, size_type j, int direction = 1) const { BOOST_UBLAS_CHECK (data ().begin () != data ().end (), internal_logic ()); for (;;) { vector_const_subiterator_type itv (data ().lower_bound (layout_type::index_M (i, j))); vector_const_subiterator_type itv_end (data ().end ()); if (itv == itv_end) return const_iterator1 (*this, rank, i, j, itv_end, (*(-- itv)).second.end ()); const_subiterator_type it ((*itv).second.lower_bound (layout_type::index_m (i, j))); const_subiterator_type it_end ((*itv).second.end ()); if (rank == 0) { // advance to the first available major index size_type M = itv->first; size_type m; if (it != it_end) { m = it->first; } else { m = layout_type::size_m(size1_, size2_); } size_type first_i = layout_type::index_M(M,m); return const_iterator1 (*this, rank, first_i, j, itv, it); } if (it != it_end && (*it).first == layout_type::index_m (i, j)) return const_iterator1 (*this, rank, i, j, itv, it); if (direction > 0) { if (layout_type::fast_i ()) { if (it == it_end) return const_iterator1 (*this, rank, i, j, itv, it); i = (*it).first; } else { if (i >= size1_) return const_iterator1 (*this, rank, i, j, itv, it); ++ i; } } else /* if (direction < 0) */ { if (layout_type::fast_i ()) { if (it == (*itv).second.begin ()) return const_iterator1 (*this, rank, i, j, itv, it); -- it; i = (*it).first; } else { if (i == 0) return const_iterator1 (*this, rank, i, j, itv, it); -- i; } } } } // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it. iterator1 find1 (int rank, size_type i, size_type j, int direction = 1) { BOOST_UBLAS_CHECK (data ().begin () != data ().end (), internal_logic ()); for (;;) { vector_subiterator_type itv (data ().lower_bound (layout_type::index_M (i, j))); vector_subiterator_type itv_end (data ().end ()); if (itv == itv_end) return iterator1 (*this, rank, i, j, itv_end, (*(-- itv)).second.end ()); subiterator_type it ((*itv).second.lower_bound (layout_type::index_m (i, j))); subiterator_type it_end ((*itv).second.end ()); if (rank == 0) { // advance to the first available major index size_type M = itv->first; size_type m; if (it != it_end) { m = it->first; } else { m = layout_type::size_m(size1_, size2_); } size_type first_i = layout_type::index_M(M,m); return iterator1 (*this, rank, first_i, j, itv, it); } if (it != it_end && (*it).first == layout_type::index_m (i, j)) return iterator1 (*this, rank, i, j, itv, it); if (direction > 0) { if (layout_type::fast_i ()) { if (it == it_end) return iterator1 (*this, rank, i, j, itv, it); i = (*it).first; } else { if (i >= size1_) return iterator1 (*this, rank, i, j, itv, it); ++ i; } } else /* if (direction < 0) */ { if (layout_type::fast_i ()) { if (it == (*itv).second.begin ()) return iterator1 (*this, rank, i, j, itv, it); -- it; i = (*it).first; } else { if (i == 0) return iterator1 (*this, rank, i, j, itv, it); -- i; } } } } // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it. const_iterator2 find2 (int rank, size_type i, size_type j, int direction = 1) const { BOOST_UBLAS_CHECK (data ().begin () != data ().end (), internal_logic ()); for (;;) { vector_const_subiterator_type itv (data ().lower_bound (layout_type::index_M (i, j))); vector_const_subiterator_type itv_end (data ().end ()); if (itv == itv_end) return const_iterator2 (*this, rank, i, j, itv_end, (*(-- itv)).second.end ()); const_subiterator_type it ((*itv).second.lower_bound (layout_type::index_m (i, j))); const_subiterator_type it_end ((*itv).second.end ()); if (rank == 0) { // advance to the first available major index size_type M = itv->first; size_type m; if (it != it_end) { m = it->first; } else { m = layout_type::size_m(size1_, size2_); } size_type first_j = layout_type::index_m(M,m); return const_iterator2 (*this, rank, i, first_j, itv, it); } if (it != it_end && (*it).first == layout_type::index_m (i, j)) return const_iterator2 (*this, rank, i, j, itv, it); if (direction > 0) { if (layout_type::fast_j ()) { if (it == it_end) return const_iterator2 (*this, rank, i, j, itv, it); j = (*it).first; } else { if (j >= size2_) return const_iterator2 (*this, rank, i, j, itv, it); ++ j; } } else /* if (direction < 0) */ { if (layout_type::fast_j ()) { if (it == (*itv).second.begin ()) return const_iterator2 (*this, rank, i, j, itv, it); -- it; j = (*it).first; } else { if (j == 0) return const_iterator2 (*this, rank, i, j, itv, it); -- j; } } } } // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it. iterator2 find2 (int rank, size_type i, size_type j, int direction = 1) { BOOST_UBLAS_CHECK (data ().begin () != data ().end (), internal_logic ()); for (;;) { vector_subiterator_type itv (data ().lower_bound (layout_type::index_M (i, j))); vector_subiterator_type itv_end (data ().end ()); if (itv == itv_end) return iterator2 (*this, rank, i, j, itv_end, (*(-- itv)).second.end ()); subiterator_type it ((*itv).second.lower_bound (layout_type::index_m (i, j))); subiterator_type it_end ((*itv).second.end ()); if (rank == 0) { // advance to the first available major index size_type M = itv->first; size_type m; if (it != it_end) { m = it->first; } else { m = layout_type::size_m(size1_, size2_); } size_type first_j = layout_type::index_m(M,m); return iterator2 (*this, rank, i, first_j, itv, it); } if (it != it_end && (*it).first == layout_type::index_m (i, j)) return iterator2 (*this, rank, i, j, itv, it); if (direction > 0) { if (layout_type::fast_j ()) { if (it == it_end) return iterator2 (*this, rank, i, j, itv, it); j = (*it).first; } else { if (j >= size2_) return iterator2 (*this, rank, i, j, itv, it); ++ j; } } else /* if (direction < 0) */ { if (layout_type::fast_j ()) { if (it == (*itv).second.begin ()) return iterator2 (*this, rank, i, j, itv, it); -- it; j = (*it).first; } else { if (j == 0) return iterator2 (*this, rank, i, j, itv, it); -- j; } } } } class const_iterator1: public container_const_reference
, public bidirectional_iterator_base
{ public: typedef typename mapped_vector_of_mapped_vector::value_type value_type; typedef typename mapped_vector_of_mapped_vector::difference_type difference_type; typedef typename mapped_vector_of_mapped_vector::const_reference reference; typedef const typename mapped_vector_of_mapped_vector::pointer pointer; typedef const_iterator2 dual_iterator_type; typedef const_reverse_iterator2 dual_reverse_iterator_type; // Construction and destruction BOOST_UBLAS_INLINE const_iterator1 (): container_const_reference
(), rank_ (), i_ (), j_ (), itv_ (), it_ () {} BOOST_UBLAS_INLINE 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): container_const_reference
(m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {} BOOST_UBLAS_INLINE const_iterator1 (const iterator1 &it): container_const_reference
(it ()), rank_ (it.rank_), i_ (it.i_), j_ (it.j_), itv_ (it.itv_), it_ (it.it_) {} // Arithmetic BOOST_UBLAS_INLINE const_iterator1 &operator ++ () { if (rank_ == 1 && layout_type::fast_i ()) ++ it_; else { const self_type &m = (*this) (); if (rank_ == 0) { ++ itv_; i_ = itv_->first; } else { i_ = index1 () + 1; } if (rank_ == 1 && ++ itv_ == m.end1 ().itv_) *this = m.find1 (rank_, i_, j_, 1); else if (rank_ == 1) { it_ = (*itv_).second.begin (); if (it_ == (*itv_).second.end () || index2 () != j_) *this = m.find1 (rank_, i_, j_, 1); } } return *this; } BOOST_UBLAS_INLINE const_iterator1 &operator -- () { if (rank_ == 1 && layout_type::fast_i ()) -- it_; else { const self_type &m = (*this) (); if (rank_ == 0) { -- itv_; i_ = itv_->first; } else { i_ = index1 () - 1; } // FIXME: this expression should never become true! if (rank_ == 1 && -- itv_ == m.end1 ().itv_) *this = m.find1 (rank_, i_, j_, -1); else if (rank_ == 1) { it_ = (*itv_).second.begin (); if (it_ == (*itv_).second.end () || index2 () != j_) *this = m.find1 (rank_, i_, j_, -1); } } return *this; } // Dereference BOOST_UBLAS_INLINE const_reference operator * () const { BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ()); BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ()); if (rank_ == 1) { return (*it_).second; } else { return (*this) () (i_, j_); } } #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_iterator2 begin () const { const self_type &m = (*this) (); return m.find2 (1, index1 (), 0); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_iterator2 end () const { const self_type &m = (*this) (); return m.find2 (1, index1 (), m.size2 ()); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator2 rbegin () const { return const_reverse_iterator2 (end ()); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator2 rend () const { return const_reverse_iterator2 (begin ()); } #endif // Indices BOOST_UBLAS_INLINE size_type index1 () const { BOOST_UBLAS_CHECK (*this != (*this) ().find1 (0, (*this) ().size1 (), j_), bad_index ()); if (rank_ == 1) { BOOST_UBLAS_CHECK (layout_type::index_M ((*itv_).first, (*it_).first) < (*this) ().size1 (), bad_index ()); return layout_type::index_M ((*itv_).first, (*it_).first); } else { return i_; } } BOOST_UBLAS_INLINE size_type index2 () const { if (rank_ == 1) { BOOST_UBLAS_CHECK (layout_type::index_m ((*itv_).first, (*it_).first) < (*this) ().size2 (), bad_index ()); return layout_type::index_m ((*itv_).first, (*it_).first); } else { return j_; } } // Assignment BOOST_UBLAS_INLINE const_iterator1 &operator = (const const_iterator1 &it) { container_const_reference
::assign (&it ()); rank_ = it.rank_; i_ = it.i_; j_ = it.j_; itv_ = it.itv_; it_ = it.it_; return *this; } // Comparison BOOST_UBLAS_INLINE bool operator == (const const_iterator1 &it) const { BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ()); if (rank_ == 1 || it.rank_ == 1) { return it_ == it.it_; } else { return i_ == it.i_ && j_ == it.j_; } } private: int rank_; size_type i_; size_type j_; vector_const_subiterator_type itv_; const_subiterator_type it_; }; BOOST_UBLAS_INLINE const_iterator1 begin1 () const { return find1 (0, 0, 0); } BOOST_UBLAS_INLINE const_iterator1 end1 () const { return find1 (0, size1_, 0); } class iterator1: public container_reference
, public bidirectional_iterator_base
{ public: typedef typename mapped_vector_of_mapped_vector::value_type value_type; typedef typename mapped_vector_of_mapped_vector::difference_type difference_type; typedef typename mapped_vector_of_mapped_vector::true_reference reference; typedef typename mapped_vector_of_mapped_vector::pointer pointer; typedef iterator2 dual_iterator_type; typedef reverse_iterator2 dual_reverse_iterator_type; // Construction and destruction BOOST_UBLAS_INLINE iterator1 (): container_reference
(), rank_ (), i_ (), j_ (), itv_ (), it_ () {} BOOST_UBLAS_INLINE iterator1 (self_type &m, int rank, size_type i, size_type j, const vector_subiterator_type &itv, const subiterator_type &it): container_reference
(m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {} // Arithmetic BOOST_UBLAS_INLINE iterator1 &operator ++ () { if (rank_ == 1 && layout_type::fast_i ()) ++ it_; else { self_type &m = (*this) (); if (rank_ == 0) { ++ itv_; i_ = itv_->first; } else { i_ = index1 () + 1; } if (rank_ == 1 && ++ itv_ == m.end1 ().itv_) *this = m.find1 (rank_, i_, j_, 1); else if (rank_ == 1) { it_ = (*itv_).second.begin (); if (it_ == (*itv_).second.end () || index2 () != j_) *this = m.find1 (rank_, i_, j_, 1); } } return *this; } BOOST_UBLAS_INLINE iterator1 &operator -- () { if (rank_ == 1 && layout_type::fast_i ()) -- it_; else { self_type &m = (*this) (); if (rank_ == 0) { -- itv_; i_ = itv_->first; } else { i_ = index1 () - 1; } // FIXME: this expression should never become true! if (rank_ == 1 && -- itv_ == m.end1 ().itv_) *this = m.find1 (rank_, i_, j_, -1); else if (rank_ == 1) { it_ = (*itv_).second.begin (); if (it_ == (*itv_).second.end () || index2 () != j_) *this = m.find1 (rank_, i_, j_, -1); } } return *this; } // Dereference BOOST_UBLAS_INLINE reference operator * () const { BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ()); BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ()); if (rank_ == 1) { return (*it_).second; } else { return (*this) ().at_element (i_, j_); } } #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif iterator2 begin () const { self_type &m = (*this) (); return m.find2 (1, index1 (), 0); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif iterator2 end () const { self_type &m = (*this) (); return m.find2 (1, index1 (), m.size2 ()); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif reverse_iterator2 rbegin () const { return reverse_iterator2 (end ()); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif reverse_iterator2 rend () const { return reverse_iterator2 (begin ()); } #endif // Indices BOOST_UBLAS_INLINE size_type index1 () const { BOOST_UBLAS_CHECK (*this != (*this) ().find1 (0, (*this) ().size1 (), j_), bad_index ()); if (rank_ == 1) { BOOST_UBLAS_CHECK (layout_type::index_M ((*itv_).first, (*it_).first) < (*this) ().size1 (), bad_index ()); return layout_type::index_M ((*itv_).first, (*it_).first); } else { return i_; } } BOOST_UBLAS_INLINE size_type index2 () const { if (rank_ == 1) { BOOST_UBLAS_CHECK (layout_type::index_m ((*itv_).first, (*it_).first) < (*this) ().size2 (), bad_index ()); return layout_type::index_m ((*itv_).first, (*it_).first); } else { return j_; } } // Assignment BOOST_UBLAS_INLINE iterator1 &operator = (const iterator1 &it) { container_reference
::assign (&it ()); rank_ = it.rank_; i_ = it.i_; j_ = it.j_; itv_ = it.itv_; it_ = it.it_; return *this; } // Comparison BOOST_UBLAS_INLINE bool operator == (const iterator1 &it) const { BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ()); if (rank_ == 1 || it.rank_ == 1) { return it_ == it.it_; } else { return i_ == it.i_ && j_ == it.j_; } } private: int rank_; size_type i_; size_type j_; vector_subiterator_type itv_; subiterator_type it_; friend class const_iterator1; }; BOOST_UBLAS_INLINE iterator1 begin1 () { return find1 (0, 0, 0); } BOOST_UBLAS_INLINE iterator1 end1 () { return find1 (0, size1_, 0); } class const_iterator2: public container_const_reference
, public bidirectional_iterator_base
{ public: typedef typename mapped_vector_of_mapped_vector::value_type value_type; typedef typename mapped_vector_of_mapped_vector::difference_type difference_type; typedef typename mapped_vector_of_mapped_vector::const_reference reference; typedef const typename mapped_vector_of_mapped_vector::pointer pointer; typedef const_iterator1 dual_iterator_type; typedef const_reverse_iterator1 dual_reverse_iterator_type; // Construction and destruction BOOST_UBLAS_INLINE const_iterator2 (): container_const_reference
(), rank_ (), i_ (), j_ (), itv_ (), it_ () {} BOOST_UBLAS_INLINE 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): container_const_reference
(m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {} BOOST_UBLAS_INLINE const_iterator2 (const iterator2 &it): container_const_reference
(it ()), rank_ (it.rank_), i_ (it.i_), j_ (it.j_), itv_ (it.itv_), it_ (it.it_) {} // Arithmetic BOOST_UBLAS_INLINE const_iterator2 &operator ++ () { if (rank_ == 1 && layout_type::fast_j ()) ++ it_; else { const self_type &m = (*this) (); if (rank_ == 0) { ++ itv_; j_ = itv_->first; } else { j_ = index2 () + 1; } if (rank_ == 1 && ++ itv_ == m.end2 ().itv_) *this = m.find2 (rank_, i_, j_, 1); else if (rank_ == 1) { it_ = (*itv_).second.begin (); if (it_ == (*itv_).second.end () || index1 () != i_) *this = m.find2 (rank_, i_, j_, 1); } } return *this; } BOOST_UBLAS_INLINE const_iterator2 &operator -- () { if (rank_ == 1 && layout_type::fast_j ()) -- it_; else { const self_type &m = (*this) (); if (rank_ == 0) { -- itv_; j_ = itv_->first; } else { j_ = index2 () - 1; } // FIXME: this expression should never become true! if (rank_ == 1 && -- itv_ == m.end2 ().itv_) *this = m.find2 (rank_, i_, j_, -1); else if (rank_ == 1) { it_ = (*itv_).second.begin (); if (it_ == (*itv_).second.end () || index1 () != i_) *this = m.find2 (rank_, i_, j_, -1); } } return *this; } // Dereference BOOST_UBLAS_INLINE const_reference operator * () const { BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ()); BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ()); if (rank_ == 1) { return (*it_).second; } else { return (*this) () (i_, j_); } } #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_iterator1 begin () const { const self_type &m = (*this) (); return m.find1 (1, 0, index2 ()); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_iterator1 end () const { const self_type &m = (*this) (); return m.find1 (1, m.size1 (), index2 ()); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator1 rbegin () const { return const_reverse_iterator1 (end ()); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif const_reverse_iterator1 rend () const { return const_reverse_iterator1 (begin ()); } #endif // Indices BOOST_UBLAS_INLINE size_type index1 () const { if (rank_ == 1) { BOOST_UBLAS_CHECK (layout_type::index_M ((*itv_).first, (*it_).first) < (*this) ().size1 (), bad_index ()); return layout_type::index_M ((*itv_).first, (*it_).first); } else { return i_; } } BOOST_UBLAS_INLINE size_type index2 () const { BOOST_UBLAS_CHECK (*this != (*this) ().find2 (0, i_, (*this) ().size2 ()), bad_index ()); if (rank_ == 1) { BOOST_UBLAS_CHECK (layout_type::index_m ((*itv_).first, (*it_).first) < (*this) ().size2 (), bad_index ()); return layout_type::index_m ((*itv_).first, (*it_).first); } else { return j_; } } // Assignment BOOST_UBLAS_INLINE const_iterator2 &operator = (const const_iterator2 &it) { container_const_reference
::assign (&it ()); rank_ = it.rank_; i_ = it.i_; j_ = it.j_; itv_ = it.itv_; it_ = it.it_; return *this; } // Comparison BOOST_UBLAS_INLINE bool operator == (const const_iterator2 &it) const { BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ()); if (rank_ == 1 || it.rank_ == 1) { return it_ == it.it_; } else { return i_ == it.i_ && j_ == it.j_; } } private: int rank_; size_type i_; size_type j_; vector_const_subiterator_type itv_; const_subiterator_type it_; }; BOOST_UBLAS_INLINE const_iterator2 begin2 () const { return find2 (0, 0, 0); } BOOST_UBLAS_INLINE const_iterator2 end2 () const { return find2 (0, 0, size2_); } class iterator2: public container_reference
, public bidirectional_iterator_base
{ public: typedef typename mapped_vector_of_mapped_vector::value_type value_type; typedef typename mapped_vector_of_mapped_vector::difference_type difference_type; typedef typename mapped_vector_of_mapped_vector::true_reference reference; typedef typename mapped_vector_of_mapped_vector::pointer pointer; typedef iterator1 dual_iterator_type; typedef reverse_iterator1 dual_reverse_iterator_type; // Construction and destruction BOOST_UBLAS_INLINE iterator2 (): container_reference
(), rank_ (), i_ (), j_ (), itv_ (), it_ () {} BOOST_UBLAS_INLINE iterator2 (self_type &m, int rank, size_type i, size_type j, const vector_subiterator_type &itv, const subiterator_type &it): container_reference
(m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {} // Arithmetic BOOST_UBLAS_INLINE iterator2 &operator ++ () { if (rank_ == 1 && layout_type::fast_j ()) ++ it_; else { self_type &m = (*this) (); if (rank_ == 0) { ++ itv_; j_ = itv_->first; } else { j_ = index2 () + 1; } if (rank_ == 1 && ++ itv_ == m.end2 ().itv_) *this = m.find2 (rank_, i_, j_, 1); else if (rank_ == 1) { it_ = (*itv_).second.begin (); if (it_ == (*itv_).second.end () || index1 () != i_) *this = m.find2 (rank_, i_, j_, 1); } } return *this; } BOOST_UBLAS_INLINE iterator2 &operator -- () { if (rank_ == 1 && layout_type::fast_j ()) -- it_; else { self_type &m = (*this) (); if (rank_ == 0) { -- itv_; j_ = itv_->first; } else { j_ = index2 () - 1; } // FIXME: this expression should never become true! if (rank_ == 1 && -- itv_ == m.end2 ().itv_) *this = m.find2 (rank_, i_, j_, -1); else if (rank_ == 1) { it_ = (*itv_).second.begin (); if (it_ == (*itv_).second.end () || index1 () != i_) *this = m.find2 (rank_, i_, j_, -1); } } return *this; } // Dereference BOOST_UBLAS_INLINE reference operator * () const { BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ()); BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ()); if (rank_ == 1) { return (*it_).second; } else { return (*this) ().at_element (i_, j_); } } #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif iterator1 begin () const { self_type &m = (*this) (); return m.find1 (1, 0, index2 ()); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif iterator1 end () const { self_type &m = (*this) (); return m.find1 (1, m.size1 (), index2 ()); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif reverse_iterator1 rbegin () const { return reverse_iterator1 (end ()); } BOOST_UBLAS_INLINE #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION typename self_type:: #endif reverse_iterator1 rend () const { return reverse_iterator1 (begin ()); } #endif // Indices BOOST_UBLAS_INLINE size_type index1 () const { if (rank_ == 1) { BOOST_UBLAS_CHECK (layout_type::index_M ((*itv_).first, (*it_).first) < (*this) ().size1 (), bad_index ()); return layout_type::index_M ((*itv_).first, (*it_).first); } else { return i_; } } BOOST_UBLAS_INLINE size_type index2 () const { BOOST_UBLAS_CHECK (*this != (*this) ().find2 (0, i_, (*this) ().size2 ()), bad_index ()); if (rank_ == 1) { BOOST_UBLAS_CHECK (layout_type::index_m ((*itv_).first, (*it_).first) < (*this) ().size2 (), bad_index ()); return layout_type::index_m ((*itv_).first, (*it_).first); } else { return j_; } } // Assignment BOOST_UBLAS_INLINE iterator2 &operator = (const iterator2 &it) { container_reference
::assign (&it ()); rank_ = it.rank_; i_ = it.i_; j_ = it.j_; itv_ = it.itv_; it_ = it.it_; return *this; } // Comparison BOOST_UBLAS_INLINE bool operator == (const iterator2 &it) const { BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ()); if (rank_ == 1 || it.rank_ == 1) { return it_ == it.it_; } else { return i_ == it.i_ && j_ == it.j_; } } private: int rank_; size_type i_; size_type j_; vector_subiterator_type itv_; subiterator_type it_; friend class const_iterator2; }; BOOST_UBLAS_INLINE iterator2 begin2 () { return find2 (0, 0, 0); } BOOST_UBLAS_INLINE iterator2 end2 () { return find2 (0, 0, size2_); } // Reverse iterators BOOST_UBLAS_INLINE const_reverse_iterator1 rbegin1 () const { return const_reverse_iterator1 (end1 ()); } BOOST_UBLAS_INLINE const_reverse_iterator1 rend1 () const { return const_reverse_iterator1 (begin1 ()); } BOOST_UBLAS_INLINE reverse_iterator1 rbegin1 () { return reverse_iterator1 (end1 ()); } BOOST_UBLAS_INLINE reverse_iterator1 rend1 () { return reverse_iterator1 (begin1 ()); } BOOST_UBLAS_INLINE const_reverse_iterator2 rbegin2 () const { return const_reverse_iterator2 (end2 ()); } BOOST_UBLAS_INLINE const_reverse_iterator2 rend2 () const { return const_reverse_iterator2 (begin2 ()); } BOOST_UBLAS_INLINE reverse_iterator2 rbegin2 () { return reverse_iterator2 (end2 ()); } BOOST_UBLAS_INLINE reverse_iterator2 rend2 () { return reverse_iterator2 (begin2 ()); } // Serialization template
void serialize(Archive & ar, const unsigned int /* file_version */){ serialization::collection_size_type s1 (size1_); serialization::collection_size_type s2 (size2_); ar & serialization::make_nvp("size1",s1); ar & serialization::make_nvp("size2",s2); if (Archive::is_loading::value) { size1_ = s1; size2_ = s2; } ar & serialization::make_nvp("data", data_); } private: size_type size1_; size_type size2_; array_type data_; static const value_type zero_; }; template
const typename mapped_vector_of_mapped_vector
::value_type mapped_vector_of_mapped_vector
::zero_ = value_type/*zero*/(); // Comperssed array based sparse matrix class // Thanks to Kresimir Fresl for extending this to cover different index bases. template
class compressed_matrix: public matrix_container
> { typedef T &true_reference; typedef T *pointer; typedef const T *const_pointer; typedef L layout_type; typedef compressed_matrix
self_type; public: #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS using matrix_container
::operator (); #endif // ISSUE require type consistency check // is_convertable (IA::size_type, TA::size_type) typedef typename IA::value_type size_type; // size_type for the data arrays. typedef typename IA::size_type array_size_type; // FIXME difference type for sparse storage iterators should it be in the container? typedef typename IA::difference_type difference_type; typedef T value_type; typedef const T &const_reference; #ifndef BOOST_UBLAS_STRICT_MATRIX_SPARSE typedef T &reference; #else typedef sparse_matrix_element
reference; #endif typedef IA index_array_type; typedef TA value_array_type; typedef const matrix_reference
const_closure_type; typedef matrix_reference
closure_type; typedef compressed_vector
vector_temporary_type; typedef self_type matrix_temporary_type; typedef sparse_tag storage_category; typedef typename L::orientation_category orientation_category; // Construction and destruction BOOST_UBLAS_INLINE compressed_matrix (): matrix_container
(), size1_ (0), size2_ (0), capacity_ (restrict_capacity (0)), filled1_ (1), filled2_ (0), index1_data_ (layout_type::size_M (size1_, size2_) + 1), index2_data_ (capacity_), value_data_ (capacity_) { index1_data_ [filled1_ - 1] = k_based (filled2_); storage_invariants (); } BOOST_UBLAS_INLINE compressed_matrix (size_type size1, size_type size2, size_type non_zeros = 0): matrix_container
(), size1_ (size1), size2_ (size2), capacity_ (restrict_capacity (non_zeros)), filled1_ (1), filled2_ (0), index1_data_ (layout_type::size_M (size1_, size2_) + 1), index2_data_ (capacity_), value_data_ (capacity_) { index1_data_ [filled1_ - 1] = k_based (filled2_); storage_invariants (); } BOOST_UBLAS_INLINE compressed_matrix (const compressed_matrix &m): matrix_container
(), size1_ (m.size1_), size2_ (m.size2_), capacity_ (m.capacity_), filled1_ (m.filled1_), filled2_ (m.filled2_), index1_data_ (m.index1_data_), index2_data_ (m.index2_data_), value_data_ (m.value_data_) { storage_invariants (); } BOOST_UBLAS_INLINE compressed_matrix (const coordinate_matrix
&m): matrix_container
(), size1_ (m.size1()), size2_ (m.size2()), index1_data_ (layout_type::size_M (size1_, size2_) + 1) { m.sort(); reserve(m.nnz(), false); filled2_ = m.nnz(); const_subiterator_type i_start = m.index1_data().begin(); const_subiterator_type i_end = (i_start + filled2_); const_subiterator_type i = i_start; size_type r = 1; for (; (r < layout_type::size_M (size1_, size2_)) && (i != i_end); ++r) { i = std::lower_bound(i, i_end, r); index1_data_[r] = k_based( i - i_start ); } filled1_ = r + 1; std::copy( m.index2_data().begin(), m.index2_data().begin() + filled2_, index2_data_.begin()); std::copy( m.value_data().begin(), m.value_data().begin() + filled2_, value_data_.begin()); index1_data_ [filled1_ - 1] = k_based(filled2_); storage_invariants (); } template
BOOST_UBLAS_INLINE compressed_matrix (const matrix_expression
&ae, size_type non_zeros = 0): matrix_container
(), size1_ (ae ().size1 ()), size2_ (ae ().size2 ()), capacity_ (restrict_capacity (non_zeros)), filled1_ (1), filled2_ (0), index1_data_ (layout_type::size_M (ae ().size1 (), ae ().size2 ()) + 1), index2_data_ (capacity_), value_data_ (capacity_) { index1_data_ [filled1_ - 1] = k_based (filled2_); storage_invariants (); matrix_assign
(*this, ae); } // Accessors BOOST_UBLAS_INLINE size_type size1 () const { return size1_; } BOOST_UBLAS_INLINE size_type size2 () const { return size2_; } BOOST_UBLAS_INLINE size_type nnz_capacity () const { return capacity_; } BOOST_UBLAS_INLINE size_type nnz () const { return filled2_; } // Storage accessors BOOST_UBLAS_INLINE static size_type index_base () { return IB; } BOOST_UBLAS_INLINE array_size_type filled1 () const { return filled1_; } BOOST_UBLAS_INLINE array_size_type filled2 () const { return filled2_; } BOOST_UBLAS_INLINE const index_array_type &index1_data () const { return index1_data_; } BOOST_UBLAS_INLINE const index_array_type &index2_data () const { return index2_data_; } BOOST_UBLAS_INLINE const value_array_type &value_data () const { return value_data_; } BOOST_UBLAS_INLINE void set_filled (const array_size_type& filled1, const array_size_type& filled2) { filled1_ = filled1; filled2_ = filled2; storage_invariants (); } BOOST_UBLAS_INLINE index_array_type &index1_data () { return index1_data_; } BOOST_UBLAS_INLINE index_array_type &index2_data () { return index2_data_; } BOOST_UBLAS_INLINE value_array_type &value_data () { return value_data_; } BOOST_UBLAS_INLINE void complete_index1_data () { while (filled1_ <= layout_type::size_M (size1_, size2_)) { this->index1_data_ [filled1_] = k_based (filled2_); ++ this->filled1_; } } // Resizing private: BOOST_UBLAS_INLINE size_type restrict_capacity (size_type non_zeros) const { non_zeros = (std::max) (non_zeros, (std::min) (size1_, size2_)); // Guarding against overflow - Thanks to Alexei Novakov for the hint. // non_zeros = (std::min) (non_zeros, size1_ * size2_); if (size1_ > 0 && non_zeros / size1_ >= size2_) non_zeros = size1_ * size2_; return non_zeros; } public: BOOST_UBLAS_INLINE void resize (size_type size1, size_type size2, bool preserve = true) { // FIXME preserve unimplemented BOOST_UBLAS_CHECK (!preserve, internal_logic ()); size1_ = size1; size2_ = size2; capacity_ = restrict_capacity (capacity_); filled1_ = 1; filled2_ = 0; index1_data_.resize (layout_type::size_M (size1_, size2_) + 1); index2_data_.resize (capacity_); value_data_.resize (capacity_); index1_data_ [filled1_ - 1] = k_based (filled2_); storage_invariants (); } // Reserving BOOST_UBLAS_INLINE void reserve (size_type non_zeros, bool preserve = true) { capacity_ = restrict_capacity (non_zeros); if (preserve) { index2_data_.resize (capacity_, size_type ()); value_data_.resize (capacity_, value_type ()); filled2_ = (std::min) (capacity_, filled2_); } else { index2_data_.resize (capacity_); value_data_.resize (capacity_); filled1_ = 1; filled2_ = 0; index1_data_ [filled1_ - 1] = k_based (filled2_); } storage_invariants (); } // Element support BOOST_UBLAS_INLINE pointer find_element (size_type i, size_type j) { return const_cast
(const_cast
(*this).find_element (i, j)); } BOOST_UBLAS_INLINE const_pointer find_element (size_type i, size_type j) const { size_type element1 (layout_type::index_M (i, j)); size_type element2 (layout_type::index_m (i, j)); if (filled1_ <= element1 + 1) return 0; vector_const_subiterator_type itv (index1_data_.begin () + element1); const_subiterator_type it_begin (index2_data_.begin () + zero_based (*itv)); const_subiterator_type it_end (index2_data_.begin () + zero_based (*(itv + 1))); const_subiterator_type it (detail::lower_bound (it_begin, it_end, k_based (element2), std::less
())); if (it == it_end || *it != k_based (element2)) return 0; return &value_data_ [it - index2_data_.begin ()]; } // Element access BOOST_UBLAS_INLINE const_reference operator () (size_type i, size_type j) const { const_pointer p = find_element (i, j); if (p) return *p; else return zero_; } BOOST_UBLAS_INLINE reference operator () (size_type i, size_type j) { #ifndef BOOST_UBLAS_STRICT_MATRIX_SPARSE size_type element1 (layout_type::index_M (i, j)); size_type element2 (layout_type::index_m (i, j)); if (filled1_ <= element1 + 1) return insert_element (i, j, value_type/*zero*/()); pointer p = find_element (i, j); if (p) return *p; else return insert_element (i, j, value_type/*zero*/()); #else return reference (*this, i, j); #endif } // Element assignment BOOST_UBLAS_INLINE true_reference insert_element (size_type i, size_type j, const_reference t) { BOOST_UBLAS_CHECK (!find_element (i, j), bad_index ()); // duplicate element if (filled2_ >= capacity_) reserve (2 * filled2_, true); BOOST_UBLAS_CHECK (filled2_ < capacity_, internal_logic ()); size_type element1 = layout_type::index_M (i, j); size_type element2 = layout_type::index_m (i, j); while (filled1_ <= element1 + 1) { index1_data_ [filled1_] = k_based (filled2_); ++ filled1_; } vector_subiterator_type itv (index1_data_.begin () + element1); subiterator_type it_begin (index2_data_.begin () + zero_based (*itv)); subiterator_type it_end (index2_data_.begin () + zero_based (*(itv + 1))); subiterator_type it (detail::lower_bound (it_begin, it_end, k_based (element2), std::less
())); typename std::iterator_traits
::difference_type n = it - index2_data_.begin (); BOOST_UBLAS_CHECK (it == it_end || *it != k_based (element2), internal_logic ()); // duplicate bound by lower_bound ++ filled2_; it = index2_data_.begin () + n; std::copy_backward (it, index2_data_.begin () + filled2_ - 1, index2_data_.begin () + filled2_); *it = k_based (element2); typename value_array_type::iterator itt (value_data_.begin () + n); std::copy_backward (itt, value_data_.begin () + filled2_ - 1, value_data_.begin () + filled2_); *itt = t; while (element1 + 1 < filled1_) { ++ index1_data_ [element1 + 1]; ++ element1; } storage_invariants (); return *itt; } BOOST_UBLAS_INLINE void erase_element (size_type i, size_type j) { size_type element1 = layout_type::index_M (i, j); size_type element2 = layout_type::index_m (i, j); if (element1 + 1 > filled1_) return; vector_subiterator_type itv (index1_data_.begin () + element1); subiterator_type it_begin (index2_data_.begin () + zero_based (*itv)); subiterator_type it_end (index2_data_.begin () + zero_based (*(itv + 1))); subiterator_type it (detail::lower_bound (it_begin, it_end, k_based (element2), std::less
())); if (it != it_end && *it == k_based (element2)) { typename std::iterator_traits
::difference_type n = it - index2_data_.begin (); std::copy (it + 1, index2_data_.begin () + filled2_, it); typename value_array_type::iterator itt (value_data_.begin () + n); std::copy (itt + 1, value_data_.begin () + filled2_, itt); -- filled2_; while (index1_data_ [filled1_ - 2] > k_based (filled2_)) { index1_data_ [filled1_ - 1] = 0; -- filled1_; } while (element1 + 1 < filled1_) { -- index1_data_ [element1 + 1]; ++ element1; } } storage_invariants (); } // Zeroing BOOST_UBLAS_INLINE void clear () { filled1_ = 1; filled2_ = 0; index1_data_ [filled1_ - 1] = k_based (filled2_); storage_invariants (); } // Assignment BOOST_UBLAS_INLINE compressed_matrix &operator = (const compressed_matrix &m) { if (this != &m) { size1_ = m.size1_; size2_ = m.size2_; capacity_ = m.capacity_; filled1_ = m.filled1_; filled2_ = m.filled2_; index1_data_ = m.index1_data_; index2_data_ = m.index2_data_; value_data_ = m.value_data_; } storage_invariants (); return *this; } template
// Container assignment without temporary BOOST_UBLAS_INLINE compressed_matrix &operator = (const matrix_container
&m) { resize (m ().size1 (), m ().size2 (), false); assign (m); return *this; } BOOST_UBLAS_INLINE compressed_matrix &assign_temporary (compressed_matrix &m) { swap (m); return *this; } template
BOOST_UBLAS_INLINE compressed_matrix &operator = (const matrix_expression
&ae) { self_type temporary (ae, capacity_); return assign_temporary (temporary); } template
BOOST_UBLAS_INLINE compressed_matrix &assign (const matrix_expression
&ae) { matrix_assign
(*this, ae); return *this; } template
BOOST_UBLAS_INLINE compressed_matrix& operator += (const matrix_expression
&ae) { self_type temporary (*this + ae, capacity_); return assign_temporary (temporary); } template
// Container assignment without temporary BOOST_UBLAS_INLINE compressed_matrix &operator += (const matrix_container
&m) { plus_assign (m); return *this; } template
BOOST_UBLAS_INLINE compressed_matrix &plus_assign (const matrix_expression
&ae) { matrix_assign
(*this, ae); return *this; } template
BOOST_UBLAS_INLINE compressed_matrix& operator -= (const matrix_expression
&ae) { self_type temporary (*this - ae, capacity_); return assign_temporary (temporary); } template
// Container assignment without temporary BOOST_UBLAS_INLINE compressed_matrix &operator -= (const matrix_container
&m) { minus_assign (m); return *this; } template
BOOST_UBLAS_INLINE compressed_matrix &minus_assign (const matrix_expression
&ae) { matrix_assign
(*this, ae); return *this; } template
BOOST_UBLAS_INLINE compressed_matrix& operator *= (const AT &at) { matrix_assign_scalar
(*this, at); return *this; } template