$extrastylesheet
Olena  User documentation 2.1
An Image Processing Platform
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
p_key.hh
1 // Copyright (C) 2008, 2009, 2013 EPITA Research and Development
2 // Laboratory (LRDE)
3 //
4 // This file is part of Olena.
5 //
6 // Olena is free software: you can redistribute it and/or modify it under
7 // the terms of the GNU General Public License as published by the Free
8 // Software Foundation, version 2 of the License.
9 //
10 // Olena is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with Olena. If not, see <http://www.gnu.org/licenses/>.
17 //
18 // As a special exception, you may use this file as part of a free
19 // software project without restriction. Specifically, if other files
20 // instantiate templates or use macros or inline functions from this
21 // file, or you compile this file and link it with other files to produce
22 // an executable, this file does not by itself cause the resulting
23 // executable to be covered by the GNU General Public License. This
24 // exception does not however invalidate any other reasons why the
25 // executable file might be covered by the GNU General Public License.
26 
27 #ifndef MLN_CORE_SITE_SET_P_KEY_HH
28 # define MLN_CORE_SITE_SET_P_KEY_HH
29 
35 
36 # include <map>
37 # include <mln/core/concept/function.hh>
38 # include <mln/core/site_set/p_set.hh>
39 # include <mln/core/site_set/p_double.hh>
40 # include <mln/core/internal/site_set_base.hh>
41 # include <mln/util/ord.hh>
42 
43 
44 namespace mln
45 {
46 
47  // Forward declaration.
48  template <typename K, typename P> class p_key;
49 
50 
51 
52  namespace trait
53  {
54 
55  template <typename K, typename P>
56  struct site_set_< p_key<K,P> >
57  {
58  typedef trait::site_set::nsites::known nsites;
59  typedef trait::site_set::bbox::unknown bbox;
60  typedef trait::site_set::contents::growing contents;
61  typedef trait::site_set::arity::unique arity;
62  };
63 
64  } // end of namespace trait
65 
66 
67 
68 
72  template <typename K, typename P>
73  class p_key : public internal::site_set_base_< P,
74  p_key<K,P> >
75  {
76  typedef p_key<K,P> self_;
77  public:
78 
80  typedef P element;
81 
82 
85 
87  typedef p_double_piter<self_,
88  mln_fwd_eiter(util::set<K>),
89  mln_fwd_piter(p_set<P>)> fwd_piter;
90 
92  typedef p_double_piter<self_,
93  mln_bkd_eiter(util::set<K>),
94  mln_bkd_piter(p_set<P>)> bkd_piter;
95 
97  typedef fwd_piter piter;
98 
99 
101  p_key();
102 
103 
105  bool has(const psite&) const;
106 
108  bool has(const P& p) const;
109 
110 
112  bool is_valid() const;
113 
115  unsigned nsites() const;
116 
117 
119  typedef std::pair<K,P> i_element;
120 
122  void insert(const i_element& k_p);
123 
125  void insert(const K& k, const P& p);
126 
127 
129  void unsafe_insert_(const K& k, const P& p);
131 
132 
133 
135  typedef P r_element;
136 
138  void remove(const P& p);
139 
141  void remove_key(const K& k);
142 
144  void change_key(const K& k, const K& new_k);
145 
147  template <typename F>
148  void change_keys(const Function_v2v<F>& f);
149 
150 
151 
153  void clear();
154 
155 
159  const p_set<P>& operator()(const K& key) const;
160 
162  const K& key(const P& p) const;
163 
165  const util::set<K>& keys() const;
166 
167 
169  bool exists_key(const K& key) const;
170 
172  // Required by p_double-related classes.
173  const util::set<K>& set_1_() const;
174  const p_set<P>& set_2_(const K& key) const;
176 
177 
179  std::size_t memory_size() const;
180 
181  protected:
182 
183  // Bunch of keys.
185 
186  // Function: key k -> set of sites {p}.
187  typedef std::map<K, p_set<P>, util::ord<K> > s_t;
189 
190  // Function: site p -> key k.
191  typedef std::map<P, K, util::ord<P> > k_t;
193 
194  // Number of sites.
195  unsigned n_;
196 
197  // Run invariance tests and return the result.
198  bool run_() const;
199  };
200 
201 
203  template <typename K, typename P>
204  std::ostream& operator<<(std::ostream& ostr, const p_key<K,P>& pk);
205 
206 
207 
208 # ifndef MLN_INCLUDE_ONLY
209 
210  template <typename K, typename P>
211  inline
213  {
214  n_ = 0;
215  mln_invariant(run_());
216  }
217 
218  template <typename K, typename P>
219  inline
220  bool
221  p_key<K,P>::has(const psite&) const
222  {
223  mln_invariant(run_());
224  // FIXME
225  return true;
226  }
227 
228  template <typename K, typename P>
229  inline
230  bool
231  p_key<K,P>::has(const P& p) const
232  {
233  mln_invariant(run_());
234  return k_.find(p) != k_.end();
235  }
236 
237  template <typename K, typename P>
238  inline
239  bool
240  p_key<K,P>::is_valid() const
241  {
242  mln_invariant(run_());
243  return true;
244  }
245 
246  template <typename K, typename P>
247  inline
248  unsigned
249  p_key<K,P>::nsites() const
250  {
251  mln_invariant(run_());
252  return n_;
253  }
254 
255 
256  template <typename K, typename P>
257  inline
258  void
259  p_key<K,P>::unsafe_insert_(const K& k, const P& p)
260  {
261  s_[k].insert(p);
262  k_[p] = k;
263  ++n_;
264  b_.insert(k);
265  mln_invariant(run_());
266  }
267 
268 
269  template <typename K, typename P>
270  inline
271  void
272  p_key<K,P>::insert(const K& k, const P& p)
273  {
274  mln_invariant(run_());
275  typename k_t::iterator p_k = k_.find(p);
276  if (p_k != k_.end())
277  // p is already in this set (so n_ is unchanged).
278  {
279  K p_key = p_k->second;
280  mln_assertion(b_.has(p_key));
281  mln_assertion(s_[p_key].has(p));
282  if (p_key == k)
283  // No-op.
284  return;
285  // p moves from s_[p_key] to s_[k].
286  s_[p_key].remove(p);
287  s_[k].insert(p);
288  // Update key of p.
289  p_k->second = k;
290  }
291  else
292  // Actual insertion.
293  {
294  s_[k].insert(p);
295  k_[p] = k;
296  ++n_;
297  }
298  b_.insert(k);
299  mln_invariant(run_());
300  }
301 
302  template <typename K, typename P>
303  inline
304  void
305  p_key<K,P>::insert(const i_element& k_p)
306  {
307  this->insert(k_p.first, k_p.second); // Also test invariants.
308  }
309 
310  template <typename K, typename P>
311  inline
312  void
313  p_key<K,P>::remove(const P& p)
314  {
315  mln_invariant(run_());
316  typename k_t::iterator p_k = k_.find(p);
317 
318  if (p_k == k_.end())
319  // No-op because p does not belong to this site set.
320  return;
321 
322  K p_key = p_k->second;
323  mln_assertion(b_.has(p_key));
324 
325  // Update k_.
326  k_.erase(p_k);
327 
328  // Update s_.
329  typename s_t::iterator k_s = s_.find(p_key);
330  mln_assertion(k_s != s_.end()); // p_key found in s_.
331  p_set<P>& s = k_s->second;
332  mln_assertion(s.has(p)); // p is in s_[p_key].
333 
334  if (s.nsites() == 1)
335  {
336  // Clean up for p is the only site with p_key.
337  s_.erase(k_s);
338  b_.remove(p_key);
339  }
340  else
341  {
342  // Simple removal.
343  s.remove(p);
344  }
345 
346  // Update n_.
347  --n_;
348 
349  mln_invariant(run_());
350  }
351 
352  template <typename K, typename P>
353  inline
354  void
355  p_key<K,P>::remove_key(const K& k)
356  {
357  mln_invariant(run_());
358  typename s_t::iterator k_s = s_.find(k);
359 
360  if (k_s == s_.end())
361  // No-op because key k does not exist.
362  return;
363 
364  // Update b_.
365  b_.remove(k);
366 
367  // Update k_.
368  p_set<P>& s = k_s->second;
369  mln_piter(p_set<P>) p(s);
370  for_all(p)
371  k_.erase(p);
372 
373  // Update n_.
374  n_ -= s.nsites();
375 
376  // Update s_.
377  s_.erase(k_s);
378 
379  mln_invariant(run_());
380  }
381 
382 
383  template <typename K, typename P>
384  inline
385  void
386  p_key<K,P>::change_key(const K& k, const K& new_k)
387  {
388  mln_invariant(run_());
389 
390  if (new_k == k)
391  // No-op.
392  return;
393 
394  typename s_t::iterator k_s = s_.find(k);
395  if (k_s == s_.end())
396  // No-op because key k does not exist.
397  return;
398 
399  // Update b_.
400  b_.remove(k);
401  b_.insert(new_k);
402 
403  // Update k_.
404  p_set<P>& s = k_s->second;
405  if (s.nsites() < n_ / 10) // Few elements to be moved.
406  {
407  // s.nsites() iterations.
408  mln_piter(p_set<P>) p(s);
409  for_all(p)
410  k_[p] = new_k;
411  }
412  else
413  {
414  // n_ iterations.
415  typename k_t::iterator p_k;
416  for (p_k = k_.begin(); p_k != k_.end(); ++p_k)
417  if (p_k->second == k)
418  p_k->second = new_k;
419  }
420 
421  // Update s_.
422  s_[new_k] += s;
423  s_.erase(k_s);
424 
425  mln_invariant(run_());
426  }
427 
428  template <typename K, typename P>
429  template <typename F>
430  inline
431  void
432  p_key<K,P>::change_keys(const Function_v2v<F>& f_)
433  {
434  mln_invariant(run_());
435 
436  const F& f = exact(f_);
437  std::map<K,K> lut;
438 
439  // Update b_.
440  {
441  util::set<K> new_b;
442  mln_eiter(util::set<K>) k(b_);
443  for_all(k)
444  new_b.insert(lut[k] = f(k));
445  b_ = new_b;
446  }
447 
448  // Update k_ and s_.
449  {
450  s_t new_s;
451  typename k_t::iterator p_k;
452  for (p_k = k_.begin(); p_k != k_.end(); ++p_k)
453  {
454  p_k->second = lut[p_k->second];
455  new_s[p_k->second].insert(p_k->first);
456  }
457  s_ = new_s;
458  }
459 
460  mln_invariant(run_());
461  }
462 
463  template <typename K, typename P>
464  inline
465  void
467  {
468  mln_invariant(run_());
469  b_.clear();
470  s_.clear();
471  k_.clear();
472  n_ = 0;
473  mln_invariant(run_());
474  }
475 
476  template <typename K, typename P>
477  inline
478  std::size_t
480  {
481  mln_invariant(run_());
482  return 0; // FIXME
483 // std::size_t mem_q = 0;
484 // typename std::map<P, Q>::const_iterator i;
485 // for (i = q_.begin(); i != q_.end(); ++i)
486 // mem_q += i->second.memory_size();
487 // return p_.memory_size() + sizeof(q_) + sizeof(n_);
488  }
489 
490  template <typename K, typename P>
491  inline
492  const p_set<P>&
493  p_key<K,P>::operator()(const K& key) const
494  {
495  static const p_set<P> nil_ = p_set<P>();
496  if (exists_key(key)) // Also test invariants.
497  return s_.find(key)->second;
498  else
499  return nil_;
500  }
501 
502  template <typename K, typename P>
503  inline
504  const K&
505  p_key<K,P>::key(const P& p) const
506  {
507  mln_invariant(run_());
508  mln_precondition(k_.find(p) != k_.end());
509  return k_.find(p)->second;
510  }
511 
512  template <typename K, typename P>
513  inline
514  const util::set<K>&
515  p_key<K,P>::keys() const
516  {
517  mln_invariant(run_());
518  return b_;
519  }
520 
521  template <typename K, typename P>
522  inline
523  bool
524  p_key<K,P>::exists_key(const K& key) const
525  {
526  mln_invariant(run_());
527  return b_.has(key);
528  }
529 
530  template <typename K, typename P>
531  inline
532  const util::set<K>&
533  p_key<K,P>::set_1_() const
534  {
535  return b_;
536  }
537 
538  template <typename K, typename P>
539  inline
540  const p_set<P>&
541  p_key<K,P>::set_2_(const K& key) const
542  {
543  mln_precondition(b_.has(key));
544  return s_.find(key)->second;
545  }
546 
547  template <typename K, typename P>
548  inline
549  bool
550  p_key<K,P>::run_() const
551  {
552  if (! implies(n_ == 0, b_.is_empty()))
553  {
554  std::cerr << "#1" << std::endl;
555  return false;
556  }
557 
558  if (b_.nelements() != s_.size())
559  {
560  // Containers b_ and s_ are not consistent in size!
561  std::cerr << "#2" << std::endl;
562  return false;
563  }
564 
565  if (k_.size() != n_)
566  {
567  // The number of entries in k_ is not n_!
568  std::cerr << "#3: k_.size=" << k_.size() << " n_=" << n_ << std::endl;
569  return false;
570  }
571 
572  unsigned n = 0;
573  mln_eiter(util::set<K>) key(b_);
574  for_all(key)
575  {
576  typename s_t::const_iterator k_s = s_.find(key);
577 
578  if (k_s == s_.end())
579  {
580  // This key is not found in s_!
581  std::cerr << "#4" << std::endl;
582  return false;
583  }
584 
585  const p_set<P>& s = k_s->second;
586 
587  if (s.nsites() == 0)
588  {
589  // The site set associated with this key is empty!
590  std::cerr << "#5" << std::endl;
591  return false;
592  }
593 
594  n += s.nsites();
595 
596  mln_piter(p_set<P>) p(s);
597  for_all(p) // For every site p with the current key w.r.t. s_.
598  {
599  typename k_t::const_iterator p_k = k_.find(p);
600 
601  if (p_k == k_.end())
602  {
603  // There is no key entry for p in k_!
604  std::cerr << "#6" << std::endl;
605  return false;
606  }
607 
608  if (p_k->second != key)
609  {
610  // We have an inconsistency for p between s_ and k_!
611  std::cerr << "#7" << std::endl;
612  return false;
613  }
614  }
615  }
616 
617  if (n != n_)
618  {
619  // The number of elements in s_ is not n_!
620  std::cerr << "#8" << std::endl;
621  return false;
622  }
623 
624  return true;
625  }
626 
627 
628 
629 
630 
631  // Operator<<.
632 
633  template <typename K, typename P>
634  std::ostream& operator<<(std::ostream& ostr, const p_key<K,P>& pk)
635  {
636  ostr << '{';
637  mln_fwd_eiter(util::set<K>) k(pk.keys());
638  for_all(k)
639  {
640  ostr << ' ' << k << ':';
641  ostr << pk.set_2_(k);
642  }
643  ostr << '}';
644  return ostr;
645  }
646 
647 # endif // ! MLN_INCLUDE_ONLY
648 
649 } // end of namespace mln
650 
651 
652 #endif // ! MLN_CORE_SITE_SET_P_KEY_HH