aimstil  5.0.5
sparse_vector.h
Go to the documentation of this file.
1 #ifndef TIL_SPARSE_VECTOR_H_
2 #define TIL_SPARSE_VECTOR_H_
3 
4 // includes from TIL
5 //#include "til/miscTools.h"
6 
7 // includes from TIL
9 #include "std_wrap.h"
10 #include "value_proxy.h"
11 
12 namespace til
13 {
14 
15  //----------------------------------------------------------------------------------
16 
17 
18  //namespace {
19 
21  // NB: the design of Loop_mapEach is a bit crappy because it requires the functor to be highly non standard,
22  // accepting combinations of pairs/T, plus the assignment is a problem, because when the first argument
23  // passed is a number, of course, the container cannot be updated. I wonder if there is a general way
24  // to do that.
25  // Here, the functor is standard, it is a stl-like functor returning a value, and this value
26  // is assigned to the first container. So, restricted use, but cleaner.
27  // I also restricted it to sparse_vector class because I want to use the set() functionality, which
28  // is useful to check for non-zero entries. TODO: Maybe this should be a policy instead
29  template < typename TMap1, typename TMap2, typename TFunctor >
31  {
32  public: // operators
33 
34  //TODO: I think it should really use iterator arguments instead. And those iterators probably
35  // should be private data so that no argument passing between functions
36  void operator()(TMap1 & map1, const TMap2 & map2, TFunctor f)
37  {
38  typename TMap1::iterator i1 = map1.begin();
39  typename TMap2::const_iterator i2 = map2.begin();
40 
41  if (i1 == map1.end()) goto map1over_checkmap2;
42  if (i2 == map2.end()) goto map2over;
43 
44  // NB: not using goto's would me to have additional end checks at each if's. This function is
45  // very low-level thus time critical, so let's stick with goto's.
46  for (;;)
47  {
48  if (i1->first < i2->first)
49  {
50  //res.insert(res.end(), std::make_pair(i1->first, f(i1->second, T())));
51  //f(i1->first, i1->second, T());
52  // TODO: This is probably no good. Imagine that mapped_type is something heavy to allocate.
53  // Probably better to instanciate a default somewhere. Policy here?
54  i1->second = f(i1->second, typename TMap2::mapped_type());
55  if (++i1 == map1.end())
56  //return this->map1over(map2, f);
57  goto map1over;
58  }
59  else if (i1->first > i2->first)
60  {
61  //res.insert(res.end(), std::make_pair(i2->first, f(i2->second, T())));
62  //f(i2->first, i2->second, T());
63  // create a new entry in map1
64  map1[i2->first] = f(typename TMap1::mapped_type(), i2->second);
65  if (++i2 == map2.end())
66  //return this->map2over(map1, f);
67  goto map2over;
68  }
69  else
70  {
71  //res.insert(res.end(), std::make_pair(i1->first, f(i1->second, i2->second)));
72  //f(i1->first, i1->second, i2->second);
73  i1->second = f(i1->second, i2->second);
74  if (++i1 == map1.end())
75  {
76  ++i2;
77  //return this->map1over_checkmap2(map2, f);
78  goto map1over_checkmap2;
79  }
80  if (++i2 == map2.end())
81  //return this->map2over(map1, f);
82  goto map2over;
83  }
84  }
85 
86  return;
87 
88  map1over_checkmap2:
89  if (i2 == map2.end()) return;
90 
91  map1over:
92  do
93  {
94  map1[i2->first] = f(typename TMap1::mapped_type(), i2->second);
95  }
96  while (++i2 != map2.end());
97  return;
98 
99  map2over:
100  do
101  {
102  i1->second = f(i1->second, typename TMap2::mapped_type());
103  }
104  while (++i1 != map1.end());
105  return;
106  }
107  };
108 
109  template < typename TMap1, typename TMap2, typename TFunctor >
110  //typename boost::enable_if<boost::is_stateless<TFunctor> >::type
111  void
112  loop_mapEachAssign(TMap1 & map1, TMap2 & map2, TFunctor f)
113  {
115  }
116  //}
117 
118 
119  //----------------------------------------------------------------------------------
120 
121  //-----------------//
122  // sparse_vector //
123  //-----------------//
124 
125 
132 
133  template < typename T, typename BaselinePolicy = policy::SVBaseline_Value<T> >
135  {
136  private: // classes
137 
140  //class ValueProxy;
141  //class ConstValueProxy;
142 
143  public: // classes
144 
146  class sparse_iterator;
148  class sparse_const_iterator;
150  class const_iterator;
151  class iterator;
152 
153  public: // typedefs
154 
155  typedef sparse_vector<T> Self;
156  typedef std::map<std::size_t, T> Map;
157  //typedef typename Map::key_type key_type;
158  typedef typename Map::mapped_type value_type;
159  typedef T const_reference;
160  typedef ValueProxy reference;
161  typedef const T * const_pointer;
162 
163  public: // constructors & destructor
164 
167  m_data()
168  , m_size()
169  , m_baselinePolicy()
170  , m_proxyIndex(std::numeric_limits<std::size_t>::max())
171  {}
172 
174  sparse_vector(std::size_t d) :
175  m_data()
176  , m_size(d)
177  , m_baselinePolicy()
178  , m_proxyIndex(std::numeric_limits<std::size_t>::max())
179  {}
180 
181  public: // set & get
182 
187  ValueProxy operator[](std::size_t i)
188  {
189  assert( i < m_size );
190  return ValueProxy(i, *this);
191  }
192 
193  // I don't really understand why we should mess with a ConstValueProxy here?
194  // We can understand that writing is costly, but reading surely has to be as
195  // fast as possible.
196  /*
197  ConstValueProxy operator[](std::size_t i) const
198  {
199  assert( i < m_size );
200  return ConstValueProxy(i, this);
201  }
202  */
203 
205  T operator[](std::size_t i) const
206  {
207  return this->get(i);
208  }
209 
210  public: //functions
211 
212  // NB: these functions bring nothing more to the user than the more standard
213  // operator[], so it's advisable to use the later instead. The only reason these
214  // are public is that (1) proxies need them, (2) I would rather not mess around
215  // with friends if I can, and (3) these functions having the same functionality
216  // as operator[], they are as harmless (or harmful). The only reason to set them
217  // to private would be to reduce noise in the API (which is a very good reason btw).
218 
220  // NB: we have to return a T and not a const T & since return value might be created
221  // inside the function
222  // NB: no non-const counterpart is given, because we don't want to initialize a value
223  // to default value.
224  T get(std::size_t i) const
225  {
226  assert( i < m_size);
227  typename Map::const_iterator pos ( m_data.find(i) );
228  if (pos != m_data.end())
229  {
230  return pos->second;
231  }
232  else
233  {
234  return m_baselinePolicy(i);
235  }
236  }
237 
238  /*
240  T & get(std::size_t i)
241  {
242  assert( i < m_size);
243  //return m_data[i];
244 
245  // NB: The following code is doing the same thing as the commented single line above.
246  // There is no performance gain or loss in doing that -- actually the running time
247  // seems to be exactly the same. However, the following code runs with multimap, while
248  // the previous line doesn't. So I keep it for later comparisons.
249 
250  typename Map::iterator pos ( m_data.find(i) );
251  if (pos != m_data.end())
252  {
253  return pos->second;
254  }
255  else
256  {
257  m_data.insert(std::make_pair(i,value));
258  }
259  }
260  */
261 
263  void set(std::size_t i, const T & value)
264  {
265  assert(i < m_size);
266 
267  if (value != m_baselinePolicy(i))
268  {
269  // Set element to non-default value
270 
271  //m_data[i] = value;
272 
273  // NB: The following code is doing the same thing as the commented single line above.
274  // There is no performance gain or loss in doing that -- actually the running time
275  // seems to be exactly the same. However, the following code runs with multimap, while
276  // the previous line doesn't. So I keep it for later comparisons.
277  sparse_iterator pos = m_data.find(i);
278 
279  if (pos != m_data.end())
280  {
281  pos->second = value;
282  }
283  else
284  {
285  m_data.insert(std::make_pair(i,value));
286  }
287  }
288  else
289  {
290  // Remove element set to default value.
291 
292  sparse_iterator pos = m_data.find(i);
293  if (pos != m_data.end())
294  {
295  m_data.erase(pos);
296  }
297  }
298  }
299 
300 
301  /*
302  public: // friend functions
303 
304  template < typename X, typename TFunctor >
305  void applyFunctor_all(const SparseVector<X> &sv1, const SparseVector<X> &sv2, TFunctor & f);
306 
307  template < typename X, typename TFunctor >
308  void applyFunctor_pairs(const SparseVector<X> &sv1, const SparseVector<X> &sv2, TFunctor & f);
309 
310  private: // set & get
311  */
312 
314  // TODO: put this in private and add friends
315  Map & getMap() { return m_data;}
316  Map const & getMap() const { return m_data;}
317 
318  //T getDefaultValue() const { return m_defaultValue; }
319  //void setDefaultValue(typename boost::call_traits<T>::param_type value) { m_defaultValue = value; }
320 
321  BaselinePolicy baselinePolicy() const { return m_baselinePolicy; }
322  BaselinePolicy & baselinePolicy () { return m_baselinePolicy; }
323 
324  public: // functions
325 
329  std::size_t size() const { return m_size; }
330 
332  void clear()
333  {
334  m_data.clear();
335  m_size = 0;
336  }
337 
339  bool empty() const { return m_size == 0; }
340 
342  void erase(const sparse_iterator & i) { m_data.erase(i); }
343 
345  bool is_null() const
346  {
347  for(typename Map::const_iterator i = m_data.begin(); i != m_data.end(); ++i)
348  {
349  if ((i->second)!=0) return false;
350  }
351  return true;
352  }
353  /*
354  public: // operators used for proxy operations -- should be private, have to be public :(
355  // All of these operations are highly risky, and should be used only by generic functions that
356  // do not know they deal with sparse_vectors
357 
358  // TODO: check that we really gain in speed by *not* using a proxy class. If not, there is not
359  // reason to get stuck with this very unsafe way of doing things...
360 
362  // Assign a value to proxy-ed element
363  void operator=(typename boost::call_traits<T>::param_type value)
364  {
365  this->set(m_proxyIndex, value);
366  //m_proxyIndex = std::numeric_limits<std::size_t>::max();
367  }
368 
370  // Get the value of the proxy-ed element
371  operator T ()
372  {
373  return this->get(m_proxyIndex);
374  }
375 
376  */
377 
378  public: // iterators
379 
380  // Iterators on the data. Note that these iterators iterate only on the non-zero
381  // values of the vector; plus, they return a pair (index, value), not a simple value.
382  // Thus, they are not compatible and alike other vector iterators -- hence the non-standard names.
383 
384  sparse_iterator sparse_begin() { return m_data.begin(); }
385  sparse_iterator sparse_end () { return m_data.end (); }
386  sparse_const_iterator sparse_begin() const { return m_data.begin(); }
387  sparse_const_iterator sparse_end () const { return m_data.end (); }
388 
389  const_iterator begin() const { return const_iterator(0, *this); }
390  const_iterator end() const { return const_iterator(this->size(), *this); }
391  iterator begin() { return iterator(0, *this); }
392  iterator end() { return iterator(this->size(), *this); }
393 
394  public: // exceptions
395 
396  class OutOfRange : public std::out_of_range
397  {
398  public: // constructors & destructor
399  OutOfRange(const std::string & msg) : std::out_of_range(msg) {}
400  };
401 
402  public: // operators
403 
404  void operator+=(const sparse_vector<T> & a)
405  { loop_mapEachAssign(this->getMap(), a.getMap(), std::plus<T>()); }
406  void operator-=(const sparse_vector<T> & a)
407  { loop_mapEachAssign(this->getMap(), a.getMap(), std::minus<T>()); }
408  void operator*=(const sparse_vector<T> & a)
409  { loop_mapEachAssign(this->getMap(), a.getMap(), std::multiplies<T>()); }
410  void operator/=(const sparse_vector<T> & a)
411  { loop_mapEachAssign(this->getMap(), a.getMap(), std::divides<T>()); }
412 
413  void operator+=(const T & value)
414  { for (typename Map::iterator i = m_data.begin(); i != m_data.end(); ++i) i->second += value; }
415  void operator-=(const T & value)
416  { for (typename Map::iterator i = m_data.begin(); i != m_data.end(); ++i) i->second -= value; }
417  void operator*=(const T & value)
418  { for (typename Map::iterator i = m_data.begin(); i != m_data.end(); ++i) i->second *= value; }
419 
420  private: // data
421 
422  // Contains the actual data
423  Map m_data;
424  // (virtual) size of our vector
425  std::size_t m_size;
426  // our default values
427  BaselinePolicy m_baselinePolicy;
428  // index used during proxy access
429  std::size_t m_proxyIndex;
430  };
431 
432 
433  //----------------------------------------------------------------------------------
434 
435 
436  //-----------------------------//
437  // sparse_vector::ValueProxy //
438  //-----------------------------//
439 
440 
441  /*
442  template < typename T, typename BaselinePolicy >
443  class sparse_vector<T>::ValueProxy : public value_proxy<sparse_vector<T> >
444  {
445  public: // typedefs
446  typedef value_proxy<sparse_vector<T> > Base;
447 
448  public: // constructors & destructor
449  ValueProxy(std::size_t i, sparse_vector<T> & sv) : Base(i, sv) {}
450 
451  public: // operators
452  // unfortunately we have to redefine this function by hand :(
453  void operator=(typename boost::call_traits<T>::param_type value) { this->Base::operator=(value); }
454  };
455 
456 
457  template < typename T, typename BaselinePolicy >
458  class sparse_vector<T>::ConstValueProxy : public const_value_proxy<const sparse_vector<T> >
459  {
460  public: // typedefs
461  typedef const_value_proxy<const sparse_vector<T> > Base;
462 
463  public: // constructors & destructor
464  ConstValueProxy(std::size_t i, const sparse_vector<T> * pSparseVector) : Base(i, pSparseVector) {}
465  public: // operators
466  // unfortunately we have to redefine this function by hand :(
467  void operator=(typename boost::call_traits<T>::param_type value) { this->Base::operator=(value); }
468  };
469  */
470 
471 
472  // NB: these have no interest at all; they are just wrappers around Map::iterators
473  // so that they are unique and distinguisable from Map::iterators, so that we can
474  // specialize stl functions for sparse_vector iterators only.
475  // TODO: change this so that it has the look'n'feel of a standard container.
476  // Actually, it probably need to be an indexed_iterator, namely an iterator yielding
477  // its index, so make it a sparse_indexed_iterator
478 
479  // TODO: actually, sparse_iterators should be much smarter than that. In particular, they should
480  // know whether to destroy current entry or not if it is set to zero, based on the container
481  // policy.
482  template < typename T, typename BaselinePolicy >
483  class sparse_vector<T,BaselinePolicy>::sparse_iterator : public Map::iterator
484  {
485  public: // typedefs
486  typedef typename Map::iterator Base;
487  public: // constructors & destructor
488  sparse_iterator() : Base() {}
489  sparse_iterator(const Base & b) : Base(b) {}
490  };
491 
492 
493  template < typename T, typename BaselinePolicy >
494  class sparse_vector<T,BaselinePolicy>::sparse_const_iterator : public Map::const_iterator
495  {
496  public: // typedefs
497  typedef typename Map::const_iterator Base;
498  public: // constructors & destructor
499  sparse_const_iterator() : Base() {}
500  sparse_const_iterator(const Base & b) : Base(b) {}
501  sparse_const_iterator(const sparse_iterator & i) : Base(i) {}
502  };
503 
504  namespace detail
505  {
506  template < typename TSparseVector, typename Proxy >
508  {
509  public: // typedefs
511  typedef typename TSparseVector::value_type value_type;
512  public: // constructors & destructor
513  //const_iterator(Self * pSparseVector) : m_valueProxy(0, pSparseVector) {}
514  sparse_vector_iterator_base(std::size_t i, TSparseVector & sv) : m_valueProxy(i, sv) {}
515  template < typename XSparseVector, typename XProxy >
517  : m_valueProxy(it.proxy()) {}
518  public: // set & get
519  const Proxy & proxy() const { return m_valueProxy; }
520  Proxy & proxy() { return m_valueProxy; }
521  public: // operators
522  //const ValueProxy & operator*() { return m_valueProxy; }
523  //reference operator*() { return *m_valueProxy; }
524  void operator++() { ++(m_valueProxy.index()); }
525  public: // friends
526  //friend bool operator==(const typename sparse_vector<T>::const_iterator & i1, const typename sparse_vector<T>::const_iterator & i2) { return i1.m_valueProxy.index() == i2.m_valueProxy.index(); }
527  //friend bool operator!=(const typename sparse_vector<T>::const_iterator & i1, const typename sparse_vector<T>::const_iterator & i2) { return i1.m_valueProxy.index() != i2.m_valueProxy.index(); }
528  /*
529  template < typename T1, typename P1, typename T2, typename P2 >
530  friend bool operator == (const sparse_vector_iterator_base<T1,P1> & i1,const sparse_vector_iterator_base<T2,P2> & i2);
531  template < typename T1, typename P1, typename T2, typename P2 >
532  friend bool operator != (const sparse_vector_iterator_base<T1,P1> & i1,const sparse_vector_iterator_base<T2,P2> & i2);
533  */
534 
535 
536  //void operator=(const Self & other) { m_valueProxy = other.m_valueProxy; }
537 
538 
539  protected: // data
541  };
542 
543  template < typename T1, typename P1, typename T2, typename P2 >
544  inline bool operator ==
545  (
548  )
549  { return i1.proxy().index() == i2.proxy().index(); }
550 
551  template < typename T1, typename P1, typename T2, typename P2 >
552  inline bool operator !=
553  (
556  )
557  { return i1.proxy().index() != i2.proxy().index(); }
558 
559  }
560 
561  template < typename T, typename BaselinePolicy >
562  class sparse_vector<T,BaselinePolicy>::const_iterator
563  : public detail::sparse_vector_iterator_base<const sparse_vector<T, BaselinePolicy>, ConstValueProxy >
564  {
565  public: // typedefs
568  typedef const T * pointer;
569  public: // constructors
570  const_iterator(std::size_t i, const sparse_vector<T,BaselinePolicy> & p) : Base(i,p) {}
571  const_iterator(const iterator & it) : Base(it) {}
572  const_reference operator*() { return const_reference(this->proxy()); }
573  pointer operator->() { return Base::m_valueProxy.operator->(); }
574  };
575 
576  template < typename T, typename BaselinePolicy >
577  class sparse_vector<T,BaselinePolicy>::iterator
578  : public detail::sparse_vector_iterator_base<sparse_vector<T,BaselinePolicy>, ValueProxy>
579  {
580  public: // typedefs
583  typedef T * pointer;
584  public: // constructors
585  iterator(std::size_t i, sparse_vector<T,BaselinePolicy> & p) : Base(i,p) {}
586  ValueProxy & operator*() { return this->proxy(); }
587  pointer operator->() { return Base::m_valueProxy.operator->(); }
588 
589 
590  //void operator=(const iterator & i) { return this->Base::operator=(i); }
591  };
592 
593  /*
594  template < typename T >
595  class sparse_vector<T>::const_iterator
596  {
597  public: // typedefs
598  typedef const_iterator Self;
599  public: // constructors & destructor
600  //const_iterator(Self * pSparseVector) : m_valueProxy(0, pSparseVector) {}
601  const_iterator(std::size_t i, const Self * pSparseVector) : m_valueProxy(i, pSparseVector) {}
602  public: // operators
603  //const ValueProxy & operator*() { return m_valueProxy; }
604  T operator*() { return T(m_valueProxy); }
605  void operator++() { ++(m_valueProxy.index()); }
606  public: // friends
607  //friend bool operator==(const typename sparse_vector<T>::const_iterator & i1, const typename sparse_vector<T>::const_iterator & i2) { return i1.m_valueProxy.index() == i2.m_valueProxy.index(); }
608  //friend bool operator!=(const typename sparse_vector<T>::const_iterator & i1, const typename sparse_vector<T>::const_iterator & i2) { return i1.m_valueProxy.index() != i2.m_valueProxy.index(); }
609  friend inline bool operator==(const Self & i1, const Self & i2) { return i1.m_valueProxy.index() == i2.m_valueProxy.index(); }
610  friend inline bool operator!=(const Self & i1, const Self & i2) { return i1.m_valueProxy.index() != i2.m_valueProxy.index(); }
611  private: // data
612  ConstValueProxy m_valueProxy;
613  };
614  */
615 
620  template < typename T, typename BaselinePolicy >
621  inline void fill(sparse_vector<T,BaselinePolicy> & v, typename boost::call_traits<T>::param_type value)
622  {
623  v.getMap().clear();
624  v.baselinePolicy().setValue(value);
625  }
626 }
627 
628 
629 // Package includes
631 #include "til/sparse_vector_tools.h"
632 
633 #endif /*SPARSE_VECTOR_H_*/
T operator[](std::size_t i) const
Get value of i-th element.
sparse_vector(std::size_t d)
Create a null vector of length d.
void clear()
Alike STL container&#39;s "clear".
const_iterator end() const
sparse_iterator sparse_begin()
sparse_const_iterator(const sparse_iterator &i)
ValueProxy reference
Adds some left-value operations to const_value_proxy.
Definition: value_proxy.h:102
OutOfRange(const std::string &msg)
STL namespace.
void operator*=(const sparse_vector< T > &a)
BaselinePolicy baselinePolicy() const
Belongs to package Box Do not include directly, include til/Box.h instead.
Definition: Accumulator.h:10
std::map< std::size_t, T > Map
void operator()(TMap1 &map1, const TMap2 &map2, TFunctor f)
Definition: sparse_vector.h:36
const_iterator(std::size_t i, const sparse_vector< T, BaselinePolicy > &p)
const_iterator begin() const
sparse_iterator sparse_end()
void loop_mapEachAssign(TMap1 &map1, TMap2 &map2, TFunctor f)
numeric_array< T, D > size(const Box< T, D > &box)
Return the size of a box.
Definition: boxTools.h:56
detail::sparse_vector_iterator_base< const sparse_vector< T, BaselinePolicy >, ConstValueProxy > Base
detail::sparse_vector_iterator_base< sparse_vector< T, BaselinePolicy >, ValueProxy > Base
sparse_vector()
Create a null vector of size 0.
void erase(const sparse_iterator &i)
Alike STL container&#39;s "erase".
A class that mimic the behavior of std::vector but with a storage policy focused on sparse data...
void operator/=(const sparse_vector< T > &a)
sparse_vector_iterator_base(std::size_t i, TSparseVector &sv)
iterator(std::size_t i, sparse_vector< T, BaselinePolicy > &p)
TImage::value_type max(const TImage &im)
Returns the maximum intensity of the input image.
sparse_const_iterator sparse_begin() const
ValueProxy operator[](std::size_t i)
Read-write access to i-th element.
sparse_const_iterator sparse_end() const
Map & getMap()
Returns the internal data.
bool is_null() const
void operator-=(const sparse_vector< T > &a)
const_iterator(const iterator &it)
sparse_vector< T > Self
sparse_vector_iterator_base Self
TSparseVector::value_type value_type
sparse_vector_iterator_base(sparse_vector_iterator_base< XSparseVector, XProxy > it)
Map const & getMap() const
The value_proxy is designed to provide a simple access to container values that are in fact complicat...
Definition: value_proxy.h:33
std::size_t size() const
Alike STL container&#39;s "size".
Apply a functor to a pair of sparse vectors where either one has data.
Definition: sparse_vector.h:30
void operator-=(const T &value)
BaselinePolicy & baselinePolicy()
bool empty() const
Alike STL container&#39;s "empty".
const T * const_pointer
void fill(sparse_vector< T, BaselinePolicy > &v, typename boost::call_traits< T >::param_type value)
Specialized fill for sparse_vector.
void operator+=(const T &value)
Map::mapped_type value_type
void operator+=(const sparse_vector< T > &a)
void operator*=(const T &value)