Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:43:14

0001 //
0002 //  Copyright (c) 2000-2002
0003 //  Joerg Walter, Mathias Koch
0004 //
0005 //  Distributed under the Boost Software License, Version 1.0. (See
0006 //  accompanying file LICENSE_1_0.txt or copy at
0007 //  http://www.boost.org/LICENSE_1_0.txt)
0008 //
0009 //  The authors gratefully acknowledge the support of
0010 //  GeNeSys mbH & Co. KG in producing this work.
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             // t <= *begin <=> ! (*begin < t)
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             // (*end - 1) <= t <=> ! (t < *end)
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         // typedef const data_value_type &data_const_reference;
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         // Construction and destruction
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         // Element access - only if data_const_reference is defined
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         // Assignment
0113         BOOST_UBLAS_INLINE
0114         sparse_storage_element &operator = (const sparse_storage_element &p) {
0115             // Overide the implict copy assignment
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         // Comparison
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         // Conversion
0169         BOOST_UBLAS_INLINE
0170         operator data_const_reference () const {
0171             return d_;
0172         }
0173 
0174         // Swapping
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     // Default map type is simply forwarded to std::map
0198     template<class I, class T, class ALLOC>
0199     class map_std : public std::map<I, T, std::less<I>, ALLOC> {
0200     public:
0201          // Serialization
0202         template<class Archive>
0203         void serialize(Archive & ar, const unsigned int /* file_version */){
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     // Map array
0212     //  Implementation requires pair<I, T> allocator definition (without const)
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         // Iterators simply are pointers.
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         // Construction and destruction
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                 // capacity != size_ requires uninitialized_fill (size_ to capacity_)
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         // Resizing - implicitly exposses uninitialized (but default constructed) mapped_type
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         // Reserving
0287         BOOST_UBLAS_INLINE
0288         void reserve (size_type capacity) {
0289             BOOST_UBLAS_CHECK (size_ <= capacity_, internal_logic ());
0290             // Reduce capacity_ if size_ allows
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         // Random Access Container
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; //TODO
0322         }
0323        
0324         BOOST_UBLAS_INLINE
0325         bool empty () const {
0326             return size_ == 0;
0327         }
0328             
0329         // Element access
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         // Assignment
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         // Swapping
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         // Element insertion and deletion
0373         
0374         // From Back Insertion Sequence concept
0375         // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.    
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         // Form Unique Associative Container concept
0386         // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.    
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;    // allow for invalidation
0394             std::copy_backward (it, end () - 1, end ());
0395             *it = p;
0396             return std::make_pair (it, true);
0397         }
0398         // Form Sorted Associative Container concept
0399         // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.    
0400                 iterator insert (iterator /*hint*/, const value_type &p) {
0401             return insert (p).first;
0402         }
0403         // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.    
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         // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.    
0410         void erase (iterator it1, iterator it2) {
0411             if (it1 == it2) return /* nothing to erase */;
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         // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.    
0417         void clear () {
0418             resize (0);
0419         }
0420 
0421         // Element lookup
0422         // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.    
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         // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.    
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         // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.    
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         // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.    
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         // Reverse iterators
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         // Allocator
0502         allocator_type get_allocator () {
0503             return alloc_;
0504         }
0505 
0506          // Serialization
0507         template<class Archive>
0508         void serialize(Archive & ar, const unsigned int /* file_version */){
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         // Provide destroy as a non member function
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         // reserve helpers for map_array and generic maps
0541         // ISSUE should be in map_traits but want to use on all compilers
0542 
0543         template<class M>
0544         BOOST_UBLAS_INLINE
0545         void map_reserve (M &/* m */, typename M::size_type /* capacity */) {
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