mirror of
https://github.com/boostorg/ublas.git
synced 2026-02-21 03:22:14 +00:00
1898 lines
68 KiB
C++
1898 lines
68 KiB
C++
//
|
|
// Copyright (c) 2000-2002
|
|
// Joerg Walter, Mathias Koch
|
|
//
|
|
// Permission to use, copy, modify, distribute and sell this software
|
|
// and its documentation for any purpose is hereby granted without fee,
|
|
// provided that the above copyright notice appear in all copies and
|
|
// that both that copyright notice and this permission notice appear
|
|
// in supporting documentation. The authors make no representations
|
|
// about the suitability of this software for any purpose.
|
|
// It is provided "as is" without express or implied warranty.
|
|
//
|
|
// The authors gratefully acknowledge the support of
|
|
// GeNeSys mbH & Co. KG in producing this work.
|
|
//
|
|
|
|
#ifndef BOOST_UBLAS_VECTOR_SPARSE_H
|
|
#define BOOST_UBLAS_VECTOR_SPARSE_H
|
|
|
|
#include <boost/numeric/ublas/config.hpp>
|
|
#include <boost/numeric/ublas/storage_sparse.hpp>
|
|
#include <boost/numeric/ublas/vector.hpp>
|
|
|
|
// Iterators based on ideas of Jeremy Siek
|
|
|
|
namespace boost { namespace numeric { namespace ublas {
|
|
|
|
#ifdef BOOST_UBLAS_STRICT_VECTOR_SPARSE
|
|
|
|
template<class V>
|
|
class sparse_vector_element:
|
|
public container_reference<V> {
|
|
public:
|
|
typedef V vector_type;
|
|
typedef typename V::size_type size_type;
|
|
typedef typename V::value_type value_type;
|
|
typedef const value_type &const_reference;
|
|
typedef value_type &reference;
|
|
typedef value_type *pointer;
|
|
|
|
// Construction and destruction
|
|
BOOST_UBLAS_INLINE
|
|
sparse_vector_element (const value_type &d):
|
|
container_reference<vector_type> (), it_ (), i_ (), d_ (d), dirty_ (false) {
|
|
external_logic ().raise ();
|
|
}
|
|
BOOST_UBLAS_INLINE
|
|
sparse_vector_element (vector_type &v, pointer it, size_type i):
|
|
container_reference<vector_type> (v), it_ (it), i_ (i), d_ (*it), dirty_ (false) {}
|
|
BOOST_UBLAS_INLINE
|
|
sparse_vector_element (vector_type &v, size_type i):
|
|
container_reference<vector_type> (v), it_ (), i_ (i), d_ (), dirty_ (false) {
|
|
pointer it = (*this) ().find_element (i_);
|
|
if (it)
|
|
d_ = *it;
|
|
}
|
|
BOOST_UBLAS_INLINE
|
|
sparse_vector_element (const sparse_vector_element &p):
|
|
container_reference<vector_type> (p), it_ (p.it_), i_ (p.i_), d_ (p.d_), dirty_ (p.dirty_) {}
|
|
BOOST_UBLAS_INLINE
|
|
~sparse_vector_element () {
|
|
if (dirty_) {
|
|
if (! it_) {
|
|
it_ = (*this) ().find_element (i_);
|
|
if (! it_)
|
|
(*this) ().insert (i_, d_);
|
|
else
|
|
*it_ = d_;
|
|
} else
|
|
*it_ = d_;
|
|
}
|
|
}
|
|
|
|
// Assignment
|
|
BOOST_UBLAS_INLINE
|
|
sparse_vector_element &operator = (const sparse_vector_element &p) {
|
|
// Overide the implict copy assignment
|
|
d_ = p.d_;
|
|
dirty_ = true;
|
|
return *this;
|
|
}
|
|
template<class D>
|
|
BOOST_UBLAS_INLINE
|
|
sparse_vector_element &operator = (const D &d) {
|
|
d_ = d;
|
|
dirty_ = true;
|
|
return *this;
|
|
}
|
|
template<class D>
|
|
BOOST_UBLAS_INLINE
|
|
sparse_vector_element &operator += (const D &d) {
|
|
d_ += d;
|
|
dirty_ = true;
|
|
return *this;
|
|
}
|
|
template<class D>
|
|
BOOST_UBLAS_INLINE
|
|
sparse_vector_element &operator -= (const D &d) {
|
|
d_ -= d;
|
|
dirty_ = true;
|
|
return *this;
|
|
}
|
|
template<class D>
|
|
BOOST_UBLAS_INLINE
|
|
sparse_vector_element &operator *= (const D &d) {
|
|
d_ *= d;
|
|
dirty_ = true;
|
|
return *this;
|
|
}
|
|
template<class D>
|
|
BOOST_UBLAS_INLINE
|
|
sparse_vector_element &operator /= (const D &d) {
|
|
d_ /= d;
|
|
dirty_ = true;
|
|
return *this;
|
|
}
|
|
|
|
// Comparison
|
|
template<class D>
|
|
BOOST_UBLAS_INLINE
|
|
bool operator == (const D &d) const {
|
|
return d_ == d;
|
|
}
|
|
template<class D>
|
|
BOOST_UBLAS_INLINE
|
|
bool operator != (const D &d) const {
|
|
return d_ != d;
|
|
}
|
|
|
|
// Conversion
|
|
BOOST_UBLAS_INLINE
|
|
operator const_reference () const {
|
|
return d_;
|
|
}
|
|
// Swapping
|
|
BOOST_UBLAS_INLINE
|
|
void swap (sparse_vector_element p) {
|
|
if (this != &p) {
|
|
dirty_ = true;
|
|
p.dirty_ = true;
|
|
std::swap (d_, p.d_);
|
|
}
|
|
}
|
|
#ifndef BOOST_UBLAS_NO_MEMBER_FRIENDS
|
|
BOOST_UBLAS_INLINE
|
|
friend void swap (sparse_vector_element p1, sparse_vector_element p2) {
|
|
p1.swap (p2);
|
|
}
|
|
#endif
|
|
|
|
private:
|
|
pointer it_;
|
|
size_type i_;
|
|
value_type d_;
|
|
bool dirty_;
|
|
};
|
|
|
|
template<class V>
|
|
struct type_traits<sparse_vector_element<V> > {
|
|
typedef typename V::value_type element_type;
|
|
typedef type_traits<sparse_vector_element<V> > self_type;
|
|
typedef typename type_traits<element_type>::value_type value_type;
|
|
typedef typename type_traits<element_type>::const_reference const_reference;
|
|
typedef sparse_vector_element<V> reference;
|
|
typedef typename type_traits<element_type>::real_type real_type;
|
|
typedef typename type_traits<element_type>::precision_type precision_type;
|
|
|
|
BOOST_STATIC_CONSTANT (std::size_t, plus_complexity = type_traits<element_type>::plus_complexity);
|
|
BOOST_STATIC_CONSTANT (std::size_t, multiplies_complexity = type_traits<element_type>::multiplies_complexity);
|
|
|
|
static
|
|
BOOST_UBLAS_INLINE
|
|
real_type real (const_reference t) {
|
|
return type_traits<element_type>::real (t);
|
|
}
|
|
static
|
|
BOOST_UBLAS_INLINE
|
|
real_type imag (const_reference t) {
|
|
return type_traits<element_type>::imag (t);
|
|
}
|
|
static
|
|
BOOST_UBLAS_INLINE
|
|
value_type conj (const_reference t) {
|
|
return type_traits<element_type>::conj (t);
|
|
}
|
|
|
|
static
|
|
BOOST_UBLAS_INLINE
|
|
real_type abs (const_reference t) {
|
|
return type_traits<element_type>::abs (t);
|
|
}
|
|
static
|
|
BOOST_UBLAS_INLINE
|
|
value_type sqrt (const_reference t) {
|
|
return type_traits<element_type>::sqrt (t);
|
|
}
|
|
|
|
static
|
|
BOOST_UBLAS_INLINE
|
|
real_type norm_1 (const_reference t) {
|
|
return type_traits<element_type>::norm_1 (t);
|
|
}
|
|
static
|
|
BOOST_UBLAS_INLINE
|
|
real_type norm_2 (const_reference t) {
|
|
return type_traits<element_type>::norm_2 (t);
|
|
}
|
|
static
|
|
BOOST_UBLAS_INLINE
|
|
real_type norm_inf (const_reference t) {
|
|
return type_traits<element_type>::norm_inf (t);
|
|
}
|
|
|
|
static
|
|
BOOST_UBLAS_INLINE
|
|
bool equals (const_reference t1, const_reference t2) {
|
|
return type_traits<element_type>::equals (t1, t2);
|
|
}
|
|
};
|
|
|
|
template<class V1, class T2>
|
|
struct promote_traits<sparse_vector_element<V1>, T2> {
|
|
typedef typename promote_traits<typename sparse_vector_element<V1>::value_type, T2>::promote_type promote_type;
|
|
};
|
|
template<class T1, class V2>
|
|
struct promote_traits<T1, sparse_vector_element<V2> > {
|
|
typedef typename promote_traits<T1, typename sparse_vector_element<V2>::value_type>::promote_type promote_type;
|
|
};
|
|
template<class V1, class V2>
|
|
struct promote_traits<sparse_vector_element<V1>, sparse_vector_element<V2> > {
|
|
typedef typename promote_traits<typename sparse_vector_element<V1>::value_type,
|
|
typename sparse_vector_element<V2>::value_type>::promote_type promote_type;
|
|
};
|
|
|
|
#endif
|
|
|
|
// Array based sparse vector class
|
|
template<class T, class A>
|
|
class sparse_vector:
|
|
public vector_expression<sparse_vector<T, A> > {
|
|
public:
|
|
#ifndef BOOST_UBLAS_NO_PROXY_SHORTCUTS
|
|
BOOST_UBLAS_USING vector_expression<sparse_vector<T, A> >::operator ();
|
|
#endif
|
|
typedef std::size_t size_type;
|
|
typedef std::ptrdiff_t difference_type;
|
|
typedef T value_type;
|
|
typedef const value_type &const_reference;
|
|
#if ! defined (BOOST_UBLAS_STRICT_STORAGE_SPARSE) && ! defined (BOOST_UBLAS_STRICT_VECTOR_SPARSE)
|
|
typedef T &reference;
|
|
#elif defined (BOOST_UBLAS_STRICT_VECTOR_SPARSE)
|
|
typedef sparse_vector_element<sparse_vector<T, A> > reference;
|
|
#elif defined (BOOST_UBLAS_STRICT_STORAGE_SPARSE)
|
|
typedef typename map_traits<A>::reference reference;
|
|
#endif
|
|
typedef const T *const_pointer;
|
|
typedef T *pointer;
|
|
private:
|
|
typedef A array_type;
|
|
typedef const A const_array_type;
|
|
typedef const sparse_vector<T, A> const_self_type;
|
|
typedef sparse_vector<T, A> self_type;
|
|
public:
|
|
#ifndef BOOST_UBLAS_CT_REFERENCE_BASE_TYPEDEFS
|
|
typedef const vector_const_reference<const_self_type> const_closure_type;
|
|
#else
|
|
typedef const vector_reference<const_self_type> const_closure_type;
|
|
#endif
|
|
typedef vector_reference<self_type> closure_type;
|
|
typedef sparse_tag storage_category;
|
|
|
|
// Construction and destruction
|
|
BOOST_UBLAS_INLINE
|
|
sparse_vector ():
|
|
vector_expression<self_type> (),
|
|
size_ (0), non_zeros_ (0), data_ () {}
|
|
BOOST_UBLAS_INLINE
|
|
sparse_vector (size_type size, size_type non_zeros = 0):
|
|
vector_expression<self_type> (),
|
|
size_ (size), non_zeros_ (non_zeros), data_ () {
|
|
reserve (non_zeros_);
|
|
}
|
|
BOOST_UBLAS_INLINE
|
|
sparse_vector (const sparse_vector &v):
|
|
vector_expression<self_type> (),
|
|
size_ (v.size_), non_zeros_ (v.non_zeros_), data_ (v.data_) {}
|
|
template<class AE>
|
|
BOOST_UBLAS_INLINE
|
|
sparse_vector (const vector_expression<AE> &ae, size_type non_zeros = 0):
|
|
vector_expression<self_type> (),
|
|
size_ (ae ().size ()), non_zeros_ (non_zeros), data_ () {
|
|
reserve (non_zeros_);
|
|
vector_assign (scalar_assign<reference, BOOST_UBLAS_TYPENAME AE::value_type> (), *this, ae);
|
|
}
|
|
|
|
// Accessors
|
|
BOOST_UBLAS_INLINE
|
|
size_type size () const {
|
|
return size_;
|
|
}
|
|
BOOST_UBLAS_INLINE
|
|
size_type non_zeros () const {
|
|
return data_.size ();
|
|
}
|
|
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 size, size_type non_zeros = 0) {
|
|
size_ = size;
|
|
non_zeros_ = (std::max) (non_zeros, size_type (1));
|
|
non_zeros_ = (std::min) (non_zeros_, size_);
|
|
detail::reserve (data (), non_zeros_);
|
|
data ().clear ();
|
|
}
|
|
|
|
// Reserving
|
|
BOOST_UBLAS_INLINE
|
|
void reserve (size_type non_zeros = 0) {
|
|
non_zeros_ = (std::max) (non_zeros, size_type (1));
|
|
non_zeros_ = (std::min) (non_zeros_, size_);
|
|
detail::reserve (data (), non_zeros_);
|
|
}
|
|
|
|
// Proxy support
|
|
#ifdef BOOST_UBLAS_STRICT_VECTOR_SPARSE
|
|
pointer find_element (size_type i) {
|
|
iterator_type it (data ().find (i));
|
|
if (it == data ().end () || (*it).first != i)
|
|
return 0;
|
|
return &(*it).second;
|
|
}
|
|
#endif
|
|
|
|
// Element access
|
|
BOOST_UBLAS_INLINE
|
|
const_reference operator () (size_type i) const {
|
|
BOOST_UBLAS_CHECK (i < size_, bad_index ());
|
|
const_iterator_type it (data ().find (i));
|
|
if (it == data ().end () || (*it).first != i)
|
|
return zero_;
|
|
return (*it).second;
|
|
}
|
|
BOOST_UBLAS_INLINE
|
|
reference operator () (size_type i) {
|
|
BOOST_UBLAS_CHECK (i < size_, bad_index ());
|
|
#ifndef BOOST_UBLAS_STRICT_VECTOR_SPARSE
|
|
return data () [i];
|
|
#else
|
|
return reference (*this, i);
|
|
#endif
|
|
}
|
|
|
|
BOOST_UBLAS_INLINE
|
|
const_reference operator [] (size_type i) const {
|
|
return (*this) (i);
|
|
}
|
|
BOOST_UBLAS_INLINE
|
|
reference operator [] (size_type i) {
|
|
return (*this) (i);
|
|
}
|
|
|
|
// Assignment
|
|
BOOST_UBLAS_INLINE
|
|
sparse_vector &operator = (const sparse_vector &v) {
|
|
if (this != &v) {
|
|
size_ = v.size_;
|
|
non_zeros_ = v.non_zeros_;
|
|
data () = v.data ();
|
|
}
|
|
return *this;
|
|
}
|
|
BOOST_UBLAS_INLINE
|
|
sparse_vector &assign_temporary (sparse_vector &v) {
|
|
swap (v);
|
|
return *this;
|
|
}
|
|
template<class AE>
|
|
BOOST_UBLAS_INLINE
|
|
sparse_vector &operator = (const vector_expression<AE> &ae) {
|
|
#ifdef BOOST_UBLAS_MUTABLE_TEMPORARY
|
|
return assign_temporary (self_type (ae, non_zeros_));
|
|
#else
|
|
// return assign (self_type (ae, non_zeros_));
|
|
self_type temporary (ae, non_zeros_);
|
|
return assign_temporary (temporary);
|
|
#endif
|
|
}
|
|
template<class AE>
|
|
BOOST_UBLAS_INLINE
|
|
sparse_vector &reset (const vector_expression<AE> &ae) {
|
|
self_type temporary (ae, non_zeros_);
|
|
resize (temporary.size (), non_zeros_);
|
|
return assign_temporary (temporary);
|
|
}
|
|
template<class AE>
|
|
BOOST_UBLAS_INLINE
|
|
sparse_vector &assign (const vector_expression<AE> &ae) {
|
|
vector_assign (scalar_assign<reference, BOOST_UBLAS_TYPENAME AE::value_type> (), *this, ae);
|
|
return *this;
|
|
}
|
|
template<class AE>
|
|
BOOST_UBLAS_INLINE
|
|
sparse_vector &operator += (const vector_expression<AE> &ae) {
|
|
#ifdef BOOST_UBLAS_MUTABLE_TEMPORARY
|
|
return assign_temporary (self_type (*this + ae, non_zeros_));
|
|
#else
|
|
// return assign (self_type (*this + ae, non_zeros_));
|
|
self_type temporary (*this + ae, non_zeros_);
|
|
return assign_temporary (temporary);
|
|
#endif
|
|
}
|
|
template<class AE>
|
|
BOOST_UBLAS_INLINE
|
|
sparse_vector &plus_assign (const vector_expression<AE> &ae) {
|
|
vector_assign (scalar_plus_assign<reference, BOOST_UBLAS_TYPENAME AE::value_type> (), *this, ae);
|
|
return *this;
|
|
}
|
|
template<class AE>
|
|
BOOST_UBLAS_INLINE
|
|
sparse_vector &operator -= (const vector_expression<AE> &ae) {
|
|
#ifdef BOOST_UBLAS_MUTABLE_TEMPORARY
|
|
return assign_temporary (self_type (*this - ae, non_zeros_));
|
|
#else
|
|
// return assign (self_type (*this - ae, non_zeros_));
|
|
self_type temporary (*this - ae, non_zeros_);
|
|
return assign_temporary (temporary);
|
|
#endif
|
|
}
|
|
template<class AE>
|
|
BOOST_UBLAS_INLINE
|
|
sparse_vector &minus_assign (const vector_expression<AE> &ae) {
|
|
vector_assign (scalar_minus_assign<reference, BOOST_UBLAS_TYPENAME AE::value_type> (), *this, ae);
|
|
return *this;
|
|
}
|
|
template<class AT>
|
|
BOOST_UBLAS_INLINE
|
|
sparse_vector &operator *= (const AT &at) {
|
|
vector_assign_scalar (scalar_multiplies_assign<reference, AT> (), *this, at);
|
|
return *this;
|
|
}
|
|
template<class AT>
|
|
BOOST_UBLAS_INLINE
|
|
sparse_vector &operator /= (const AT &at) {
|
|
vector_assign_scalar (scalar_divides_assign<reference, AT> (), *this, at);
|
|
return *this;
|
|
}
|
|
|
|
// Swapping
|
|
BOOST_UBLAS_INLINE
|
|
void swap (sparse_vector &v) {
|
|
if (this != &v) {
|
|
std::swap (size_, v.size_);
|
|
std::swap (non_zeros_, v.non_zeros_);
|
|
data ().swap (v.data ());
|
|
}
|
|
}
|
|
#ifndef BOOST_UBLAS_NO_MEMBER_FRIENDS
|
|
BOOST_UBLAS_INLINE
|
|
friend void swap (sparse_vector &v1, sparse_vector &v2) {
|
|
v1.swap (v2);
|
|
}
|
|
#endif
|
|
|
|
// Element insertion and erasure
|
|
BOOST_UBLAS_INLINE
|
|
void insert (size_type i, const_reference t) {
|
|
BOOST_UBLAS_CHECK (data ().find (i) == data ().end (), bad_index ());
|
|
data ().insert (data ().end (), std::pair<size_type, value_type> (i, t));
|
|
}
|
|
BOOST_UBLAS_INLINE
|
|
void erase (size_type i) {
|
|
// FIXME: shouldn't we use const_iterator_type here?
|
|
iterator_type it = data ().find (i);
|
|
if (it == data ().end ())
|
|
return;
|
|
data ().erase (it);
|
|
}
|
|
BOOST_UBLAS_INLINE
|
|
void clear () {
|
|
data ().clear ();
|
|
}
|
|
|
|
// Iterator types
|
|
private:
|
|
// Use storage iterator
|
|
typedef typename A::const_iterator const_iterator_type;
|
|
typedef typename A::iterator iterator_type;
|
|
|
|
public:
|
|
class const_iterator;
|
|
class iterator;
|
|
|
|
// Element lookup
|
|
// This function seems to be big. So we do not let the compiler inline it.
|
|
// BOOST_UBLAS_INLINE
|
|
const_iterator find (size_type i) const {
|
|
return const_iterator (*this, data ().lower_bound (i));
|
|
}
|
|
// This function seems to be big. So we do not let the compiler inline it.
|
|
// BOOST_UBLAS_INLINE
|
|
iterator find (size_type i) {
|
|
return iterator (*this, data ().lower_bound (i));
|
|
}
|
|
|
|
|
|
class const_iterator:
|
|
public container_const_reference<sparse_vector>,
|
|
public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
|
|
const_iterator, value_type> {
|
|
public:
|
|
typedef sparse_bidirectional_iterator_tag iterator_category;
|
|
#ifdef BOOST_MSVC_STD_ITERATOR
|
|
typedef const_reference reference;
|
|
#else
|
|
typedef typename sparse_vector::difference_type difference_type;
|
|
typedef typename sparse_vector::value_type value_type;
|
|
typedef typename sparse_vector::const_reference reference;
|
|
typedef typename sparse_vector::const_pointer pointer;
|
|
#endif
|
|
|
|
// Construction and destruction
|
|
BOOST_UBLAS_INLINE
|
|
const_iterator ():
|
|
container_const_reference<self_type> (), it_ () {}
|
|
BOOST_UBLAS_INLINE
|
|
const_iterator (const self_type &v, const const_iterator_type &it):
|
|
container_const_reference<self_type> (v), it_ (it) {}
|
|
#ifndef BOOST_UBLAS_QUALIFIED_TYPENAME
|
|
BOOST_UBLAS_INLINE
|
|
const_iterator (const iterator &it):
|
|
container_const_reference<self_type> (it ()), it_ (it.it_) {}
|
|
#else
|
|
BOOST_UBLAS_INLINE
|
|
const_iterator (const typename self_type::iterator &it):
|
|
container_const_reference<self_type> (it ()), it_ (it.it_) {}
|
|
#endif
|
|
// Arithmetic
|
|
BOOST_UBLAS_INLINE
|
|
const_iterator &operator ++ () {
|
|
++ it_;
|
|
return *this;
|
|
}
|
|
BOOST_UBLAS_INLINE
|
|
const_iterator &operator -- () {
|
|
-- it_;
|
|
return *this;
|
|
}
|
|
|
|
// Dereference
|
|
BOOST_UBLAS_INLINE
|
|
const_reference operator * () const {
|
|
BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
|
|
return (*it_).second;
|
|
}
|
|
|
|
// Index
|
|
BOOST_UBLAS_INLINE
|
|
size_type index () const {
|
|
BOOST_UBLAS_CHECK (*this != (*this) ().end (), bad_index ());
|
|
BOOST_UBLAS_CHECK ((*it_).first < (*this) ().size (), bad_index ());
|
|
return (*it_).first;
|
|
}
|
|
|
|
// Assignment
|
|
BOOST_UBLAS_INLINE
|
|
const_iterator &operator = (const const_iterator &it) {
|
|
container_const_reference<self_type>::assign (&it ());
|
|
it_ = it.it_;
|
|
return *this;
|
|
}
|
|
|
|
// Comparison
|
|
BOOST_UBLAS_INLINE
|
|
bool operator == (const const_iterator &it) const {
|
|
BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
|
|
return it_ == it.it_;
|
|
}
|
|
|
|
private:
|
|
const_iterator_type it_;
|
|
};
|
|
|
|
BOOST_UBLAS_INLINE
|
|
const_iterator begin () const {
|
|
return const_iterator (*this, data ().begin ());
|
|
}
|
|
BOOST_UBLAS_INLINE
|
|
const_iterator end () const {
|
|
return const_iterator (*this, data ().end ());
|
|
}
|
|
|
|
class iterator:
|
|
public container_reference<sparse_vector>,
|
|
public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
|
|
iterator, value_type> {
|
|
public:
|
|
typedef sparse_bidirectional_iterator_tag iterator_category;
|
|
#ifndef BOOST_MSVC_STD_ITERATOR
|
|
typedef typename sparse_vector::difference_type difference_type;
|
|
typedef typename sparse_vector::value_type value_type;
|
|
typedef typename sparse_vector::reference reference;
|
|
typedef typename sparse_vector::pointer pointer;
|
|
#endif
|
|
|
|
// Construction and destruction
|
|
BOOST_UBLAS_INLINE
|
|
iterator ():
|
|
container_reference<self_type> (), it_ () {}
|
|
BOOST_UBLAS_INLINE
|
|
iterator (self_type &v, const iterator_type &it):
|
|
container_reference<self_type> (v), it_ (it) {}
|
|
|
|
// Arithmetic
|
|
BOOST_UBLAS_INLINE
|
|
iterator &operator ++ () {
|
|
++ it_;
|
|
return *this;
|
|
}
|
|
BOOST_UBLAS_INLINE
|
|
iterator &operator -- () {
|
|
-- it_;
|
|
return *this;
|
|
}
|
|
|
|
// Dereference
|
|
BOOST_UBLAS_INLINE
|
|
reference operator * () const {
|
|
BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
|
|
#if ! defined (BOOST_UBLAS_STRICT_STORAGE_SPARSE) && ! defined (BOOST_UBLAS_STRICT_VECTOR_SPARSE)
|
|
return (*it_).second;
|
|
#elif defined (BOOST_UBLAS_STRICT_VECTOR_SPARSE)
|
|
return reference ((*this) (), &(*it_).second, index ());
|
|
#elif defined (BOOST_UBLAS_STRICT_STORAGE_SPARSE)
|
|
return detail::make_reference ((*this) ().data (), it_);
|
|
#endif
|
|
}
|
|
|
|
// Index
|
|
BOOST_UBLAS_INLINE
|
|
size_type index () const {
|
|
BOOST_UBLAS_CHECK (*this != (*this) ().end (), bad_index ());
|
|
BOOST_UBLAS_CHECK ((*it_).first < (*this) ().size (), bad_index ());
|
|
return (*it_).first;
|
|
}
|
|
|
|
// Assignment
|
|
BOOST_UBLAS_INLINE
|
|
iterator &operator = (const iterator &it) {
|
|
container_reference<self_type>::assign (&it ());
|
|
it_ = it.it_;
|
|
return *this;
|
|
}
|
|
|
|
// Comparison
|
|
BOOST_UBLAS_INLINE
|
|
bool operator == (const iterator &it) const {
|
|
BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
|
|
return it_ == it.it_;
|
|
}
|
|
|
|
private:
|
|
iterator_type it_;
|
|
|
|
friend class const_iterator;
|
|
};
|
|
|
|
BOOST_UBLAS_INLINE
|
|
iterator begin () {
|
|
return iterator (*this, data ().begin ());
|
|
}
|
|
BOOST_UBLAS_INLINE
|
|
iterator end () {
|
|
return iterator (*this, data ().end ());
|
|
}
|
|
|
|
// Reverse iterator
|
|
|
|
#ifdef BOOST_MSVC_STD_ITERATOR
|
|
typedef reverse_iterator_base<const_iterator, value_type, const_reference> const_reverse_iterator;
|
|
#else
|
|
typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
|
|
#endif
|
|
|
|
BOOST_UBLAS_INLINE
|
|
const_reverse_iterator rbegin () const {
|
|
return const_reverse_iterator (end ());
|
|
}
|
|
BOOST_UBLAS_INLINE
|
|
const_reverse_iterator rend () const {
|
|
return const_reverse_iterator (begin ());
|
|
}
|
|
|
|
#ifdef BOOST_MSVC_STD_ITERATOR
|
|
typedef reverse_iterator_base<iterator, value_type, reference> reverse_iterator;
|
|
#else
|
|
typedef reverse_iterator_base<iterator> reverse_iterator;
|
|
#endif
|
|
|
|
BOOST_UBLAS_INLINE
|
|
reverse_iterator rbegin () {
|
|
return reverse_iterator (end ());
|
|
}
|
|
BOOST_UBLAS_INLINE
|
|
reverse_iterator rend () {
|
|
return reverse_iterator (begin ());
|
|
}
|
|
|
|
private:
|
|
size_type size_;
|
|
size_type non_zeros_;
|
|
array_type data_;
|
|
static const value_type zero_;
|
|
};
|
|
|
|
template<class T, class A>
|
|
const typename sparse_vector<T, A>::value_type sparse_vector<T, A>::zero_
|
|
#ifdef BOOST_UBLAS_STATIC_OLD_INIT
|
|
= BOOST_UBLAS_TYPENAME sparse_vector<T, A>::value_type
|
|
#endif
|
|
(0);
|
|
|
|
// Array based sparse vector class
|
|
// Thanks to Kresimir Fresl for extending this to cover different index bases.
|
|
template<class T, std::size_t IB, class IA, class TA>
|
|
class compressed_vector:
|
|
public vector_expression<compressed_vector<T, IB, IA, TA> > {
|
|
public:
|
|
#ifndef BOOST_UBLAS_NO_PROXY_SHORTCUTS
|
|
BOOST_UBLAS_USING vector_expression<compressed_vector<T, IB, IA, TA> >::operator ();
|
|
#endif
|
|
typedef std::size_t size_type;
|
|
typedef std::ptrdiff_t difference_type;
|
|
typedef T value_type;
|
|
typedef const T &const_reference;
|
|
#ifndef BOOST_UBLAS_STRICT_VECTOR_SPARSE
|
|
typedef T &reference;
|
|
#else
|
|
typedef sparse_vector_element<compressed_vector<T, IB, IA, TA> > reference;
|
|
#endif
|
|
typedef const T *const_pointer;
|
|
typedef T *pointer;
|
|
private:
|
|
typedef IA index_array_type;
|
|
typedef TA value_array_type;
|
|
typedef const compressed_vector<T, IB, IA, TA> const_self_type;
|
|
typedef compressed_vector<T, IB, IA, TA> self_type;
|
|
public:
|
|
#ifndef BOOST_UBLAS_CT_REFERENCE_BASE_TYPEDEFS
|
|
typedef const vector_const_reference<const_self_type> const_closure_type;
|
|
#else
|
|
typedef const vector_reference<const_self_type> const_closure_type;
|
|
#endif
|
|
typedef vector_reference<self_type> closure_type;
|
|
typedef sparse_tag storage_category;
|
|
|
|
// Construction and destruction
|
|
BOOST_UBLAS_INLINE
|
|
compressed_vector ():
|
|
vector_expression<self_type> (),
|
|
size_ (0), non_zeros_ (0), filled_ (0),
|
|
index_data_ (), value_data_ () {}
|
|
BOOST_UBLAS_INLINE
|
|
compressed_vector (size_type size, size_type non_zeros = 0):
|
|
vector_expression<self_type> (),
|
|
size_ (size), non_zeros_ (non_zeros), filled_ (0),
|
|
index_data_ (non_zeros), value_data_ (non_zeros) {
|
|
reserve (non_zeros_);
|
|
}
|
|
BOOST_UBLAS_INLINE
|
|
compressed_vector (const compressed_vector &v):
|
|
vector_expression<self_type> (),
|
|
size_ (v.size_), non_zeros_ (v.non_zeros_), filled_ (v.filled_),
|
|
index_data_ (v.index_data_), value_data_ (v.value_data_) {}
|
|
template<class AE>
|
|
BOOST_UBLAS_INLINE
|
|
compressed_vector (const vector_expression<AE> &ae, size_type non_zeros = 0):
|
|
vector_expression<self_type> (),
|
|
size_ (ae ().size ()), non_zeros_ (non_zeros), filled_ (0),
|
|
index_data_ (non_zeros), value_data_ (non_zeros) {
|
|
reserve (non_zeros_, false);
|
|
vector_assign (scalar_assign<reference, BOOST_UBLAS_TYPENAME AE::value_type> (), *this, ae);
|
|
}
|
|
|
|
// Accessors
|
|
BOOST_UBLAS_INLINE
|
|
size_type size () const {
|
|
return size_;
|
|
}
|
|
BOOST_UBLAS_INLINE
|
|
size_type non_zeros () const {
|
|
return non_zeros_;
|
|
}
|
|
BOOST_UBLAS_INLINE
|
|
size_type filled () const {
|
|
return filled_;
|
|
}
|
|
BOOST_UBLAS_INLINE
|
|
static size_type index_base () {
|
|
return IB;
|
|
}
|
|
BOOST_UBLAS_INLINE
|
|
const index_array_type &index_data () const {
|
|
return index_data_;
|
|
}
|
|
BOOST_UBLAS_INLINE
|
|
index_array_type &index_data () {
|
|
return index_data_;
|
|
}
|
|
BOOST_UBLAS_INLINE
|
|
const value_array_type &value_data () const {
|
|
return value_data_;
|
|
}
|
|
BOOST_UBLAS_INLINE
|
|
value_array_type &value_data () {
|
|
return value_data_;
|
|
}
|
|
|
|
// Resizing
|
|
BOOST_UBLAS_INLINE
|
|
void resize (size_type size, size_type non_zeros = 0, bool preserve = true) {
|
|
size_ = size;
|
|
non_zeros_ = (std::max) (non_zeros, size_type (1));
|
|
non_zeros_ = (std::min) (non_zeros_, size_);
|
|
filled_ = 0;
|
|
detail::resize (index_data (), non_zeros_, preserve);
|
|
detail::resize (value_data (), non_zeros_, preserve);
|
|
}
|
|
|
|
// Reserving
|
|
BOOST_UBLAS_INLINE
|
|
void reserve (size_type non_zeros = 0, bool preserve = true) {
|
|
non_zeros_ = (std::max) (non_zeros, size_type (1));
|
|
non_zeros_ = (std::min) (non_zeros_, size_);
|
|
detail::resize (index_data (), non_zeros_, preserve);
|
|
detail::resize (value_data (), non_zeros_, preserve);
|
|
}
|
|
|
|
// Proxy support
|
|
#ifdef BOOST_UBLAS_STRICT_VECTOR_SPARSE
|
|
pointer find_element (size_type i) {
|
|
iterator_type it (detail::lower_bound (index_data ().begin (), index_data ().begin () + filled_, k_based (i), std::less<size_type> ()));
|
|
if (it == index_data ().begin () + filled_ || *it != k_based (i))
|
|
return 0;
|
|
return &value_data () [it - index_data ().begin ()];
|
|
}
|
|
#endif
|
|
|
|
// Element access
|
|
BOOST_UBLAS_INLINE
|
|
const_reference operator () (size_type i) const {
|
|
BOOST_UBLAS_CHECK (i < size_, bad_index ());
|
|
const_iterator_type it (detail::lower_bound (index_data ().begin (), index_data ().begin () + filled_, k_based (i), std::less<size_type> ()));
|
|
if (it == index_data ().begin () + filled_ || *it != k_based (i))
|
|
return zero_;
|
|
return value_data () [it - index_data ().begin ()];
|
|
}
|
|
BOOST_UBLAS_INLINE
|
|
reference operator () (size_type i) {
|
|
BOOST_UBLAS_CHECK (i < size_, bad_index ());
|
|
#ifndef BOOST_UBLAS_STRICT_VECTOR_SPARSE
|
|
iterator_type it (detail::lower_bound (index_data ().begin (), index_data ().begin () + filled_, k_based (i), std::less<size_type> ()));
|
|
if (it == index_data ().begin () + filled_ || *it != k_based (i)) {
|
|
insert (i, value_type ());
|
|
it = detail::lower_bound (index_data ().begin (), index_data ().begin () + filled_, k_based (i), std::less<size_type> ());
|
|
}
|
|
return value_data () [it - index_data ().begin ()];
|
|
#else
|
|
return reference (*this, i);
|
|
#endif
|
|
}
|
|
|
|
BOOST_UBLAS_INLINE
|
|
const_reference operator [] (size_type i) const {
|
|
return (*this) (i);
|
|
}
|
|
BOOST_UBLAS_INLINE
|
|
reference operator [] (size_type i) {
|
|
return (*this) (i);
|
|
}
|
|
|
|
// Assignment
|
|
BOOST_UBLAS_INLINE
|
|
compressed_vector &operator = (const compressed_vector &v) {
|
|
if (this != &v) {
|
|
size_ = v.size_;
|
|
non_zeros_ = v.non_zeros_;
|
|
filled_ = v.filled_;
|
|
detail::resize (index_data (), non_zeros_, false);
|
|
detail::resize (value_data (), non_zeros_, false);
|
|
index_data () = v.index_data ();
|
|
value_data () = v.value_data ();
|
|
}
|
|
return *this;
|
|
}
|
|
BOOST_UBLAS_INLINE
|
|
compressed_vector &assign_temporary (compressed_vector &v) {
|
|
swap (v);
|
|
return *this;
|
|
}
|
|
template<class AE>
|
|
BOOST_UBLAS_INLINE
|
|
compressed_vector &operator = (const vector_expression<AE> &ae) {
|
|
#ifdef BOOST_UBLAS_MUTABLE_TEMPORARY
|
|
return assign_temporary (self_type (ae, non_zeros_));
|
|
#else
|
|
// return assign (self_type (ae, non_zeros_));
|
|
self_type temporary (ae, non_zeros_);
|
|
return assign_temporary (temporary);
|
|
#endif
|
|
}
|
|
template<class AE>
|
|
BOOST_UBLAS_INLINE
|
|
compressed_vector &reset (const vector_expression<AE> &ae) {
|
|
self_type temporary (ae, non_zeros_);
|
|
resize (temporary.size (), non_zeros_, false);
|
|
return assign_temporary (temporary);
|
|
}
|
|
template<class AE>
|
|
BOOST_UBLAS_INLINE
|
|
compressed_vector &assign (const vector_expression<AE> &ae) {
|
|
vector_assign (scalar_assign<reference, BOOST_UBLAS_TYPENAME AE::value_type> (), *this, ae);
|
|
return *this;
|
|
}
|
|
template<class AE>
|
|
BOOST_UBLAS_INLINE
|
|
compressed_vector &operator += (const vector_expression<AE> &ae) {
|
|
#ifdef BOOST_UBLAS_MUTABLE_TEMPORARY
|
|
return assign_temporary (self_type (*this + ae, non_zeros_));
|
|
#else
|
|
// return assign (self_type (*this + ae, non_zeros_));
|
|
self_type temporary (*this + ae, non_zeros_);
|
|
return assign_temporary (temporary);
|
|
#endif
|
|
}
|
|
template<class AE>
|
|
BOOST_UBLAS_INLINE
|
|
compressed_vector &plus_assign (const vector_expression<AE> &ae) {
|
|
vector_assign (scalar_plus_assign<reference, BOOST_UBLAS_TYPENAME AE::value_type> (), *this, ae);
|
|
return *this;
|
|
}
|
|
template<class AE>
|
|
BOOST_UBLAS_INLINE
|
|
compressed_vector &operator -= (const vector_expression<AE> &ae) {
|
|
#ifdef BOOST_UBLAS_MUTABLE_TEMPORARY
|
|
return assign_temporary (self_type (*this - ae, non_zeros_));
|
|
#else
|
|
// return assign (self_type (*this - ae, non_zeros_));
|
|
self_type temporary (*this - ae, non_zeros_);
|
|
return assign_temporary (temporary);
|
|
#endif
|
|
}
|
|
template<class AE>
|
|
BOOST_UBLAS_INLINE
|
|
compressed_vector &minus_assign (const vector_expression<AE> &ae) {
|
|
vector_assign (scalar_minus_assign<reference, BOOST_UBLAS_TYPENAME AE::value_type> (), *this, ae);
|
|
return *this;
|
|
}
|
|
template<class AT>
|
|
BOOST_UBLAS_INLINE
|
|
compressed_vector &operator *= (const AT &at) {
|
|
vector_assign_scalar (scalar_multiplies_assign<reference, AT> (), *this, at);
|
|
return *this;
|
|
}
|
|
template<class AT>
|
|
BOOST_UBLAS_INLINE
|
|
compressed_vector &operator /= (const AT &at) {
|
|
vector_assign_scalar (scalar_divides_assign<reference, AT> (), *this, at);
|
|
return *this;
|
|
}
|
|
|
|
// Swapping
|
|
BOOST_UBLAS_INLINE
|
|
void swap (compressed_vector &v) {
|
|
if (this != &v) {
|
|
std::swap (size_, v.size_);
|
|
std::swap (non_zeros_, v.non_zeros_);
|
|
std::swap (filled_, v.filled_);
|
|
index_data ().swap (v.index_data ());
|
|
value_data ().swap (v.value_data ());
|
|
}
|
|
}
|
|
#ifndef BOOST_UBLAS_NO_MEMBER_FRIENDS
|
|
BOOST_UBLAS_INLINE
|
|
friend void swap (compressed_vector &v1, compressed_vector &v2) {
|
|
v1.swap (v2);
|
|
}
|
|
#endif
|
|
|
|
// Element insertion and erasure
|
|
BOOST_UBLAS_INLINE
|
|
void push_back (size_type i, const_reference t) {
|
|
if (filled_ >= non_zeros_)
|
|
reserve (2 * non_zeros_);
|
|
if (filled_ == 0 || index_data () [filled_ - 1] < k_based (i)) {
|
|
++ filled_;
|
|
index_data () [filled_ - 1] = k_based (i);
|
|
value_data () [filled_ - 1] = t;
|
|
return;
|
|
}
|
|
external_logic ().raise ();
|
|
}
|
|
BOOST_UBLAS_INLINE
|
|
void insert (size_type i, const_reference t) {
|
|
if (filled_ >= non_zeros_)
|
|
reserve (2 * non_zeros_);
|
|
iterator_type it (detail::lower_bound (index_data ().begin (), index_data ().begin () + filled_, k_based (i), std::less<size_type> ()));
|
|
difference_type n = it - index_data ().begin ();
|
|
BOOST_UBLAS_CHECK (filled_ == 0 || filled_ == size_type (n) || *it != k_based (i), external_logic ());
|
|
++ filled_;
|
|
it = index_data ().begin () + n;
|
|
std::copy_backward (it, index_data ().begin () + filled_ - 1, index_data ().begin () + filled_);
|
|
*it = k_based (i);
|
|
typename value_array_type::iterator itt (value_data ().begin () + n);
|
|
std::copy_backward (itt, value_data ().begin () + filled_ - 1, value_data ().begin () + filled_);
|
|
*itt = t;
|
|
}
|
|
BOOST_UBLAS_INLINE
|
|
void pop_back () {
|
|
BOOST_UBLAS_CHECK (filled_ > 0, external_logic ());
|
|
-- filled_;
|
|
}
|
|
BOOST_UBLAS_INLINE
|
|
void erase (size_type i) {
|
|
iterator_type it (detail::lower_bound (index_data ().begin (), index_data ().begin () + filled_, k_based (i), std::less<size_type> ()));
|
|
difference_type n = it - index_data ().begin ();
|
|
if (filled_ > size_type (n) && *it == k_based (i)) {
|
|
std::copy (it + 1, index_data ().begin () + filled_, it);
|
|
typename value_array_type::iterator itt (value_data ().begin () + n);
|
|
std::copy (itt + 1, value_data ().begin () + filled_, itt);
|
|
-- filled_;
|
|
}
|
|
}
|
|
BOOST_UBLAS_INLINE
|
|
void clear () {
|
|
filled_ = 0;
|
|
}
|
|
|
|
// Iterator types
|
|
private:
|
|
// Use index array iterator
|
|
typedef typename IA::const_iterator const_iterator_type;
|
|
typedef typename IA::iterator iterator_type;
|
|
|
|
public:
|
|
class const_iterator;
|
|
class iterator;
|
|
|
|
// Element lookup
|
|
// This function seems to be big. So we do not let the compiler inline it.
|
|
// BOOST_UBLAS_INLINE
|
|
const_iterator find (size_type i) const {
|
|
return const_iterator (*this, detail::lower_bound (index_data ().begin (), index_data ().begin () + filled_, k_based (i), std::less<size_type> ()));
|
|
}
|
|
// This function seems to be big. So we do not let the compiler inline it.
|
|
// BOOST_UBLAS_INLINE
|
|
iterator find (size_type i) {
|
|
return iterator (*this, detail::lower_bound (index_data ().begin (), index_data ().begin () + filled_, k_based (i), std::less<size_type> ()));
|
|
}
|
|
|
|
|
|
class const_iterator:
|
|
public container_const_reference<compressed_vector>,
|
|
public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
|
|
const_iterator, value_type> {
|
|
public:
|
|
typedef sparse_bidirectional_iterator_tag iterator_category;
|
|
#ifdef BOOST_MSVC_STD_ITERATOR
|
|
typedef const_reference reference;
|
|
#else
|
|
typedef typename compressed_vector::difference_type difference_type;
|
|
typedef typename compressed_vector::value_type value_type;
|
|
typedef typename compressed_vector::const_reference reference;
|
|
typedef typename compressed_vector::const_pointer pointer;
|
|
#endif
|
|
|
|
// Construction and destruction
|
|
BOOST_UBLAS_INLINE
|
|
const_iterator ():
|
|
container_const_reference<self_type> (), it_ () {}
|
|
BOOST_UBLAS_INLINE
|
|
const_iterator (const self_type &v, const const_iterator_type &it):
|
|
container_const_reference<self_type> (v), it_ (it) {}
|
|
#ifndef BOOST_UBLAS_QUALIFIED_TYPENAME
|
|
BOOST_UBLAS_INLINE
|
|
const_iterator (const iterator &it):
|
|
container_const_reference<self_type> (it ()), it_ (it.it_) {}
|
|
#else
|
|
BOOST_UBLAS_INLINE
|
|
const_iterator (const typename self_type::iterator &it):
|
|
container_const_reference<self_type> (it ()), it_ (it.it_) {}
|
|
#endif
|
|
// Arithmetic
|
|
BOOST_UBLAS_INLINE
|
|
const_iterator &operator ++ () {
|
|
++ it_;
|
|
return *this;
|
|
}
|
|
BOOST_UBLAS_INLINE
|
|
const_iterator &operator -- () {
|
|
-- it_;
|
|
return *this;
|
|
}
|
|
|
|
// Dereference
|
|
BOOST_UBLAS_INLINE
|
|
const_reference operator * () const {
|
|
BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
|
|
return (*this) ().value_data () [it_ - (*this) ().index_data ().begin ()];
|
|
}
|
|
|
|
// Index
|
|
BOOST_UBLAS_INLINE
|
|
size_type index () const {
|
|
BOOST_UBLAS_CHECK (*this != (*this) ().end (), bad_index ());
|
|
BOOST_UBLAS_CHECK ((*this) ().zero_based (*it_) < (*this) ().size (), bad_index ());
|
|
return (*this) ().zero_based (*it_);
|
|
}
|
|
|
|
// Assignment
|
|
BOOST_UBLAS_INLINE
|
|
const_iterator &operator = (const const_iterator &it) {
|
|
container_const_reference<self_type>::assign (&it ());
|
|
it_ = it.it_;
|
|
return *this;
|
|
}
|
|
|
|
// Comparison
|
|
BOOST_UBLAS_INLINE
|
|
bool operator == (const const_iterator &it) const {
|
|
BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
|
|
return it_ == it.it_;
|
|
}
|
|
|
|
private:
|
|
const_iterator_type it_;
|
|
};
|
|
|
|
BOOST_UBLAS_INLINE
|
|
const_iterator begin () const {
|
|
return find (0);
|
|
}
|
|
BOOST_UBLAS_INLINE
|
|
const_iterator end () const {
|
|
return find (size_);
|
|
}
|
|
|
|
class iterator:
|
|
public container_reference<compressed_vector>,
|
|
public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
|
|
iterator, value_type> {
|
|
public:
|
|
typedef sparse_bidirectional_iterator_tag iterator_category;
|
|
#ifndef BOOST_MSVC_STD_ITERATOR
|
|
typedef typename compressed_vector::difference_type difference_type;
|
|
typedef typename compressed_vector::value_type value_type;
|
|
typedef typename compressed_vector::reference reference;
|
|
typedef typename compressed_vector::pointer pointer;
|
|
#endif
|
|
|
|
// Construction and destruction
|
|
BOOST_UBLAS_INLINE
|
|
iterator ():
|
|
container_reference<self_type> (), it_ () {}
|
|
BOOST_UBLAS_INLINE
|
|
iterator (self_type &v, const iterator_type &it):
|
|
container_reference<self_type> (v), it_ (it) {}
|
|
|
|
// Arithmetic
|
|
BOOST_UBLAS_INLINE
|
|
iterator &operator ++ () {
|
|
++ it_;
|
|
return *this;
|
|
}
|
|
BOOST_UBLAS_INLINE
|
|
iterator &operator -- () {
|
|
-- it_;
|
|
return *this;
|
|
}
|
|
|
|
// Dereference
|
|
BOOST_UBLAS_INLINE
|
|
reference operator * () const {
|
|
BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
|
|
#if ! defined (BOOST_UBLAS_STRICT_VECTOR_SPARSE)
|
|
return (*this) ().value_data () [it_ - (*this) ().index_data ().begin ()];
|
|
#else
|
|
return reference ((*this) (), &(*this) ().value_data () [it_ - (*this) ().index_data ().begin ()], index ());
|
|
#endif
|
|
}
|
|
|
|
// Index
|
|
BOOST_UBLAS_INLINE
|
|
size_type index () const {
|
|
BOOST_UBLAS_CHECK (*this != (*this) ().end (), bad_index ());
|
|
BOOST_UBLAS_CHECK ((*this) ().zero_based (*it_) < (*this) ().size (), bad_index ());
|
|
return (*this) ().zero_based (*it_);
|
|
}
|
|
|
|
// Assignment
|
|
BOOST_UBLAS_INLINE
|
|
iterator &operator = (const iterator &it) {
|
|
container_reference<self_type>::assign (&it ());
|
|
it_ = it.it_;
|
|
return *this;
|
|
}
|
|
|
|
// Comparison
|
|
BOOST_UBLAS_INLINE
|
|
bool operator == (const iterator &it) const {
|
|
BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
|
|
return it_ == it.it_;
|
|
}
|
|
|
|
private:
|
|
iterator_type it_;
|
|
|
|
friend class const_iterator;
|
|
};
|
|
|
|
BOOST_UBLAS_INLINE
|
|
iterator begin () {
|
|
return find (0);
|
|
}
|
|
BOOST_UBLAS_INLINE
|
|
iterator end () {
|
|
return find (size_);
|
|
}
|
|
|
|
// Reverse iterator
|
|
|
|
#ifdef BOOST_MSVC_STD_ITERATOR
|
|
typedef reverse_iterator_base<const_iterator, value_type, const_reference> const_reverse_iterator;
|
|
#else
|
|
typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
|
|
#endif
|
|
|
|
BOOST_UBLAS_INLINE
|
|
const_reverse_iterator rbegin () const {
|
|
return const_reverse_iterator (end ());
|
|
}
|
|
BOOST_UBLAS_INLINE
|
|
const_reverse_iterator rend () const {
|
|
return const_reverse_iterator (begin ());
|
|
}
|
|
|
|
#ifdef BOOST_MSVC_STD_ITERATOR
|
|
typedef reverse_iterator_base<iterator, value_type, reference> reverse_iterator;
|
|
#else
|
|
typedef reverse_iterator_base<iterator> reverse_iterator;
|
|
#endif
|
|
|
|
BOOST_UBLAS_INLINE
|
|
reverse_iterator rbegin () {
|
|
return reverse_iterator (end ());
|
|
}
|
|
BOOST_UBLAS_INLINE
|
|
reverse_iterator rend () {
|
|
return reverse_iterator (begin ());
|
|
}
|
|
|
|
private:
|
|
size_type size_;
|
|
size_type non_zeros_;
|
|
size_type filled_;
|
|
index_array_type index_data_;
|
|
value_array_type value_data_;
|
|
static const value_type zero_;
|
|
|
|
BOOST_UBLAS_INLINE
|
|
static size_type zero_based (size_type k_based_index) {
|
|
return k_based_index - IB;
|
|
}
|
|
BOOST_UBLAS_INLINE
|
|
static size_type k_based (size_type zero_based_index) {
|
|
return zero_based_index + IB;
|
|
}
|
|
|
|
friend class iterator;
|
|
friend class const_iterator;
|
|
};
|
|
|
|
template<class T, std::size_t IB, class IA, class TA>
|
|
const typename compressed_vector<T, IB, IA, TA>::value_type compressed_vector<T, IB, IA, TA>::zero_
|
|
#ifdef BOOST_UBLAS_STATIC_OLD_INIT
|
|
= BOOST_UBLAS_TYPENAME compressed_vector<T, IB, IA, TA>::value_type
|
|
#endif
|
|
(0);
|
|
|
|
// Array based sparse vector class
|
|
// Thanks to Kresimir Fresl for extending this to cover different index bases.
|
|
template<class T, std::size_t IB, class IA, class TA>
|
|
class coordinate_vector:
|
|
public vector_expression<coordinate_vector<T, IB, IA, TA> > {
|
|
public:
|
|
#ifndef BOOST_UBLAS_NO_PROXY_SHORTCUTS
|
|
BOOST_UBLAS_USING vector_expression<coordinate_vector<T, IB, IA, TA> >::operator ();
|
|
#endif
|
|
typedef std::size_t size_type;
|
|
typedef std::ptrdiff_t difference_type;
|
|
typedef T value_type;
|
|
typedef const T &const_reference;
|
|
#ifndef BOOST_UBLAS_STRICT_VECTOR_SPARSE
|
|
typedef T &reference;
|
|
#else
|
|
typedef sparse_vector_element<coordinate_vector<T, IB, IA, TA> > reference;
|
|
#endif
|
|
typedef const T *const_pointer;
|
|
typedef T *pointer;
|
|
private:
|
|
typedef IA index_array_type;
|
|
typedef TA value_array_type;
|
|
typedef const coordinate_vector<T, IB, IA, TA> const_self_type;
|
|
typedef coordinate_vector<T, IB, IA, TA> self_type;
|
|
public:
|
|
#ifndef BOOST_UBLAS_CT_REFERENCE_BASE_TYPEDEFS
|
|
typedef const vector_const_reference<const_self_type> const_closure_type;
|
|
#else
|
|
typedef const vector_reference<const_self_type> const_closure_type;
|
|
#endif
|
|
typedef vector_reference<self_type> closure_type;
|
|
typedef sparse_tag storage_category;
|
|
|
|
// Construction and destruction
|
|
BOOST_UBLAS_INLINE
|
|
coordinate_vector ():
|
|
vector_expression<self_type> (),
|
|
size_ (0), non_zeros_ (0), filled_ (0),
|
|
sorted_ (true), index_data_ (), value_data_ () {}
|
|
BOOST_UBLAS_INLINE
|
|
coordinate_vector (size_type size, size_type non_zeros = 0):
|
|
vector_expression<self_type> (),
|
|
size_ (size), non_zeros_ (non_zeros), filled_ (0),
|
|
sorted_ (true), index_data_ (non_zeros), value_data_ (non_zeros) {
|
|
reserve (non_zeros_);
|
|
}
|
|
BOOST_UBLAS_INLINE
|
|
coordinate_vector (const coordinate_vector &v):
|
|
vector_expression<self_type> (),
|
|
size_ (v.size_), non_zeros_ (v.non_zeros_), filled_ (v.filled_),
|
|
sorted_ (v.sorted_), index_data_ (v.index_data_), value_data_ (v.value_data_) {}
|
|
template<class AE>
|
|
BOOST_UBLAS_INLINE
|
|
coordinate_vector (const vector_expression<AE> &ae, size_type non_zeros = 0):
|
|
vector_expression<self_type> (),
|
|
size_ (ae ().size ()), non_zeros_ (non_zeros), filled_ (0),
|
|
sorted_ (true), index_data_ (non_zeros), value_data_ (non_zeros) {
|
|
reserve (non_zeros_, false);
|
|
vector_assign (scalar_assign<reference, BOOST_UBLAS_TYPENAME AE::value_type> (), *this, ae);
|
|
}
|
|
|
|
// Accessors
|
|
BOOST_UBLAS_INLINE
|
|
size_type size () const {
|
|
return size_;
|
|
}
|
|
BOOST_UBLAS_INLINE
|
|
size_type non_zeros () const {
|
|
return non_zeros_;
|
|
}
|
|
BOOST_UBLAS_INLINE
|
|
size_type filled () const {
|
|
return filled_;
|
|
}
|
|
BOOST_UBLAS_INLINE
|
|
static size_type index_base () {
|
|
return IB;
|
|
}
|
|
BOOST_UBLAS_INLINE
|
|
const index_array_type &index_data () const {
|
|
return index_data_;
|
|
}
|
|
BOOST_UBLAS_INLINE
|
|
index_array_type &index_data () {
|
|
return index_data_;
|
|
}
|
|
BOOST_UBLAS_INLINE
|
|
const value_array_type &value_data () const {
|
|
return value_data_;
|
|
}
|
|
BOOST_UBLAS_INLINE
|
|
value_array_type &value_data () {
|
|
return value_data_;
|
|
}
|
|
|
|
// Resizing
|
|
BOOST_UBLAS_INLINE
|
|
void resize (size_type size, size_type non_zeros = 0, bool preserve = true) {
|
|
size_ = size;
|
|
non_zeros_ = (std::max) (non_zeros, size_type (1));
|
|
// FIX: coordinate_vector may contain duplicate elements.
|
|
// non_zeros_ = (std::min) (non_zeros_, size_);
|
|
filled_ = 0;
|
|
detail::resize (index_data (), non_zeros_, preserve);
|
|
detail::resize (value_data (), non_zeros_, preserve);
|
|
}
|
|
|
|
// Reserving
|
|
BOOST_UBLAS_INLINE
|
|
void reserve (size_type non_zeros = 0, bool preserve = true) {
|
|
non_zeros_ = (std::max) (non_zeros, size_type (1));
|
|
// FIX: coordinate_vector may contain duplicate elements.
|
|
// non_zeros_ = (std::min) (non_zeros_, size_);
|
|
detail::resize (index_data (), non_zeros_, preserve);
|
|
detail::resize (value_data (), non_zeros_, preserve);
|
|
}
|
|
|
|
// Proxy support
|
|
#ifdef BOOST_UBLAS_STRICT_VECTOR_SPARSE
|
|
pointer find_element (size_type i) {
|
|
sort ();
|
|
iterator_type it (detail::lower_bound (index_data ().begin (), index_data ().begin () + filled_, k_based (i), std::less<size_type> ()));
|
|
if (it == index_data ().begin () + filled_ || *it != k_based (i))
|
|
return 0;
|
|
return &value_data () [it - index_data ().begin ()];
|
|
}
|
|
#endif
|
|
|
|
// Element access
|
|
BOOST_UBLAS_INLINE
|
|
const_reference operator () (size_type i) const {
|
|
BOOST_UBLAS_CHECK (i < size_, bad_index ());
|
|
sort ();
|
|
const_iterator_type it (detail::lower_bound (index_data ().begin (), index_data ().begin () + filled_, k_based (i), std::less<size_type> ()));
|
|
if (it == index_data ().begin () + filled_ || *it != k_based (i))
|
|
return zero_;
|
|
return value_data () [it - index_data ().begin ()];
|
|
}
|
|
BOOST_UBLAS_INLINE
|
|
reference operator () (size_type i) {
|
|
BOOST_UBLAS_CHECK (i < size_, bad_index ());
|
|
#ifndef BOOST_UBLAS_STRICT_VECTOR_SPARSE
|
|
sort ();
|
|
iterator_type it (detail::lower_bound (index_data ().begin (), index_data ().begin () + filled_, k_based (i), std::less<size_type> ()));
|
|
if (it == index_data ().begin () + filled_ || *it != k_based (i)) {
|
|
insert (i, value_type ());
|
|
sort ();
|
|
it = detail::lower_bound (index_data ().begin (), index_data ().begin () + filled_, k_based (i), std::less<size_type> ());
|
|
}
|
|
return value_data () [it - index_data ().begin ()];
|
|
#else
|
|
return reference (*this, i);
|
|
#endif
|
|
}
|
|
|
|
BOOST_UBLAS_INLINE
|
|
const_reference operator [] (size_type i) const {
|
|
return (*this) (i);
|
|
}
|
|
BOOST_UBLAS_INLINE
|
|
reference operator [] (size_type i) {
|
|
return (*this) (i);
|
|
}
|
|
|
|
// Assignment
|
|
BOOST_UBLAS_INLINE
|
|
coordinate_vector &operator = (const coordinate_vector &v) {
|
|
if (this != &v) {
|
|
size_ = v.size_;
|
|
non_zeros_ = v.non_zeros_;
|
|
filled_ = v.filled_;
|
|
sorted_ = v.sorted_;
|
|
detail::resize (index_data (), non_zeros_, false);
|
|
detail::resize (value_data (), non_zeros_, false);
|
|
index_data () = v.index_data ();
|
|
value_data () = v.value_data ();
|
|
}
|
|
return *this;
|
|
}
|
|
BOOST_UBLAS_INLINE
|
|
coordinate_vector &assign_temporary (coordinate_vector &v) {
|
|
swap (v);
|
|
return *this;
|
|
}
|
|
template<class AE>
|
|
BOOST_UBLAS_INLINE
|
|
coordinate_vector &operator = (const vector_expression<AE> &ae) {
|
|
#ifdef BOOST_UBLAS_MUTABLE_TEMPORARY
|
|
return assign_temporary (self_type (ae, non_zeros_));
|
|
#else
|
|
// return assign (self_type (ae, non_zeros_));
|
|
self_type temporary (ae, non_zeros_);
|
|
return assign_temporary (temporary);
|
|
#endif
|
|
}
|
|
template<class AE>
|
|
BOOST_UBLAS_INLINE
|
|
coordinate_vector &reset (const vector_expression<AE> &ae) {
|
|
self_type temporary (ae, non_zeros_);
|
|
resize (temporary.size (), non_zeros_, false);
|
|
return assign_temporary (temporary);
|
|
}
|
|
template<class AE>
|
|
BOOST_UBLAS_INLINE
|
|
coordinate_vector &assign (const vector_expression<AE> &ae) {
|
|
vector_assign (scalar_assign<reference, BOOST_UBLAS_TYPENAME AE::value_type> (), *this, ae);
|
|
return *this;
|
|
}
|
|
template<class AE>
|
|
BOOST_UBLAS_INLINE
|
|
coordinate_vector &operator += (const vector_expression<AE> &ae) {
|
|
#ifdef BOOST_UBLAS_MUTABLE_TEMPORARY
|
|
return assign_temporary (self_type (*this + ae, non_zeros_));
|
|
#else
|
|
// return assign (self_type (*this + ae, non_zeros_));
|
|
self_type temporary (*this + ae, non_zeros_);
|
|
return assign_temporary (temporary);
|
|
#endif
|
|
}
|
|
template<class AE>
|
|
BOOST_UBLAS_INLINE
|
|
coordinate_vector &plus_assign (const vector_expression<AE> &ae) {
|
|
vector_assign (scalar_plus_assign<reference, BOOST_UBLAS_TYPENAME AE::value_type> (), *this, ae);
|
|
return *this;
|
|
}
|
|
template<class AE>
|
|
BOOST_UBLAS_INLINE
|
|
coordinate_vector &operator -= (const vector_expression<AE> &ae) {
|
|
#ifdef BOOST_UBLAS_MUTABLE_TEMPORARY
|
|
return assign_temporary (self_type (*this - ae, non_zeros_));
|
|
#else
|
|
// return assign (self_type (*this - ae, non_zeros_));
|
|
self_type temporary (*this - ae, non_zeros_);
|
|
return assign_temporary (temporary);
|
|
#endif
|
|
}
|
|
template<class AE>
|
|
BOOST_UBLAS_INLINE
|
|
coordinate_vector &minus_assign (const vector_expression<AE> &ae) {
|
|
vector_assign (scalar_minus_assign<reference, BOOST_UBLAS_TYPENAME AE::value_type> (), *this, ae);
|
|
return *this;
|
|
}
|
|
template<class AT>
|
|
BOOST_UBLAS_INLINE
|
|
coordinate_vector &operator *= (const AT &at) {
|
|
vector_assign_scalar (scalar_multiplies_assign<reference, AT> (), *this, at);
|
|
return *this;
|
|
}
|
|
template<class AT>
|
|
BOOST_UBLAS_INLINE
|
|
coordinate_vector &operator /= (const AT &at) {
|
|
vector_assign_scalar (scalar_divides_assign<reference, AT> (), *this, at);
|
|
return *this;
|
|
}
|
|
|
|
// Swapping
|
|
BOOST_UBLAS_INLINE
|
|
void swap (coordinate_vector &v) {
|
|
if (this != &v) {
|
|
std::swap (size_, v.size_);
|
|
std::swap (non_zeros_, v.non_zeros_);
|
|
std::swap (filled_, v.filled_);
|
|
std::swap (sorted_, v.sorted_);
|
|
index_data ().swap (v.index_data ());
|
|
value_data ().swap (v.value_data ());
|
|
}
|
|
}
|
|
#ifndef BOOST_UBLAS_NO_MEMBER_FRIENDS
|
|
BOOST_UBLAS_INLINE
|
|
friend void swap (coordinate_vector &v1, coordinate_vector &v2) {
|
|
v1.swap (v2);
|
|
}
|
|
#endif
|
|
|
|
// Sorting
|
|
BOOST_UBLAS_INLINE
|
|
void sort () const {
|
|
if (! sorted_ && filled_ > 0) {
|
|
index_pair_array<index_array_type, value_array_type>
|
|
ipa (filled_, index_data_, value_data_);
|
|
std::sort (ipa.begin (), ipa.end ());
|
|
// FIX: check for duplicates
|
|
size_type filled = 1;
|
|
for (size_type i = 1; i < filled_; ++ i) {
|
|
if (index_data_ [filled - 1] != index_data_ [i]) {
|
|
++ filled;
|
|
if (filled - 1 != i) {
|
|
index_data_ [filled - 1] = index_data_ [i];
|
|
value_data_ [filled - 1] = value_data_ [i];
|
|
}
|
|
} else {
|
|
value_data_ [filled - 1] += value_data_ [i];
|
|
}
|
|
}
|
|
filled_ = filled;
|
|
sorted_ = true;
|
|
}
|
|
}
|
|
|
|
// Element insertion and erasure
|
|
BOOST_UBLAS_INLINE
|
|
void push_back (size_type i, const_reference t) {
|
|
if (filled_ >= non_zeros_)
|
|
reserve (2 * non_zeros_);
|
|
if (filled_ == 0 || index_data () [filled_ - 1] < k_based (i)) {
|
|
++ filled_;
|
|
index_data () [filled_ - 1] = k_based (i);
|
|
value_data () [filled_ - 1] = t;
|
|
return;
|
|
}
|
|
external_logic ().raise ();
|
|
}
|
|
BOOST_UBLAS_INLINE
|
|
void insert (size_type i, const_reference t) {
|
|
if (filled_ >= non_zeros_)
|
|
reserve (2 * non_zeros_);
|
|
++ filled_;
|
|
index_data () [filled_ - 1] = k_based (i);
|
|
value_data () [filled_ - 1] = t;
|
|
sorted_ = false;
|
|
}
|
|
BOOST_UBLAS_INLINE
|
|
void pop_back () {
|
|
BOOST_UBLAS_CHECK (filled_ > 0, external_logic ());
|
|
-- filled_;
|
|
}
|
|
BOOST_UBLAS_INLINE
|
|
void erase (size_type i) {
|
|
sort ();
|
|
iterator_type it (detail::lower_bound (index_data ().begin (), index_data ().begin () + filled_, k_based (i), std::less<size_type> ()));
|
|
difference_type n = it - index_data ().begin ();
|
|
if (filled_ > size_type (n) && *it == k_based (i)) {
|
|
std::copy (it + 1, index_data ().begin () + filled_, it);
|
|
typename value_array_type::iterator itt (value_data ().begin () + n);
|
|
std::copy (itt + 1, value_data ().begin () + filled_, itt);
|
|
-- filled_;
|
|
}
|
|
}
|
|
BOOST_UBLAS_INLINE
|
|
void clear () {
|
|
filled_ = 0;
|
|
}
|
|
|
|
// Iterator types
|
|
private:
|
|
// Use index array iterator
|
|
typedef typename IA::const_iterator const_iterator_type;
|
|
typedef typename IA::iterator iterator_type;
|
|
|
|
public:
|
|
class const_iterator;
|
|
class iterator;
|
|
|
|
// Element lookup
|
|
// This function seems to be big. So we do not let the compiler inline it.
|
|
// BOOST_UBLAS_INLINE
|
|
const_iterator find (size_type i) const {
|
|
sort ();
|
|
return const_iterator (*this, detail::lower_bound (index_data ().begin (), index_data ().begin () + filled_, k_based (i), std::less<size_type> ()));
|
|
}
|
|
// This function seems to be big. So we do not let the compiler inline it.
|
|
// BOOST_UBLAS_INLINE
|
|
iterator find (size_type i) {
|
|
sort ();
|
|
return iterator (*this, detail::lower_bound (index_data ().begin (), index_data ().begin () + filled_, k_based (i), std::less<size_type> ()));
|
|
}
|
|
|
|
|
|
class const_iterator:
|
|
public container_const_reference<coordinate_vector>,
|
|
public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
|
|
const_iterator, value_type> {
|
|
public:
|
|
typedef sparse_bidirectional_iterator_tag iterator_category;
|
|
#ifdef BOOST_MSVC_STD_ITERATOR
|
|
typedef const_reference reference;
|
|
#else
|
|
typedef typename coordinate_vector::difference_type difference_type;
|
|
typedef typename coordinate_vector::value_type value_type;
|
|
typedef typename coordinate_vector::const_reference reference;
|
|
typedef typename coordinate_vector::const_pointer pointer;
|
|
#endif
|
|
|
|
// Construction and destruction
|
|
BOOST_UBLAS_INLINE
|
|
const_iterator ():
|
|
container_const_reference<self_type> (), it_ () {}
|
|
BOOST_UBLAS_INLINE
|
|
const_iterator (const self_type &v, const const_iterator_type &it):
|
|
container_const_reference<self_type> (v), it_ (it) {}
|
|
#ifndef BOOST_UBLAS_QUALIFIED_TYPENAME
|
|
BOOST_UBLAS_INLINE
|
|
const_iterator (const iterator &it):
|
|
container_const_reference<self_type> (it ()), it_ (it.it_) {}
|
|
#else
|
|
BOOST_UBLAS_INLINE
|
|
const_iterator (const typename self_type::iterator &it):
|
|
container_const_reference<self_type> (it ()), it_ (it.it_) {}
|
|
#endif
|
|
// Arithmetic
|
|
BOOST_UBLAS_INLINE
|
|
const_iterator &operator ++ () {
|
|
++ it_;
|
|
return *this;
|
|
}
|
|
BOOST_UBLAS_INLINE
|
|
const_iterator &operator -- () {
|
|
-- it_;
|
|
return *this;
|
|
}
|
|
|
|
// Dereference
|
|
BOOST_UBLAS_INLINE
|
|
const_reference operator * () const {
|
|
BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
|
|
return (*this) ().value_data () [it_ - (*this) ().index_data ().begin ()];
|
|
}
|
|
|
|
// Index
|
|
BOOST_UBLAS_INLINE
|
|
size_type index () const {
|
|
BOOST_UBLAS_CHECK (*this != (*this) ().end (), bad_index ());
|
|
BOOST_UBLAS_CHECK ((*this) ().zero_based (*it_) < (*this) ().size (), bad_index ());
|
|
return (*this) ().zero_based (*it_);
|
|
}
|
|
|
|
// Assignment
|
|
BOOST_UBLAS_INLINE
|
|
const_iterator &operator = (const const_iterator &it) {
|
|
container_const_reference<self_type>::assign (&it ());
|
|
it_ = it.it_;
|
|
return *this;
|
|
}
|
|
|
|
// Comparison
|
|
BOOST_UBLAS_INLINE
|
|
bool operator == (const const_iterator &it) const {
|
|
BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
|
|
return it_ == it.it_;
|
|
}
|
|
|
|
private:
|
|
const_iterator_type it_;
|
|
};
|
|
|
|
BOOST_UBLAS_INLINE
|
|
const_iterator begin () const {
|
|
return find (0);
|
|
}
|
|
BOOST_UBLAS_INLINE
|
|
const_iterator end () const {
|
|
return find (size_);
|
|
}
|
|
|
|
class iterator:
|
|
public container_reference<coordinate_vector>,
|
|
public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
|
|
iterator, value_type> {
|
|
public:
|
|
typedef sparse_bidirectional_iterator_tag iterator_category;
|
|
#ifndef BOOST_MSVC_STD_ITERATOR
|
|
typedef typename coordinate_vector::difference_type difference_type;
|
|
typedef typename coordinate_vector::value_type value_type;
|
|
typedef typename coordinate_vector::reference reference;
|
|
typedef typename coordinate_vector::pointer pointer;
|
|
#endif
|
|
|
|
// Construction and destruction
|
|
BOOST_UBLAS_INLINE
|
|
iterator ():
|
|
container_reference<self_type> (), it_ () {}
|
|
BOOST_UBLAS_INLINE
|
|
iterator (self_type &v, const iterator_type &it):
|
|
container_reference<self_type> (v), it_ (it) {}
|
|
|
|
// Arithmetic
|
|
BOOST_UBLAS_INLINE
|
|
iterator &operator ++ () {
|
|
++ it_;
|
|
return *this;
|
|
}
|
|
BOOST_UBLAS_INLINE
|
|
iterator &operator -- () {
|
|
-- it_;
|
|
return *this;
|
|
}
|
|
|
|
// Dereference
|
|
BOOST_UBLAS_INLINE
|
|
reference operator * () const {
|
|
BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
|
|
#if ! defined (BOOST_UBLAS_STRICT_VECTOR_SPARSE)
|
|
return (*this) ().value_data () [it_ - (*this) ().index_data ().begin ()];
|
|
#else
|
|
return reference ((*this) (), &(*this) ().value_data () [it_ - (*this) ().index_data ().begin ()], index ());
|
|
#endif
|
|
}
|
|
|
|
// Index
|
|
BOOST_UBLAS_INLINE
|
|
size_type index () const {
|
|
BOOST_UBLAS_CHECK (*this != (*this) ().end (), bad_index ());
|
|
BOOST_UBLAS_CHECK ((*this) ().zero_based (*it_) < (*this) ().size (), bad_index ());
|
|
return (*this) ().zero_based (*it_);
|
|
}
|
|
|
|
// Assignment
|
|
BOOST_UBLAS_INLINE
|
|
iterator &operator = (const iterator &it) {
|
|
container_reference<self_type>::assign (&it ());
|
|
it_ = it.it_;
|
|
return *this;
|
|
}
|
|
|
|
// Comparison
|
|
BOOST_UBLAS_INLINE
|
|
bool operator == (const iterator &it) const {
|
|
BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
|
|
return it_ == it.it_;
|
|
}
|
|
|
|
private:
|
|
iterator_type it_;
|
|
|
|
friend class const_iterator;
|
|
};
|
|
|
|
BOOST_UBLAS_INLINE
|
|
iterator begin () {
|
|
return find (0);
|
|
}
|
|
BOOST_UBLAS_INLINE
|
|
iterator end () {
|
|
return find (size_);
|
|
}
|
|
|
|
// Reverse iterator
|
|
|
|
#ifdef BOOST_MSVC_STD_ITERATOR
|
|
typedef reverse_iterator_base<const_iterator, value_type, const_reference> const_reverse_iterator;
|
|
#else
|
|
typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
|
|
#endif
|
|
|
|
BOOST_UBLAS_INLINE
|
|
const_reverse_iterator rbegin () const {
|
|
return const_reverse_iterator (end ());
|
|
}
|
|
BOOST_UBLAS_INLINE
|
|
const_reverse_iterator rend () const {
|
|
return const_reverse_iterator (begin ());
|
|
}
|
|
|
|
#ifdef BOOST_MSVC_STD_ITERATOR
|
|
typedef reverse_iterator_base<iterator, value_type, reference> reverse_iterator;
|
|
#else
|
|
typedef reverse_iterator_base<iterator> reverse_iterator;
|
|
#endif
|
|
|
|
BOOST_UBLAS_INLINE
|
|
reverse_iterator rbegin () {
|
|
return reverse_iterator (end ());
|
|
}
|
|
BOOST_UBLAS_INLINE
|
|
reverse_iterator rend () {
|
|
return reverse_iterator (begin ());
|
|
}
|
|
|
|
private:
|
|
size_type size_;
|
|
size_type non_zeros_;
|
|
mutable size_type filled_;
|
|
mutable bool sorted_;
|
|
mutable index_array_type index_data_;
|
|
mutable value_array_type value_data_;
|
|
static const value_type zero_;
|
|
|
|
BOOST_UBLAS_INLINE
|
|
static size_type zero_based (size_type k_based_index) {
|
|
return k_based_index - IB;
|
|
}
|
|
BOOST_UBLAS_INLINE
|
|
static size_type k_based (size_type zero_based_index) {
|
|
return zero_based_index + IB;
|
|
}
|
|
|
|
friend class iterator;
|
|
friend class const_iterator;
|
|
};
|
|
|
|
template<class T, std::size_t IB, class IA, class TA>
|
|
const typename coordinate_vector<T, IB, IA, TA>::value_type coordinate_vector<T, IB, IA, TA>::zero_
|
|
#ifdef BOOST_UBLAS_STATIC_OLD_INIT
|
|
= BOOST_UBLAS_TYPENAME coordinate_vector<T, IB, IA, TA>::value_type
|
|
#endif
|
|
(0);
|
|
|
|
}}}
|
|
|
|
#endif
|