Milena (Olena)  User documentation 2.0a Id
 All Classes Namespaces Functions Variables Typedefs Enumerator Groups Pages
stack.hh
1 // Copyright (C) 2007, 2008, 2009 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_VALUE_STACK_HH
28 # define MLN_VALUE_STACK_HH
29 
33 
34 # include <mln/core/internal/image_value_morpher.hh>
35 
36 # include <mln/algebra/vec.hh>
37 # include <mln/value/set.hh>
38 # include <mln/value/proxy.hh>
39 
40 
41 namespace mln
42 {
43 
44  // Forward declaration.
45  namespace value { template <unsigned n, typename I> struct stack_image; }
46 
47  namespace internal
48  {
49 
50 
53  template <unsigned n, typename I>
54  struct data< value::stack_image<n, I> >
55  {
56  public:
57  data(const algebra::vec<n,I>& imas);
58  algebra::vec<n,I> imas_;
59  I& ima_;
60  };
61 
62  }
63 
64  namespace value
65  {
66 
67  namespace internal
68  {
69  template <unsigned n, typename I>
70  struct helper_stack_image_lvalue_
71  {
72  typedef value::proxy< stack_image<n,I> > ret;
73  static ret make(stack_image<n,I>& ima, const mln_psite(I)& p)
74  {
75  ret tmp(ima, p);
76  return tmp;
77  }
78  };
79 
80  template <unsigned n, typename I>
81  struct helper_stack_image_lvalue_< n, const I >
82  {
83  typedef algebra::vec<n, mln_value(I)> ret;
84  static ret make(stack_image<n, const I>& ima, const mln_psite(I)& p)
85  {
86  return ima.read_(p);
87  }
88  };
89 
90 
91  } // end of namespace mln::value::internal
92 
93  } // end of namespace mln::value
94 
95 
96  namespace trait
97  {
98 
99  template <unsigned n, typename I>
100  struct image_< mln::value::stack_image<n, I> >
101  : default_image_morpher< I,
102  algebra::vec<n, mln_value(I)>,
103  mln::value::stack_image<n, I> >
104  {
105  // FIXME: We shall carefully define the missing required traits
106  // here.
107  typedef trait::image::category::value_morpher category;
108 
109  typedef trait::image::nature::vectorial nature;
110  /* FIXME: Setting the speed trait of a stack_image to `fast' is
111  a bad approximation.
112 
113  The value cannot reasonnably be `fastest', as several images
114  in different memory locations are involved in a stack image.
115  So we cannot just rely on the speed trait of I.
116  Nevertheless, we cannot guarantee that a stack_image will be
117  a least `fast': think of a stack_image over a ``slow''
118  image_type (e.g., an image whose values are computed). That
119  image would retain the `slow' value of the speed trait.
120 
121  In conclusion, this value of the speed trait should be
122  computed too. */
123  typedef trait::image::speed::fast speed;
124  };
125 
126  } // end of namespace mln::trait
127 
128 
129  namespace value
130  {
144  template <unsigned n, typename I>
145  struct stack_image
146  : public mln::internal::image_value_morpher< I,
147  algebra::vec<n, mln_value(I)>,
148  stack_image<n,I> >
149  {
151  typedef mln_psite(I) psite;
152 
154  typedef mln_domain(I) domain_t;
155 
157  typedef algebra::vec<n, mln_value(I)> value;
158 
163  typedef value rvalue;
164 
166  typedef typename internal::helper_stack_image_lvalue_<n,I>::ret lvalue;
167 
168 
170  typedef stack_image< n, tag::image_<I> > skeleton;
171 
172 
175  stack_image(const algebra::vec<n,I>& imas);
176  stack_image();
178 
180  void init_(const algebra::vec<n,I>& imas);
181 
183  bool is_valid() const;
184 
186  rvalue operator()(const psite& p) const;
187  rvalue read_(const psite& p) const;
188 
190  lvalue operator()(const psite&);
191  void write_(const psite& p, const value& v);
192  };
193 
195  template <typename I>
196  stack_image<2, const I>
197  stack(const Image<I>& ima1, const Image<I>& ima2);
198 
199 
200  template <typename I>
201  stack_image<2, I>
202  stack(Image<I>& ima1, Image<I>& ima2);
204 
205  } // end of namespace mln::value
206 
207 # ifndef MLN_INCLUDE_ONLY
208 
209  namespace internal
210  {
211  // internal::data< cast_image_<T,I> >
212 
213  template <unsigned n, typename I>
214  inline
215  data< value::stack_image<n,I> >::data(const algebra::vec<n,I>& imas)
216  : imas_(imas),
217  ima_(imas_[0])
218  {
219  }
220 
221  } // end of namespace mln::internal
222 
223 
224  namespace value
225  {
226  // stack_image<n, I>
227 
228  template <unsigned n, typename I>
229  inline
231  {
232  }
233 
234  template <unsigned n, typename I>
235  inline
236  stack_image<n,I>::stack_image(const algebra::vec<n,I>& imas)
237  {
238  init_(imas);
239  }
240 
241  template <unsigned n, typename I>
242  inline
243  void
244  stack_image<n,I>::init_(const algebra::vec<n,I>& imas)
245  {
246  this->data_ = new mln::internal::data< stack_image<n, I> >(imas);
247  for (unsigned i = 0; i < n; ++i)
248  {
249  mln_precondition(imas[i].is_valid());
250  }
251  }
252 
253  template <unsigned n, typename I>
254  inline
256  {
257  for (unsigned i = 0; i < n; ++i)
258  mln_invariant(this->data_->imas_[i].is_valid());
259  return true;
260  }
261 
262  template <unsigned n, typename I>
263  inline
264  typename stack_image<n,I>::rvalue
265  stack_image<n,I>::read_(const psite& p) const
266  {
267  mln_precondition(this->has(p));
268  algebra::vec<n, mln_value(I)> tmp;
269  for (unsigned i = 0; i < n; ++i)
270  tmp[i] = this->data_->imas_[i].operator()(p);
271  return tmp;
272  }
273 
274  template <unsigned n, typename I>
275  inline
276  typename stack_image<n,I>::rvalue
277  stack_image<n,I>::operator()(const psite& p) const
278  {
279  return read_(p);
280  }
281 
282  template <unsigned n, typename I>
283  inline
284  void
285  stack_image<n,I>::write_(const psite& p, const value& v)
286  {
287  mln_precondition(this->has(p));
288  // FIXME!!!
289  for (unsigned i = 0; i < n; ++i)
290  this->data_->imas_[i].operator()(p) = v[i];
291  }
292 
293  template <unsigned n, typename I>
294  inline
295  typename stack_image<n,I>::lvalue
297  {
298  return internal::helper_stack_image_lvalue_<n,I>::make(*this, p);
299  }
300 
301  // stack(..)
302 
303  template <typename I>
304  inline
306  stack(const Image<I>& ima1, const Image<I>& ima2)
307  {
308  mln_precondition(exact(ima1).domain() == exact(ima2).domain());
309  algebra::vec<2, const I> imas;
310  imas[0] = exact(ima1);
311  imas[1] = exact(ima2);
312  return imas;
313  }
314 
315  template <typename I>
316  inline
318  stack(Image<I>& ima1, Image<I>& ima2)
319  {
320  mln_precondition(exact(ima1).domain() == exact(ima2).domain());
321  algebra::vec<2, I> imas;
322  imas[0] = exact(ima1);
323  imas[1] = exact(ima2);
324  return imas;
325  }
326 
327  } // end of namespace mln::value
328 
329 # endif // ! MLN_INCLUDE_ONLY
330 
331 } // end of namespace mln
332 
333 
334 #endif // ! MLN_VALUE_STACK_HH