Milena (Olena)  User documentation 2.0a Id
 All Classes Namespaces Functions Variables Typedefs Enumerator Groups Pages
sort_offsets.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_DATA_SORT_OFFSETS_HH
27 # define MLN_DATA_SORT_OFFSETS_HH
28 
33 
34 # include <algorithm>
35 
36 # include <mln/core/concept/image.hh>
37 # include <mln/histo/compute.hh>
38 # include <mln/util/array.hh>
39 # include <mln/util/ord.hh>
40 # include <mln/geom/nsites.hh>
41 
42 
43 namespace mln
44 {
45 
46  namespace data
47  {
48 
52  template <typename I>
53  util::array<unsigned>
54  sort_offsets_increasing(const Image<I>& input);
55 
56 
57  // /// Sort pixel offsets of the image \p input wrt decreasing pixel
58  // /// values.
59  // ///
60  // template <typename I>
61  // util::array<unsigned>
62  // sort_offsets_decreasing(const Image<I>& input);
63 
64 
65 
66 # ifndef MLN_INCLUDE_ONLY
67 
68  namespace impl
69  {
70 
71  namespace generic
72  {
73 
74  // increasing
75 
76  template <typename I>
77  struct value_offset_less_
78  {
79  const I& ima_;
80  inline value_offset_less_(const I& ima) : ima_(ima) {}
81  inline bool operator()(unsigned lhs, unsigned rhs) const
82  {
83  return util::ord_strict(ima_.element(lhs), ima_.element(rhs))
84  || (ima_.element(lhs) == ima_.element(rhs)
85  &&
86  lhs < rhs);
87  }
88  };
89 
90  template <typename I>
91  inline
92  util::array<unsigned>
93  sort_offsets_increasing(const Image<I>& input_)
94  {
95  trace::entering("data::impl::generic::sort_offsets_increasing");
96 
97  const I& input = exact(input_);
98 
99  util::array<unsigned> v;
100  v.reserve(input.nelements());
101  mln_fwd_pixter(const I) pxl(input);
102  for_all(pxl)
103  v.append(pxl.offset());
104  std::sort(v.hook_std_vector_().begin(), v.hook_std_vector_().end(),
105  value_offset_less_<I>(input));
106 
107  trace::exiting("data::impl::generic::sort_offsets_increasing");
108  return v;
109  }
110 
111 
112  // decreasing
113 
114  template <typename I>
115  struct value_offset_greater_
116  {
117  const I& ima_;
118  inline value_offset_greater_(const I& ima) : ima_(ima) {}
119  inline bool operator()(unsigned lhs, unsigned rhs) const
120  {
121  return util::ord_strict(ima_.element(rhs), ima_.element(lhs))
122  || (ima_.element(lhs) == ima_.element(rhs)
123  &&
124  lhs > rhs);
125  }
126  };
127 
128  template <typename I>
129  inline
130  util::array<unsigned>
131  sort_offsets_decreasing(const Image<I>& input_)
132  {
133  trace::entering("data::impl::generic::sort_offsets_decreasing");
134 
135  const I& input = exact(input_);
136 
137  util::array<unsigned> v;
138  v.reserve(input.nelements());
139  mln_fwd_pixter(const I) pxl(input);
140  for_all(pxl)
141  v.append(pxl.offset());
142  std::sort(v.hook_std_vector_().begin(), v.hook_std_vector_().end(),
143  value_offset_greater_<I>(input));
144 
145  trace::exiting("data::impl::generic::sort_offsets_decreasing");
146  return v;
147  }
148 
149 
150  } // end of namespace mln::data::impl::generic
151 
152 
153 
154  // increasing
155 
156  template <typename I>
157  inline
158  util::array<unsigned>
159  sort_offsets_increasing_radix(const Image<I>& input_)
160  {
161  trace::entering("data::impl::sort_offsets_increasing_radix");
162 
163  const I& input = exact(input_);
164 
165  typedef mln_vset(I) S;
166  const S& vset = input.values_eligible();
167  const unsigned n = vset.nvalues();
168 
169  // h
170  histo::array<mln_value(I)> h = histo::compute(input);
171 
172  // preparing output data
173  std::vector<unsigned> loc(vset.nvalues());
174  loc[0] = 0;
175  for (unsigned i = 1; i != n; ++i)
176  loc[i] = loc[i-1] + h[i-1];
177 
178  // computing output data
179  util::array<unsigned> vec(geom::nsites(input));
180  mln_fwd_pixter(const I) pxl(input);
181  for_all(pxl)
182  vec[loc[vset.index_of(pxl.val())]++] = pxl.offset();
183 
184  trace::exiting("data::impl::sort_offsets_increasing_radix");
185  return vec;
186  }
187 
188 
189  // decreasing
190 
191  template <typename I>
192  inline
193  util::array<unsigned>
194  sort_offsets_decreasing_radix(const Image<I>& input_)
195  {
196  trace::entering("data::impl::sort_offsets_decreasing_radix");
197 
198  const I& input = exact(input_);
199 
200  typedef mln_vset(I) S;
201  const S& vset = input.values_eligible();
202  const unsigned n = vset.nvalues();
203 
204  // h
205  histo::array<mln_value(I)> h = histo::compute(input);
206 
207  // preparing output data
208  std::vector<unsigned> loc(vset.nvalues());
209  loc[n-1] = 0;
210  for (int i = n - 2; i >= 0; --i)
211  loc[i] = loc[i+1] + h[i+1];
212 
213  // computing output data
214  util::array<unsigned> vec(geom::nsites(input));
215  mln_fwd_pixter(const I) pxl(input);
216  for_all(pxl)
217  vec[loc[vset.index_of(pxl.val())]++] = pxl.offset();
218 
219  trace::exiting("data::impl::sort_offsets_decreasing_radix");
220  return vec;
221  }
222 
223 
224  } // end of namespace mln::data::impl
225 
226 
227 
228  namespace internal
229  {
230 
231  // increasing
232 
233  template <typename I>
234  inline
235  util::array<unsigned>
236  sort_offsets_increasing_dispatch(trait::image::quant::any,
237  const Image<I>& input)
238  {
239  return impl::generic::sort_offsets_increasing(input);
240  }
241 
242  template <typename I>
243  inline
244  util::array<unsigned>
245  sort_offsets_increasing_dispatch(trait::image::quant::low,
246  const Image<I>& input)
247  {
248  return impl::sort_offsets_increasing_radix(input);
249  }
250 
251  template <typename I>
252  inline
253  util::array<unsigned>
254  sort_offsets_increasing_dispatch(const Image<I>& input)
255  {
256  return sort_offsets_increasing_dispatch(mln_trait_image_quant(I)(),
257  input);
258  }
259 
260  // decreasing
261 
262  template <typename I>
263  inline
264  util::array<unsigned>
265  sort_offsets_decreasing_dispatch(trait::image::quant::any,
266  const Image<I>& input)
267  {
268  return impl::generic::sort_offsets_decreasing(input);
269  }
270 
271  template <typename I>
272  inline
273  util::array<unsigned>
274  sort_offsets_decreasing_dispatch(trait::image::quant::low,
275  const Image<I>& input)
276  {
277  return impl::sort_offsets_decreasing_radix(input);
278  }
279 
280  template <typename I>
281  inline
282  util::array<unsigned>
283  sort_offsets_decreasing_dispatch(const Image<I>& input)
284  {
285  return sort_offsets_decreasing_dispatch(mln_trait_image_quant(I)(),
286  input);
287  }
288 
289  } // end of namespace mln::data::internal
290 
291 
292 
293  // Facades.
294 
295  template <typename I>
296  inline
297  util::array<unsigned>
298  sort_offsets_increasing(const Image<I>& input)
299  {
300  trace::entering("data::sort_offsets_increasing");
301  mlc_is(mln_trait_image_speed(I),
302  trait::image::speed::fastest)::check();
303 
304  mln_precondition(exact(input).is_valid());
305  util::array<unsigned> output = internal::sort_offsets_increasing_dispatch(input);
306 
307  trace::exiting("data::sort_offsets_increasing");
308  return output;
309  }
310 
311  template <typename I>
312  inline
314  sort_offsets_decreasing(const Image<I>& input)
315  {
316  trace::entering("data::sort_offsets_decreasing");
317  mlc_is(mln_trait_image_speed(I),
318  trait::image::speed::fastest)::check();
319 
320  mln_precondition(exact(input).is_valid());
321  util::array<unsigned> output = internal::sort_offsets_decreasing_dispatch(input);
322 
323  trace::exiting("data::sort_offsets_decreasing");
324  return output;
325  }
326 
327 # endif // ! MLN_INCLUDE_ONLY
328 
329  } // end of namespace mln::data
330 
331 } // end of namespace mln
332 
333 
334 #endif // ! MLN_DATA_SORT_OFFSETS_HH