$extrastylesheet
Olena  User documentation 2.1
An Image Processing Platform
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
rank.hh
1 // Copyright (C) 2007, 2008, 2009 EPITA Research and Development Laboratory (LRDE)
2 //
3 // This file is part of Olena.
4 //
5 // Olena is free software: you can redistribute it and/or modify it under
6 // the terms of the GNU General Public License as published by the Free
7 // Software Foundation, version 2 of the License.
8 //
9 // Olena is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with Olena. If not, see <http://www.gnu.org/licenses/>.
16 //
17 // As a special exception, you may use this file as part of a free
18 // software project without restriction. Specifically, if other files
19 // instantiate templates or use macros or inline functions from this
20 // file, or you compile this file and link it with other files to produce
21 // an executable, this file does not by itself cause the resulting
22 // executable to be covered by the GNU General Public License. This
23 // exception does not however invalidate any other reasons why the
24 // executable file might be covered by the GNU General Public License.
25 
26 #ifndef MLN_ACCU_STAT_RANK_HH
27 # define MLN_ACCU_STAT_RANK_HH
28 
35 
36 # include <vector>
37 # include <mln/accu/internal/base.hh>
38 # include <mln/accu/histo.hh>
39 # include <mln/core/concept/meta_accumulator.hh>
40 # include <mln/trait/value_.hh>
41 # include <mln/util/pix.hh>
42 
43 
44 namespace mln
45 {
46 
47  namespace accu
48  {
49 
50  namespace stat
51  {
52 
53 
59  template <typename T>
60  struct rank : public mln::accu::internal::base< const T&, rank<T> >
61  {
62  typedef T argument;
64 
65  rank();
66  explicit rank(unsigned k);
67 
70  void init();
71  void take(const argument& t);
72  void take(const rank<T>& other);
73  void untake(const argument& t);
74  void untake(const rank<T>& other);
76 
77  unsigned card() const { return h_.sum(); }
78 
80  const T& to_result() const;
81 
84  bool is_valid() const;
85 
87  unsigned k() const;
88 
89  protected:
90 
91  unsigned k_; // 0 <= k_ < n
92 
93  mutable accu::histo<T> h_;
94  const S& s_; // derived from h_
95 
96  mutable unsigned sum_minus_, sum_plus_;
97 
98  mutable bool valid_;
99  mutable unsigned i_; // the median index
100  mutable argument t_; // the median value
101 
102  // Auxiliary methods
103  void update_() const;
104  void go_minus_() const;
105  void go_plus_() const;
106  };
107 
108 
109  template <typename I> struct rank< util::pix<I> >;
110 
111 
112  } // end of mln::accu::stat
113 
114 
115  namespace meta
116  {
117 
118  namespace stat
119  {
120 
122 
123  struct rank : public Meta_Accumulator< rank >
124  {
125  rank(unsigned k_) : k(k_) {}
126 
127  template <typename T>
128  struct with
129  {
131  };
132 
133  unsigned k;
134  };
135 
136  } // end of namespace mln::accu::meta::stat
137 
138  } // end of namespace mln::accu::meta
139 
140 
141  template <typename T>
143  {
144  stat::rank<T> a(m.k);
145  return a;
146  }
147 
148 
149 
150 
151  namespace stat
152  {
153 
154 # ifndef MLN_INCLUDE_ONLY
155 
156  template <typename T>
157  inline
158  rank<T>::rank()
159  : h_(),
160  s_(h_.vset())
161  {
162  init();
163  }
164 
165  template <typename T>
166  inline
167  rank<T>::rank(unsigned k)
168  : k_(k),
169  h_(),
170  s_(h_.vset())
171  {
172  init();
173  }
174 
175  template <typename T>
176  inline
177  unsigned
178  rank<T>::k() const
179  {
180  return k_;
181  }
182 
183  template <typename T>
184  inline
185  void rank<T>::take(const argument& t)
186  {
187  h_.take(t);
188 
189  if (t < t_)
190  ++sum_minus_;
191  else if (t > t_)
192  ++sum_plus_;
193 
194  if (valid_)
195  valid_ = false;
196  }
197 
198  template <typename T>
199  inline
200  void
201  rank<T>::take(const rank<T>& other)
202  {
203  // h_
204  h_.take(other.h_);
205 
206  // sum_minus_
207  for (unsigned i = 0; i < i_; ++i)
208  sum_minus_ += other.h_[i];
209 
210  // sum_plus_
211  for (unsigned i = i_ + 1; i < h_.nvalues(); ++i)
212  sum_plus_ += other.h_[i];
213 
214  if (valid_)
215  valid_ = false;
216  }
217 
218 
219  template <typename T>
220  inline
221  void
222  rank<T>::untake(const argument& t)
223  {
224  mln_precondition(h_(t) != 0);
225  h_.untake(t);
226 
227  if (t < t_)
228  --sum_minus_;
229  else if (t > t_)
230  --sum_plus_;
231 
232  if (valid_)
233  valid_ = false;
234  }
235 
236  template <typename T>
237  inline
238  void
239  rank<T>::untake(const rank<T>& other)
240  {
241  // h_
242  h_.untake(other.h_);
243 
244  // sum_minus_
245  for (unsigned i = 0; i < i_; ++i)
246  sum_minus_ -= other.h_[i];
247 
248  // sum_plus_
249  for (unsigned i = i_ + 1; i < h_.nvalues(); ++i)
250  sum_plus_ -= other.h_[i];
251 
252  if (valid_)
253  valid_ = false;
254  }
255 
256  template <typename T>
257  inline
258  void
259  rank<T>::update_() const
260  {
261  valid_ = true;
262 
263  if (h_.sum() == 0)
264  return;
265 
266  if (sum_minus_ > k_)
267  go_minus_();
268  else
269  if ((sum_minus_ + h_[i_]) < k_)
270  go_plus_();
271  else
272  if (h_[i_] == 0)
273  {
274  // go to the heaviest side
275  if (sum_plus_ > sum_minus_)
276  go_plus_();
277  else
278  go_minus_(); // default when both sides are balanced
279  }
280  }
281 
282  template <typename T>
283  inline
284  void
285  rank<T>::go_minus_() const
286  {
287  do
288  {
289  sum_plus_ += h_[i_];
290  do
291  --i_;
292  while (h_[i_] == 0);
293  sum_minus_ -= h_[i_];
294  }
295  while (sum_minus_ > k_);
296  t_ = s_[i_];
297  }
298 
299  template <typename T>
300  inline
301  void
302  rank<T>::go_plus_() const
303  {
304  do
305  {
306  sum_minus_ += h_[i_];
307  do
308  ++i_;
309  while (h_[i_] == 0);
310  sum_plus_ -= h_[i_];
311  }
312  while ((sum_minus_ + h_[i_]) < k_);
313  t_ = s_[i_];
314  }
315 
316  template <typename T>
317  inline
318  void
319  rank<T>::init()
320  {
321  h_.init();
322  sum_minus_ = 0;
323  sum_plus_ = 0;
324  i_ = (s_.index_of(mln_max(argument))
325  - s_.index_of(mln_min(argument))) / 2;
326  t_ = s_[i_];
327  valid_ = true;
328  }
329 
330  template <typename T>
331  inline
332  const T&
333  rank<T>::to_result() const
334  {
335  if (! valid_)
336  update_();
337  return t_;
338  }
339 
340  template <typename T>
341  inline
342  bool
343  rank<T>::is_valid() const
344  {
345  return valid_;
346  }
347 
348 # endif // ! MLN_INCLUDE_ONLY
349 
350  } // end of namespace mln::accu::stat
351 
352  } // end of namespace mln::accu
353 
354 } // end of namespace mln
355 
356 #include <mln/accu/stat/rank_bool.hh>
357 
358 #endif // ! MLN_ACCU_STAT_RANK_HH