$extrastylesheet
Olena  User documentation 2.1
An Image Processing Platform
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
p_priority.hh
1 // Copyright (C) 2007, 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_PRIORITY_HH
28 # define MLN_CORE_SITE_SET_P_PRIORITY_HH
29 
33 
34 # include <map>
35 # include <mln/core/site_set/p_double.hh>
36 # include <mln/core/internal/site_set_base.hh>
37 # include <mln/util/set.hh>
38 # include <mln/util/ord.hh>
39 
40 
41 namespace mln
42 {
43 
44  // Forward declaration.
45  template <typename P, typename Q> class p_priority;
46 
47 
48 
49  namespace trait
50  {
51 
52  template <typename P, typename Q>
53  struct site_set_< p_priority<P,Q> >
54  {
55  typedef trait::site_set::nsites::known nsites;
56  typedef trait::site_set::bbox::unknown bbox;
57  typedef trait::site_set::contents::growing contents;
58  typedef trait::site_set::arity::multiple arity;
59  };
60 
61  } // end of namespace trait
62 
63 
64 
65 
69 
76  template <typename P, typename Q>
77  class p_priority : public internal::site_set_base_< mln_site(Q),
78  p_priority<P,Q> >,
79  private mlc_is_a(Q, Site_Set)::check_t
80  {
81  typedef p_priority<P,Q> self_;
82  public:
83 
85  typedef mln_element(Q) element;
86 
87 
89  typedef p_double_psite<self_, Q> psite;
90 
92  typedef p_double_piter< self_,
93  mln_bkd_eiter(util::set<P>),
94  mln_fwd_piter(Q) > fwd_piter;
95 
97  typedef p_double_piter< self_,
98  mln_fwd_eiter(util::set<P>),
99  mln_bkd_piter(Q) > bkd_piter;
100 
102  typedef fwd_piter piter;
103 
104 
106  p_priority();
107 
109  bool has(const psite&) const;
110 
112  bool is_valid() const;
113 
115  unsigned nsites() const;
116 
117 
119  void push(const P& priority, const element& e);
120 
122  typedef std::pair<P, element> i_element;
123 
125  void insert(const i_element& p_e);
126 
128  void insert(const p_priority<P,Q>& other);
129 
130 
134  void pop();
135 
139  const mln_element(Q)& front() const;
140 
144  mln_element(Q) pop_front();
145 
146 
148  void clear();
149 
150 
154  const Q& operator()(const P& priority) const;
155 
157  const util::set<P>& priorities() const;
158 
160  bool exists_priority(const P& priority) const;
161 
164  const P highest_priority() const;
165 
168  const P lowest_priority() const;
169 
171  // Required by p_double-related classes.
172  const util::set<P>& set_1_() const;
173  const Q& set_2_(const P& priority) const;
175 
176 
178  std::size_t memory_size() const;
179 
180 
181  protected:
182 
183  typedef std::map<P, Q, util::ord<P> > q_type_;
184 
185  util::set<P> p_;
186  q_type_ q_;
187  unsigned n_;
188 
189  // Run invariance tests and return the result.
190  bool run_() const;
191  };
192 
193 
195  template <typename P, typename Q>
196  std::ostream& operator<<(std::ostream& ostr, const p_priority<P,Q>& pq);
197 
198 
199 
200 # ifndef MLN_INCLUDE_ONLY
201 
202  template <typename P, typename Q>
203  inline
205  {
206  n_ = 0;
207  mln_invariant(run_());
208  }
209 
210  template <typename P, typename Q>
211  inline
212  bool
213  p_priority<P,Q>::has(const psite&) const
214  {
215  mln_invariant(run_());
216  // FIXME
217  return true;
218  }
219 
220  template <typename P, typename Q>
221  inline
222  bool
224  {
225  mln_invariant(run_());
226  return true;
227  }
228 
229  template <typename P, typename Q>
230  inline
231  unsigned
233  {
234  mln_invariant(run_());
235  return n_;
236  }
237 
238  template <typename P, typename Q>
239  inline
240  void
241  p_priority<P,Q>::push(const P& priority, const element& e)
242  {
243  mln_invariant(run_());
244  p_.insert(priority); // No-op if this priority already exists.
245  q_[priority].push(e);
246  ++n_;
247  mln_invariant(run_());
248  }
249 
250  template <typename P, typename Q>
251  inline
252  void
253  p_priority<P,Q>::insert(const i_element& p_e)
254  {
255  this->push(p_e.first, p_e.second); // Also test invariants.
256  }
257 
258  template <typename P, typename Q>
259  inline
260  void
261  p_priority<P,Q>::insert(const p_priority<P,Q>& other)
262  {
263  mln_invariant(run_());
264  typename q_type_::const_iterator i;
265  for (i = other.q_.begin(); i != other.q_.end(); ++i)
266  {
267  P priority = i->first;
268  p_.insert(priority);
269  const Q& q_p = i->second;
270  q_[priority] += q_p;
271  }
272  n_ += other.n_;
273  mln_invariant(run_());
274  }
275 
276  template <typename P, typename Q>
277  inline
278  void
280  {
281  mln_precondition(! this->is_empty()); // Also test invariants.
282  P prior = highest_priority();
283  q_[prior].pop();
284  if (q_[prior].is_empty())
285  {
286  q_.erase(prior);
287  p_.remove(prior);
288  }
289  --n_;
290  mln_invariant(run_());
291  }
292 
293  template <typename P, typename Q>
294  inline
295  const mln_element(Q)&
296  p_priority<P,Q>::front() const
297  {
298  mln_precondition(! this->is_empty()); // Also test invariants.
299  q_type_& q__ = const_cast< q_type_& >(q_);
300  return q__[highest_priority()].front();
301  }
302 
303  template <typename P, typename Q>
304  inline
305  mln_element(Q)
306  p_priority<P,Q>::pop_front()
307  {
308  mln_precondition(! this->is_empty()); // Also test invariants.
309  // FIXME: can be speeded up, return const& when possible...
310  mln_element(Q) e = this->front();
311  this->pop();
312  return e;
313  }
314 
315  template <typename P, typename Q>
316  inline
317  void
318  p_priority<P,Q>::clear()
319  {
320  mln_invariant(run_());
321  p_.clear();
322  q_.clear();
323  n_ = 0;
324  mln_invariant(run_());
325  }
326 
327  template <typename P, typename Q>
328  inline
329  std::size_t
331  {
332  mln_invariant(run_());
333  std::size_t mem_q = 0;
334  typename q_type_::const_iterator i;
335  for (i = q_.begin(); i != q_.end(); ++i)
336  mem_q += i->second.memory_size();
337  return p_.memory_size() + sizeof(q_) + sizeof(n_);
338  }
339 
340  template <typename P, typename Q>
341  inline
342  const Q&
343  p_priority<P,Q>::operator()(const P& priority) const
344  {
345  static const Q nil_ = Q();
346  if (exists_priority(priority)) // Also test invariants.
347  {
348  q_type_& mq = const_cast<q_type_&>(q_);
349  mln_assertion(mq[priority].nsites() > 0);
350  return mq[priority];
351  }
352  else
353  return nil_;
354  }
355 
356  template <typename P, typename Q>
357  inline
358  const util::set<P>&
360  {
361  mln_invariant(run_());
362  return p_;
363  }
364 
365  template <typename P, typename Q>
366  inline
367  bool
368  p_priority<P,Q>::exists_priority(const P& priority) const
369  {
370  mln_invariant(run_());
371  return p_.has(priority);
372  }
373 
374  template <typename P, typename Q>
375  inline
376  const P
378  {
379  mln_precondition(! this->is_empty()); // Also test invariants.
380  return p_.last_element();
381  }
382 
383  template <typename P, typename Q>
384  inline
385  const P
387  {
388  mln_precondition(! this->is_empty()); // Also test invariants.
389  return p_.first_element();
390  }
391 
392  template <typename P, typename Q>
393  inline
394  const util::set<P>&
395  p_priority<P,Q>::set_1_() const
396  {
397  return p_;
398  }
399 
400  template <typename P, typename Q>
401  inline
402  const Q&
403  p_priority<P,Q>::set_2_(const P& priority) const
404  {
405  mln_precondition(p_.has(priority));
406  q_type_& mq = const_cast<q_type_&>(q_);
407  mln_precondition(mq[priority].nsites() > 0);
408  return mq[priority];
409  }
410 
411  template <typename P, typename Q>
412  inline
413  bool
414  p_priority<P,Q>::run_() const
415  {
416  if (! implies(n_ == 0, p_.is_empty()))
417  return false;
418 
419  if (! (p_.nelements() == q_.size()))
420  // Containers p_ and q_ are not consistent in size!
421  return false;
422 
423  mln_eiter(util::set<P>) p(p_);
424  for_all(p)
425  if (q_.find(p) == q_.end())
426  // We have an empty queue (with priority p)!
427  return false;
428 
429  typename std::map<P,Q>::const_iterator i;
430  for (i = q_.begin(); i != q_.end(); ++i)
431  if (! p_.has(i->first))
432  // A priority is unknown (for a known queue)!
433  return false;
434 
435  return true;
436  }
437 
438 
439  // Operator<<.
440 
441  template <typename P, typename Q>
442  std::ostream& operator<<(std::ostream& ostr, const p_priority<P,Q>& pq)
443  {
444  ostr << '{';
445  mln_bkd_eiter(util::set<P>) p(pq.priorities());
446  for_all(p)
447  {
448  ostr << ' ' << p << ':';
449  ostr << pq.set_2_(p);
450  }
451  ostr << '}';
452  return ostr;
453  }
454 
455 # endif // ! MLN_INCLUDE_ONLY
456 
457 } // end of namespace mln
458 
459 
460 #endif // ! MLN_CORE_SITE_SET_P_PRIORITY_HH