#ifndef _utl_SparseVector_h_ #define _utl_SparseVector_h_ #include #include #include namespace utl { /** \class SparseVector SparseVector.h "utl/SparseVector.h" \brief Sparse container class for vectorial data Importatant notes:
  • the operator[] access is not creating entries. It should be used for reading of the whole vector.
  • the operator() access creates the corresponding entry on the fly and initializes it to GetInitializer() before the reference to the element is returned
Please refer to the testSparseVector.cc and test SparseMatrixVectorOps.cc files for detailed usage cases. \author Darko Veberic \version $Id$ \date 3 Jun 2008 \ingroup math */ template class SparseVector { public: typedef int IndexType; private: typedef std::map MapType; typedef typename MapType::value_type MapValueType; typedef typename MapType::iterator MapIterator; typedef typename MapType::const_iterator MapConstIterator; public: template class IteratorTransformer { public: IteratorTransformer(const IteratorType& it) : fIterator(it) { } IndexType GetIndex() const { return fIterator->first; } ValueType& operator()() const { return fIterator->second; } ValueType& operator*() const { return fIterator->second; } IteratorTransformer& operator++() { ++fIterator; return *this; } bool operator==(const IteratorTransformer& it) const { return fIterator == it.fIterator; } bool operator!=(const IteratorTransformer& it) const { return fIterator != it.fIterator; } private: IteratorType fIterator; }; SparseVector(const T& init = T()) : fInitializer(init) { } template explicit SparseVector(const SparseVector& v) : fInitializer(v.GetInitializer()) { for (typename SparseVector::ConstIterator it = v.SparseBegin(); it != v.SparseEnd(); ++it) (*this)(it.GetIndex()) = it(); } unsigned int GetNonEmptySize() const { return fVector.size(); } const T& GetInitializer() const { return fInitializer; } void Clear() { fVector.clear(); } /// noncreating element access const T& operator[](const IndexType index) const { const MapConstIterator it = fVector.find(index); return (it == fVector.end()) ? fInitializer : it->second; } /// creating element access T& operator()(const IndexType index) { return fVector.insert(MapValueType(index, fInitializer)).first->second; } const T& operator()(const IndexType index) const { const MapConstIterator it = fVector.find(index); return (it == fVector.end()) ? fInitializer : it->second; } bool IsEmpty() const { return fVector.empty(); } bool IsEmpty(const IndexType index) const { const MapConstIterator it = fVector.find(index); return it == fVector.end(); } /// remove "empty" elements (that are equal to the initializer) unsigned int Reclaim() { unsigned int erased = 0; for (MapIterator it = fVector.begin(); it != fVector.end(); ) if (it->second != fInitializer) ++it; else { Erase(it++); ++erased; } return erased; } bool operator==(const SparseVector& v) const { return fInitializer == v.fInitializer && fVector == v.fVector; } bool operator!=(const SparseVector& v) const { return !operator==(v); } template bool operator==(const SparseVector& v) const { if (fInitializer != v.GetInitializer()) return false; ConstIterator it1 = SparseBegin(); typename SparseVector::ConstIterator it2 = v.SparseBegin(); while (it1 != SparseEnd() && it2 != v.SparseEnd()) { if (it1.GetIndex() != it2.GetIndex() || it1() != it2()) return false; ++it1; ++it2; } if (it1 != SparseEnd() || it2 != v.SparseEnd()) return false; return true; } template bool operator!=(const SparseVector& v) const { return !operator==(v); } typedef IteratorTransformer Iterator; typedef IteratorTransformer ConstIterator; Iterator SparseBegin() { return Iterator(fVector.begin()); } ConstIterator SparseBegin() const { return ConstIterator(fVector.begin()); } Iterator SparseEnd() { return Iterator(fVector.end()); } ConstIterator SparseEnd() const { return ConstIterator(fVector.end()); } Iterator Find(const IndexType index) { return Iterator(fVector.find(index)); } ConstIterator Find(const IndexType index) const { return ConstIterator(fVector.find(index)); } /// multiplication with scalar template SparseVector& operator*=(const U& value) { for (MapIterator it = fVector.begin(); it != fVector.end(); ++it) it->second *= value; return *this; } /// vector addition template SparseVector& operator+=(const SparseVector& m) { for (typename SparseVector::ConstIterator it = m.SparseBegin(); it != m.SparseEnd(); ++it) (*this)(it.GetIndex()) += it(); return *this; } /// vector subtraction template SparseVector& operator-=(const SparseVector& m) { for (typename SparseVector::ConstIterator it = m.SparseBegin(); it != m.SparseEnd(); ++it) (*this)(it.GetIndex()) -= it(); return *this; } private: void Erase(const MapIterator it) { fVector.erase(it); } const T fInitializer; MapType fVector; }; /// dot product (scalar product of vectors) template typename boost::lambda::return_type_2< boost::lambda::arithmetic_action, SparseVector, SparseVector >::type operator*(const SparseVector& a, const SparseVector& b) { typedef typename boost::lambda::return_type_2< boost::lambda::arithmetic_action, SparseVector, SparseVector >::type Result; Result r = Result(); typename SparseVector::ConstIterator aIt = a.SparseBegin(); typename SparseVector::ConstIterator bIt = b.SparseBegin(); if (aIt == a.SparseEnd() || bIt == b.SparseEnd()) return r; typename SparseVector::IndexType ai; typename SparseVector::IndexType bi; do { ai = aIt.GetIndex(); bi = bIt.GetIndex(); if (ai < bi) { ++aIt; continue; } if (bi < ai) { ++bIt; continue; } r += aIt() * bIt(); ++aIt; ++bIt; } while (aIt != a.SparseEnd() && bIt != b.SparseEnd()); return r; } // output stuff template Stream& Output(Stream& s, const SparseVector& v, const unsigned int size, const char separator = ' ') { if (!size) return s; if (v.IsEmpty(0)) s << '.'; else s << v[0]; for (unsigned int i = 1; i < size; ++i) if (v.IsEmpty(i)) s << separator << '.'; else s << separator << v[i]; return s; } } namespace boost { namespace lambda { template class plain_return_type_2< arithmetic_action, utl::SparseVector, utl::SparseVector > { private: // delegate to the action result of (T, Action, U) typedef typename return_type_2< arithmetic_action, T, U >::type res_type; public: typedef res_type type; }; } } #include #endif