📄 storage_sparse.hpp
字号:
//
// 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_STORAGE_SPARSE_H
#define BOOST_UBLAS_STORAGE_SPARSE_H
#include <algorithm>
#include <map>
#include <set>
#include <boost/numeric/ublas/config.hpp>
#include <boost/numeric/ublas/exception.hpp>
#include <boost/numeric/ublas/iterator.hpp>
#include <boost/numeric/ublas/storage.hpp>
namespace boost { namespace numeric { namespace ublas {
namespace detail {
template<class I, class T, class C>
BOOST_UBLAS_INLINE
I lower_bound (const I &begin, const I &end, const T &t, C compare) {
// t <= *begin <=> ! (*begin < t)
if (begin == end || ! compare (*begin, t))
return begin;
if (compare (*(end - 1), t))
return end;
return std::lower_bound (begin, end, t, compare);
}
template<class I, class T, class C>
BOOST_UBLAS_INLINE
I upper_bound (const I &begin, const I &end, const T &t, C compare) {
if (begin == end || compare (t, *begin))
return begin;
// (*end - 1) <= t <=> ! (t < *end)
if (! compare (t, *(end - 1)))
return end;
return std::upper_bound (begin, end, t, compare);
}
template<class P>
struct less_pair {
BOOST_UBLAS_INLINE
bool operator () (const P &p1, const P &p2) {
return p1.first < p2.first;
}
};
template<class T>
struct less_triple {
BOOST_UBLAS_INLINE
bool operator () (const T &t1, const T &t2) {
return t1.first.first < t2.first.first ||
(t1.first.first == t2.first.first && t1.first.second < t2.first.second);
}
};
}
#ifdef BOOST_UBLAS_STRICT_STORAGE_SPARSE
template<class D>
struct sparse_storage_element_traits {
typedef typename D::index_type index_type;
typedef typename D::data_const_reference data_const_reference;
typedef typename D::data_reference data_reference;
};
template<>
struct sparse_storage_element_traits<float> {
typedef std::size_t index_type;
typedef void data_const_reference;
typedef void data_reference;
};
template<>
struct sparse_storage_element_traits<double> {
typedef std::size_t index_type;
typedef void data_const_reference;
typedef void data_reference;
};
#ifdef BOOST_UBLAS_USE_LONG_DOUBLE
template<>
struct sparse_storage_element_traits<long double> {
typedef std::size_t index_type;
typedef void data_const_reference;
typedef void data_reference;
};
#endif
template<>
struct sparse_storage_element_traits<std::complex<float> > {
typedef std::size_t index_type;
typedef void data_const_reference;
typedef void data_reference;
};
template<>
struct sparse_storage_element_traits<std::complex<double> > {
typedef std::size_t index_type;
typedef void data_const_reference;
typedef void data_reference;
};
#ifdef BOOST_UBLAS_USE_LONG_DOUBLE
template<>
struct sparse_storage_element_traits<std::complex<long double> > {
typedef std::size_t index_type;
typedef void data_const_reference;
typedef void data_reference;
};
#endif
template<class A>
class sparse_storage_element:
public container_reference<A> {
public:
typedef A array_type;
typedef typename A::index_type index_type;
typedef typename A::data_value_type data_value_type;
// typedef const data_value_type &data_const_reference;
typedef typename type_traits<data_value_type>::const_reference data_const_reference;
typedef data_value_type &data_reference;
typedef std::pair<index_type, data_value_type> value_type;
typedef std::pair<index_type, data_value_type> *pointer;
// Construction and destruction
BOOST_UBLAS_INLINE
sparse_storage_element (array_type &a, pointer it):
container_reference<array_type> (a), it_ (it), i_ (it->first), d_ (it->second), dirty_ (false) {}
BOOST_UBLAS_INLINE
sparse_storage_element (array_type &a, index_type i):
container_reference<array_type> (a), it_ (), i_ (i), d_ (), dirty_ (false) {
pointer it = (*this) ().find (i_);
if (it == (*this) ().end ())
it = (*this) ().insert ((*this) ().end (), value_type (i_, d_));
d_ = it->second;
}
BOOST_UBLAS_INLINE
~sparse_storage_element () {
if (dirty_) {
if (! it_)
it_ = (*this) ().find (i_);
BOOST_UBLAS_CHECK (it_ != (*this) ().end (), internal_logic ());
it_->second = d_;
}
}
// Element access
BOOST_UBLAS_INLINE
typename sparse_storage_element_traits<data_value_type>::data_const_reference
operator [] (typename sparse_storage_element_traits<data_value_type>::index_type i) const {
return d_ [i];
}
#ifdef BOOST_UBLAS_DEPRECATED
BOOST_UBLAS_INLINE
typename sparse_storage_element_traits<data_value_type>::data_reference
operator [] (typename sparse_storage_element_traits<data_value_type>::index_type i) {
dirty_ = true;
return d_ [i];
}
#endif
// Assignment
template<class D>
BOOST_UBLAS_INLINE
sparse_storage_element &operator = (const D &d) {
d_ = d;
dirty_ = true;
return *this;
}
BOOST_UBLAS_INLINE
sparse_storage_element &operator = (const sparse_storage_element &p) {
d_ = p.d_;
dirty_ = true;
return *this;
}
template<class D>
BOOST_UBLAS_INLINE
sparse_storage_element &operator += (const D &d) {
d_ += d;
dirty_ = true;
return *this;
}
BOOST_UBLAS_INLINE
sparse_storage_element &operator += (const sparse_storage_element &p) {
d_ += p.d_;
dirty_ = true;
return *this;
}
template<class D>
BOOST_UBLAS_INLINE
sparse_storage_element &operator -= (const D &d) {
d_ -= d;
dirty_ = true;
return *this;
}
BOOST_UBLAS_INLINE
sparse_storage_element &operator -= (const sparse_storage_element &p) {
d_ -= p.d_;
dirty_ = true;
return *this;
}
template<class D>
BOOST_UBLAS_INLINE
sparse_storage_element &operator *= (const D &d) {
d_ *= d;
dirty_ = true;
return *this;
}
BOOST_UBLAS_INLINE
sparse_storage_element &operator *= (const sparse_storage_element &p) {
d_ *= p.d_;
dirty_ = true;
return *this;
}
template<class D>
BOOST_UBLAS_INLINE
sparse_storage_element &operator /= (const D &d) {
d_ /= d;
dirty_ = true;
return *this;
}
BOOST_UBLAS_INLINE
sparse_storage_element &operator /= (const sparse_storage_element &p) {
d_ /= p.d_;
dirty_ = true;
return *this;
}
// Conversion
BOOST_UBLAS_INLINE
operator data_const_reference () const {
return d_;
}
#ifdef BOOST_UBLAS_DEPRECATED
BOOST_UBLAS_INLINE
operator data_reference () {
dirty_ = true;
return d_;
}
#endif
// Swapping
BOOST_UBLAS_INLINE
void swap (sparse_storage_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_storage_element p1, sparse_storage_element p2) {
p1.swap (p2);
}
#endif
private:
pointer it_;
index_type i_;
data_value_type d_;
bool dirty_;
};
#endif
// Map array
template<class I, class T>
class map_array {
public:
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
typedef I index_type;
typedef T data_value_type;
// typedef const T &data_const_reference;
typedef typename type_traits<T>::const_reference data_const_reference;
#ifndef BOOST_UBLAS_STRICT_STORAGE_SPARSE
typedef T &data_reference;
#else
typedef sparse_storage_element<map_array> data_reference;
#endif
typedef std::pair<I, T> value_type;
typedef const std::pair<I, T> &const_reference;
typedef std::pair<I, T> &reference;
typedef const std::pair<I, T> *const_pointer;
typedef std::pair<I, T> *pointer;
// Construction and destruction
BOOST_UBLAS_INLINE
map_array ():
capacity_ (0), data_ (new value_type [0]), size_ (0) {
// Assuming std compliant allocator as requested during review.
// if (! data_)
// throw std::bad_alloc ();
std::fill (data_, data_ + size_, value_type ());
}
BOOST_UBLAS_INLINE
map_array (no_init):
capacity_ (0), data_ (new value_type [0]), size_ (0) {
// Assuming std compliant allocator as requested during review.
// if (! data_)
// throw std::bad_alloc ();
}
BOOST_UBLAS_EXPLICIT BOOST_UBLAS_INLINE
map_array (size_type size):
capacity_ (size), data_ (new value_type [size]), size_ (0) {
// Assuming std compliant allocator as requested during review.
// if (! data_)
// throw std::bad_alloc ();
std::fill (data_, data_ + size_, value_type ());
}
BOOST_UBLAS_EXPLICIT BOOST_UBLAS_INLINE
map_array (size_type size, no_init):
capacity_ (size), data_ (new value_type [size]), size_ (0) {
// Assuming std compliant allocator as requested during review.
// if (! data_)
// throw std::bad_alloc ();
}
BOOST_UBLAS_INLINE
map_array (const map_array &a):
capacity_ (a.size_), data_ (new value_type [a.size_]), size_ (a.size_) {
// Assuming std compliant allocator as requested during review.
// if (! data_)
// throw std::bad_alloc ();
*this = a;
}
BOOST_UBLAS_INLINE
~map_array () {
// Assuming std compliant allocator as requested during review.
// if (! data_)
// throw std::bad_alloc ();
delete [] data_;
}
// Resizing
BOOST_UBLAS_INLINE
void resize (size_type size) {
BOOST_UBLAS_CHECK (size_ <= capacity_, internal_logic ());
if (size > capacity_) {
pointer data = new value_type [size << 1];
// Assuming std compliant allocator as requested during review.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -