File indexing completed on 2025-01-18 09:43:14
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #ifndef _BOOST_UBLAS_STORAGE_SPARSE_
0014 #define _BOOST_UBLAS_STORAGE_SPARSE_
0015
0016 #include <map>
0017 #include <boost/serialization/collection_size_type.hpp>
0018 #include <boost/serialization/nvp.hpp>
0019 #include <boost/serialization/array.hpp>
0020 #include <boost/serialization/map.hpp>
0021 #include <boost/serialization/base_object.hpp>
0022
0023 #include <boost/numeric/ublas/storage.hpp>
0024
0025
0026 namespace boost { namespace numeric { namespace ublas {
0027
0028 namespace detail {
0029
0030 template<class I, class T, class C>
0031 BOOST_UBLAS_INLINE
0032 I lower_bound (const I &begin, const I &end, const T &t, C compare) {
0033
0034 if (begin == end || ! compare (*begin, t))
0035 return begin;
0036 if (compare (*(end - 1), t))
0037 return end;
0038 return std::lower_bound (begin, end, t, compare);
0039 }
0040 template<class I, class T, class C>
0041 BOOST_UBLAS_INLINE
0042 I upper_bound (const I &begin, const I &end, const T &t, C compare) {
0043 if (begin == end || compare (t, *begin))
0044 return begin;
0045
0046 if (! compare (t, *(end - 1)))
0047 return end;
0048 return std::upper_bound (begin, end, t, compare);
0049 }
0050
0051 template<class P>
0052 struct less_pair {
0053 BOOST_UBLAS_INLINE
0054 bool operator () (const P &p1, const P &p2) {
0055 return p1.first < p2.first;
0056 }
0057 };
0058 template<class T>
0059 struct less_triple {
0060 BOOST_UBLAS_INLINE
0061 bool operator () (const T &t1, const T &t2) {
0062 return t1.first.first < t2.first.first ||
0063 (t1.first.first == t2.first.first && t1.first.second < t2.first.second);
0064 }
0065 };
0066
0067 }
0068
0069 #ifdef BOOST_UBLAS_STRICT_MAP_ARRAY
0070 template<class A>
0071 class sparse_storage_element:
0072 public container_reference<A> {
0073 public:
0074 typedef A array_type;
0075 typedef typename A::key_type index_type;
0076 typedef typename A::mapped_type data_value_type;
0077
0078 typedef typename type_traits<data_value_type>::const_reference data_const_reference;
0079 typedef data_value_type &data_reference;
0080 typedef typename A::value_type value_type;
0081 typedef value_type *pointer;
0082
0083
0084 BOOST_UBLAS_INLINE
0085 sparse_storage_element (array_type &a, pointer it):
0086 container_reference<array_type> (a), it_ (it), i_ (it->first), d_ (it->second), dirty_ (false) {}
0087 BOOST_UBLAS_INLINE
0088 sparse_storage_element (array_type &a, index_type i):
0089 container_reference<array_type> (a), it_ (), i_ (i), d_ (), dirty_ (false) {
0090 pointer it = (*this) ().find (i_);
0091 if (it == (*this) ().end ())
0092 it = (*this) ().insert ((*this) ().end (), value_type (i_, d_));
0093 d_ = it->second;
0094 }
0095 BOOST_UBLAS_INLINE
0096 ~sparse_storage_element () {
0097 if (dirty_) {
0098 if (! it_)
0099 it_ = (*this) ().find (i_);
0100 BOOST_UBLAS_CHECK (it_ != (*this) ().end (), internal_logic ());
0101 it_->second = d_;
0102 }
0103 }
0104
0105
0106 BOOST_UBLAS_INLINE
0107 typename data_value_type::data_const_reference
0108 operator [] (index_type i) const {
0109 return d_ [i];
0110 }
0111
0112
0113 BOOST_UBLAS_INLINE
0114 sparse_storage_element &operator = (const sparse_storage_element &p) {
0115
0116 d_ = p.d_;
0117 dirty_ = true;
0118 return *this;
0119 }
0120 template<class D>
0121 BOOST_UBLAS_INLINE
0122 sparse_storage_element &operator = (const D &d) {
0123 d_ = d;
0124 dirty_ = true;
0125 return *this;
0126 }
0127 template<class D>
0128 BOOST_UBLAS_INLINE
0129 sparse_storage_element &operator += (const D &d) {
0130 d_ += d;
0131 dirty_ = true;
0132 return *this;
0133 }
0134 template<class D>
0135 BOOST_UBLAS_INLINE
0136 sparse_storage_element &operator -= (const D &d) {
0137 d_ -= d;
0138 dirty_ = true;
0139 return *this;
0140 }
0141 template<class D>
0142 BOOST_UBLAS_INLINE
0143 sparse_storage_element &operator *= (const D &d) {
0144 d_ *= d;
0145 dirty_ = true;
0146 return *this;
0147 }
0148 template<class D>
0149 BOOST_UBLAS_INLINE
0150 sparse_storage_element &operator /= (const D &d) {
0151 d_ /= d;
0152 dirty_ = true;
0153 return *this;
0154 }
0155
0156
0157 template<class D>
0158 BOOST_UBLAS_INLINE
0159 bool operator == (const D &d) const {
0160 return d_ == d;
0161 }
0162 template<class D>
0163 BOOST_UBLAS_INLINE
0164 bool operator != (const D &d) const {
0165 return d_ != d;
0166 }
0167
0168
0169 BOOST_UBLAS_INLINE
0170 operator data_const_reference () const {
0171 return d_;
0172 }
0173
0174
0175 BOOST_UBLAS_INLINE
0176 void swap (sparse_storage_element p) {
0177 if (this != &p) {
0178 dirty_ = true;
0179 p.dirty_ = true;
0180 std::swap (d_, p.d_);
0181 }
0182 }
0183 BOOST_UBLAS_INLINE
0184 friend void swap (sparse_storage_element p1, sparse_storage_element p2) {
0185 p1.swap (p2);
0186 }
0187
0188 private:
0189 pointer it_;
0190 index_type i_;
0191 data_value_type d_;
0192 bool dirty_;
0193 };
0194 #endif
0195
0196
0197
0198 template<class I, class T, class ALLOC>
0199 class map_std : public std::map<I, T, std::less<I>, ALLOC> {
0200 public:
0201
0202 template<class Archive>
0203 void serialize(Archive & ar, const unsigned int ){
0204 ar & serialization::make_nvp("base", boost::serialization::base_object< std::map<I, T, std::less<I>, ALLOC> >(*this));
0205 }
0206 };
0207
0208
0209
0210
0211
0212
0213 template<class I, class T, class ALLOC>
0214 class map_array {
0215 public:
0216 typedef ALLOC allocator_type;
0217 typedef typename boost::allocator_size_type<ALLOC>::type size_type;
0218 typedef typename boost::allocator_difference_type<ALLOC>::type difference_type;
0219 typedef std::pair<I,T> value_type;
0220 typedef I key_type;
0221 typedef T mapped_type;
0222 typedef const value_type &const_reference;
0223 typedef value_type &reference;
0224 typedef const value_type *const_pointer;
0225 typedef value_type *pointer;
0226
0227 typedef const_pointer const_iterator;
0228 typedef pointer iterator;
0229
0230 typedef const T &data_const_reference;
0231 #ifndef BOOST_UBLAS_STRICT_MAP_ARRAY
0232 typedef T &data_reference;
0233 #else
0234 typedef sparse_storage_element<map_array> data_reference;
0235 #endif
0236
0237
0238 BOOST_UBLAS_INLINE
0239 map_array (const ALLOC &a = ALLOC()):
0240 alloc_(a), capacity_ (0), size_ (0) {
0241 data_ = 0;
0242 }
0243 BOOST_UBLAS_INLINE
0244 map_array (const map_array &c):
0245 alloc_ (c.alloc_), capacity_ (c.size_), size_ (c.size_) {
0246 if (capacity_) {
0247 data_ = alloc_.allocate (capacity_);
0248 std::uninitialized_copy (data_, data_ + capacity_, c.data_);
0249
0250 }
0251 else
0252 data_ = 0;
0253 }
0254 BOOST_UBLAS_INLINE
0255 ~map_array () {
0256 if (capacity_) {
0257 std::for_each (data_, data_ + capacity_, static_destroy);
0258 alloc_.deallocate (data_, capacity_);
0259 }
0260 }
0261
0262 private:
0263
0264 BOOST_UBLAS_INLINE
0265 void resize (size_type size) {
0266 BOOST_UBLAS_CHECK (size_ <= capacity_, internal_logic ());
0267 if (size > capacity_) {
0268 const size_type capacity = size << 1;
0269 BOOST_UBLAS_CHECK (capacity, internal_logic ());
0270 pointer data = alloc_.allocate (capacity);
0271 std::uninitialized_copy (data_, data_ + (std::min) (size, size_), data);
0272 std::uninitialized_fill (data + (std::min) (size, size_), data + capacity, value_type ());
0273
0274 if (capacity_) {
0275 std::for_each (data_, data_ + capacity_, static_destroy);
0276 alloc_.deallocate (data_, capacity_);
0277 }
0278 capacity_ = capacity;
0279 data_ = data;
0280 }
0281 size_ = size;
0282 BOOST_UBLAS_CHECK (size_ <= capacity_, internal_logic ());
0283 }
0284 public:
0285
0286
0287 BOOST_UBLAS_INLINE
0288 void reserve (size_type capacity) {
0289 BOOST_UBLAS_CHECK (size_ <= capacity_, internal_logic ());
0290
0291 BOOST_UBLAS_CHECK (capacity >= size_, bad_size ());
0292 pointer data;
0293 if (capacity) {
0294 data = alloc_.allocate (capacity);
0295 std::uninitialized_copy (data_, data_ + size_, data);
0296 std::uninitialized_fill (data + size_, data + capacity, value_type ());
0297 }
0298 else
0299 data = 0;
0300
0301 if (capacity_) {
0302 std::for_each (data_, data_ + capacity_, static_destroy);
0303 alloc_.deallocate (data_, capacity_);
0304 }
0305 capacity_ = capacity;
0306 data_ = data;
0307 BOOST_UBLAS_CHECK (size_ <= capacity_, internal_logic ());
0308 }
0309
0310
0311 BOOST_UBLAS_INLINE
0312 size_type size () const {
0313 return size_;
0314 }
0315 BOOST_UBLAS_INLINE
0316 size_type capacity () const {
0317 return capacity_;
0318 }
0319 BOOST_UBLAS_INLINE
0320 size_type max_size () const {
0321 return 0;
0322 }
0323
0324 BOOST_UBLAS_INLINE
0325 bool empty () const {
0326 return size_ == 0;
0327 }
0328
0329
0330 BOOST_UBLAS_INLINE
0331 data_reference operator [] (key_type i) {
0332 #ifndef BOOST_UBLAS_STRICT_MAP_ARRAY
0333 pointer it = find (i);
0334 if (it == end ())
0335 it = insert (end (), value_type (i, mapped_type (0)));
0336 BOOST_UBLAS_CHECK (it != end (), internal_logic ());
0337 return it->second;
0338 #else
0339 return data_reference (*this, i);
0340 #endif
0341 }
0342
0343
0344 BOOST_UBLAS_INLINE
0345 map_array &operator = (const map_array &a) {
0346 if (this != &a) {
0347 resize (a.size_);
0348 std::copy (a.data_, a.data_ + a.size_, data_);
0349 }
0350 return *this;
0351 }
0352 BOOST_UBLAS_INLINE
0353 map_array &assign_temporary (map_array &a) {
0354 swap (a);
0355 return *this;
0356 }
0357
0358
0359 BOOST_UBLAS_INLINE
0360 void swap (map_array &a) {
0361 if (this != &a) {
0362 std::swap (capacity_, a.capacity_);
0363 std::swap (data_, a.data_);
0364 std::swap (size_, a.size_);
0365 }
0366 }
0367 BOOST_UBLAS_INLINE
0368 friend void swap (map_array &a1, map_array &a2) {
0369 a1.swap (a2);
0370 }
0371
0372
0373
0374
0375
0376 iterator push_back (iterator it, const value_type &p) {
0377 if (size () == 0 || (it = end () - 1)->first < p.first) {
0378 resize (size () + 1);
0379 *(it = end () - 1) = p;
0380 return it;
0381 }
0382 external_logic ().raise ();
0383 return it;
0384 }
0385
0386
0387 std::pair<iterator,bool> insert (const value_type &p) {
0388 iterator it = detail::lower_bound (begin (), end (), p, detail::less_pair<value_type> ());
0389 if (it != end () && it->first == p.first)
0390 return std::make_pair (it, false);
0391 difference_type n = it - begin ();
0392 resize (size () + 1);
0393 it = begin () + n;
0394 std::copy_backward (it, end () - 1, end ());
0395 *it = p;
0396 return std::make_pair (it, true);
0397 }
0398
0399
0400 iterator insert (iterator , const value_type &p) {
0401 return insert (p).first;
0402 }
0403
0404 void erase (iterator it) {
0405 BOOST_UBLAS_CHECK (begin () <= it && it < end (), bad_index ());
0406 std::copy (it + 1, end (), it);
0407 resize (size () - 1);
0408 }
0409
0410 void erase (iterator it1, iterator it2) {
0411 if (it1 == it2) return ;
0412 BOOST_UBLAS_CHECK (begin () <= it1 && it1 < it2 && it2 <= end (), bad_index ());
0413 std::copy (it2, end (), it1);
0414 resize (size () - (it2 - it1));
0415 }
0416
0417 void clear () {
0418 resize (0);
0419 }
0420
0421
0422
0423 const_iterator find (key_type i) const {
0424 const_iterator it (detail::lower_bound (begin (), end (), value_type (i, mapped_type (0)), detail::less_pair<value_type> ()));
0425 if (it == end () || it->first != i)
0426 it = end ();
0427 return it;
0428 }
0429
0430 iterator find (key_type i) {
0431 iterator it (detail::lower_bound (begin (), end (), value_type (i, mapped_type (0)), detail::less_pair<value_type> ()));
0432 if (it == end () || it->first != i)
0433 it = end ();
0434 return it;
0435 }
0436
0437 const_iterator lower_bound (key_type i) const {
0438 return detail::lower_bound (begin (), end (), value_type (i, mapped_type (0)), detail::less_pair<value_type> ());
0439 }
0440
0441 iterator lower_bound (key_type i) {
0442 return detail::lower_bound (begin (), end (), value_type (i, mapped_type (0)), detail::less_pair<value_type> ());
0443 }
0444
0445 BOOST_UBLAS_INLINE
0446 const_iterator begin () const {
0447 return data_;
0448 }
0449 BOOST_UBLAS_INLINE
0450 const_iterator cbegin () const {
0451 return begin ();
0452 }
0453 BOOST_UBLAS_INLINE
0454 const_iterator end () const {
0455 return data_ + size_;
0456 }
0457 BOOST_UBLAS_INLINE
0458 const_iterator cend () const {
0459 return end ();
0460 }
0461
0462 BOOST_UBLAS_INLINE
0463 iterator begin () {
0464 return data_;
0465 }
0466 BOOST_UBLAS_INLINE
0467 iterator end () {
0468 return data_ + size_;
0469 }
0470
0471
0472 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
0473 typedef std::reverse_iterator<iterator> reverse_iterator;
0474
0475 BOOST_UBLAS_INLINE
0476 const_reverse_iterator rbegin () const {
0477 return const_reverse_iterator (end ());
0478 }
0479 BOOST_UBLAS_INLINE
0480 const_reverse_iterator crbegin () const {
0481 return rbegin ();
0482 }
0483 BOOST_UBLAS_INLINE
0484 const_reverse_iterator rend () const {
0485 return const_reverse_iterator (begin ());
0486 }
0487 BOOST_UBLAS_INLINE
0488 const_reverse_iterator crend () const {
0489 return rend ();
0490 }
0491
0492 BOOST_UBLAS_INLINE
0493 reverse_iterator rbegin () {
0494 return reverse_iterator (end ());
0495 }
0496 BOOST_UBLAS_INLINE
0497 reverse_iterator rend () {
0498 return reverse_iterator (begin ());
0499 }
0500
0501
0502 allocator_type get_allocator () {
0503 return alloc_;
0504 }
0505
0506
0507 template<class Archive>
0508 void serialize(Archive & ar, const unsigned int ){
0509 serialization::collection_size_type s (size_);
0510 ar & serialization::make_nvp("size",s);
0511 if (Archive::is_loading::value) {
0512 resize(s);
0513 }
0514 ar & serialization::make_array(data_, s);
0515 }
0516
0517 private:
0518
0519 BOOST_UBLAS_INLINE
0520 static void static_destroy (reference p) {
0521 (&p) -> ~value_type ();
0522 }
0523 ALLOC alloc_;
0524 size_type capacity_;
0525 pointer data_;
0526 size_type size_;
0527 };
0528
0529
0530 namespace detail {
0531 template<class A, class T>
0532 struct map_traits {
0533 typedef typename A::mapped_type &reference;
0534 };
0535 template<class I, class T, class ALLOC>
0536 struct map_traits<map_array<I, T, ALLOC>, T > {
0537 typedef typename map_array<I, T, ALLOC>::data_reference reference;
0538 };
0539
0540
0541
0542
0543 template<class M>
0544 BOOST_UBLAS_INLINE
0545 void map_reserve (M &, typename M::size_type ) {
0546 }
0547 template<class I, class T, class ALLOC>
0548 BOOST_UBLAS_INLINE
0549 void map_reserve (map_array<I, T, ALLOC> &m, typename map_array<I, T, ALLOC>::size_type capacity) {
0550 m.reserve (capacity);
0551 }
0552
0553 template<class M>
0554 struct map_capacity_traits {
0555 typedef typename M::size_type type ;
0556 type operator() ( M const& m ) const {
0557 return m.size ();
0558 }
0559 } ;
0560
0561 template<class I, class T, class ALLOC>
0562 struct map_capacity_traits< map_array<I, T, ALLOC> > {
0563 typedef typename map_array<I, T, ALLOC>::size_type type ;
0564 type operator() ( map_array<I, T, ALLOC> const& m ) const {
0565 return m.capacity ();
0566 }
0567 } ;
0568
0569 template<class M>
0570 BOOST_UBLAS_INLINE
0571 typename map_capacity_traits<M>::type map_capacity (M const& m) {
0572 return map_capacity_traits<M>() ( m );
0573 }
0574 }
0575
0576 }}}
0577
0578 #endif