Milena (Olena)  User documentation 2.0a Id
 All Classes Namespaces Functions Variables Typedefs Enumerator Groups Pages
mln/core/image/complex_image.hh
1 // Copyright (C) 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_CORE_IMAGE_COMPLEX_IMAGE_HH
27 # define MLN_CORE_IMAGE_COMPLEX_IMAGE_HH
28 
32 
33 # include <vector>
34 
35 # include <mln/trait/images.hh>
36 
37 # include <mln/core/internal/image_primary.hh>
38 # include <mln/metal/vec.hh>
39 # include <mln/core/site_set/p_complex.hh>
40 # include <mln/core/site_set/complex_psite.hh>
41 # include <mln/value/set.hh>
42 
43 // FIXME: Move this elsewhere.
44 // Working around std::vector<bool>'s (forced) specialization.
45 
46 # define mlc_unbool(V) \
47  typename mln::internal::unbool<V>::ret
48 
49 namespace mln
50 {
51 
52  namespace internal
53  {
54 
56  struct bool_proxy
57  {
58  public:
59  bool_proxy() {}
60  bool_proxy(bool b) : b_(b) {}
61  bool& operator=(bool b) { b_ = b; return *this; }
62 
63  operator bool&() { return b_; }
64  operator const bool&() const { return b_; }
65 
66  bool operator==(const bool_proxy& rhs) { return b_ == rhs.b_; }
67  bool operator< (const bool_proxy& rhs) { return b_ < rhs.b_; }
68 
69  private:
71  bool b_;
72  };
73 
74  template <typename V> struct unbool { typedef V ret; };
75  template <> struct unbool<bool> { typedef bool_proxy ret; };
76 
77  } // end of namespace mln::internal
78 
79 }
80 
81 
82 
83 /* FIXME: In the current implementation, the type of values on faces
84  of different dimensions is necessarily the same (V). We should
85  allow different data types for vertices and edges. */
86 
87 
88 namespace mln
89 {
90 
91  // Forward declaration.
92  template <unsigned D, typename G, typename V> class complex_image;
93 
94  namespace internal
95  {
96 
98  template <unsigned D, typename G, typename V>
99  struct data< complex_image<D, G, V> >
100  {
101  data(const p_complex<D, G>& pc,
102  const metal::vec< D + 1, std::vector<V> >& values);
103 
104  metal::vec< D + 1, std::vector< mlc_unbool(V) > > values_;
105  const p_complex<D, G> pc_;
106  };
107 
108  } // end of namespace mln::internal
109 
110 
111  namespace trait
112  {
113 
114  template <unsigned D, typename G, typename V>
115  struct image_< complex_image<D, G, V> >
116  : default_image_< V, complex_image<D, G, V> >
117  {
118  typedef trait::image::category::primary category;
119 
120  // FIXME: Is that right?
121  typedef trait::image::speed::fast speed;
122  typedef trait::image::size::regular size;
123 
124  // Value.
125  typedef trait::image::value_access::direct value_access;
126  // FIXME: This image is value wise read_write, and provides
127  // an access to its values throught a multi-set,
128  // but we need to add the corresponding interface in the class.
129  typedef trait::image::vw_io::none vw_io;
130  typedef trait::image::vw_set::none vw_set;
131  typedef trait::image::value_storage::disrupted value_storage;
132  typedef trait::image::value_browsing::site_wise_only value_browsing;
133  typedef trait::image::value_alignment::irrelevant value_alignment;
134  typedef trait::image::value_io::read_write value_io;
135 
136  // Site / domain.
137  typedef trait::image::pw_io::read_write pw_io;
138  typedef trait::image::localization::space localization;
139  /* FIXME: Depends on G. We could use
140  `trait::image::space_from_point<mln_site(G)>::ret' in most
141  cases (i.e., when G's site is a Point), but would not be
142  generic. */
143  typedef typename trait::image::dimension::none dimension;
144 
145  // Extended domain.
146  typedef trait::image::ext_domain::none ext_domain;
147  typedef trait::image::ext_value::irrelevant ext_value;
148  typedef trait::image::ext_io::irrelevant ext_io;
149  };
150 
151  } // end of namespace mln::trait
152 
153 
163  template <unsigned D, typename G, typename V>
165  : public internal::image_primary< V, p_complex<D, G>,
166  complex_image<D, G, V> >
167  {
168  public:
170  static const unsigned dim = D;
172  typedef G geom;
174  typedef V value;
175 
177  typedef V& lvalue;
178 
180  typedef const V& rvalue;
181 
183  typedef complex_image< D, tag::psite_<G>, tag::value_<V> > skeleton;
184 
185  public:
188  complex_image();
189  complex_image(const p_complex<D, G>& pc);
190  complex_image(const p_complex<D, G>& pc,
191  const metal::vec< D + 1, std::vector<V> >& values);
193 
195  void init_(const p_complex<D, G>& pc,
196  const metal::vec< D + 1, std::vector<V> >& values);
197 
199  rvalue operator()(const complex_psite<D, G>& p) const;
202 
206  const p_complex<D, G>& domain() const;
207 
209  const metal::vec<D + 1, std::vector< mlc_unbool(V) > >& values() const;
211  };
212 
213  // Fwd decl.
214  template <unsigned D, typename G, typename V, typename W>
215  void init_(tag::image_t,
216  complex_image<D, G, V>& target,
217  const complex_image<D, G, W>& model);
218 
219 
220 # ifndef MLN_INCLUDE_ONLY
221 
222  /*-----------------.
223  | Initialization. |
224  `-----------------*/
225 
226  template <unsigned D, typename G, typename V, typename W>
227  inline
228  void init_(tag::image_t,
229  complex_image<D, G, V>& target,
230  const complex_image<D, G, W>& model)
231  {
232  metal::vec<D + 1, std::vector<V> > values;
233  for (unsigned i = 0; i <= D; ++i)
234  values[i].resize(model.domain().nfaces_of_dim(i));
235  target.init_(model.domain(), values);
236  }
237 
238  /*-------.
239  | Data. |
240  `-------*/
241 
242  namespace internal
243  {
244  template <unsigned D, typename G, typename V>
245  inline
246  data< complex_image<D, G, V> >::data(const p_complex<D, G>& pc,
247  const metal::vec< D + 1, std::vector<V> >& values)
248  : pc_(pc)
249  {
250  // We cannot use the initialization list for values_ (it
251  // would not work when V = bool).
252  for (unsigned i = 0; i <= D; ++i)
253  {
254  values_[i].reserve(values[i].size());
255  values_[i].insert(values_[i].begin(),
256  values[i].begin(), values[i].end());
257  }
258 
259  // Ensure the complex is consistent with the values.
260  /* FIXME: We need additional macros in mln/core/contract.hh for
261  big blocks of preconditions like this one. */
262 # ifndef NDEBUG
263  for (unsigned i = 0; i < D; ++i)
264  mln_precondition(pc.nfaces_of_dim(i) == values[i].size());
265 # endif // !NDEBUG
266  }
267 
268  } // end of namespace mln::internal
269 
270  /*---------------.
271  | Construction. |
272  `---------------*/
273 
274  template <unsigned D, typename G, typename V>
275  inline
277  {
278  }
279 
280  template <unsigned D, typename G, typename V>
281  inline
283  {
284  metal::vec<D + 1, std::vector<V> > values;
285  for (unsigned i = 0; i <= D; ++i)
286  values[i].resize(pc.nfaces_of_dim(i));
287  init_(pc, values);
288  }
289 
290  template <unsigned D, typename G, typename V>
291  inline
292  complex_image<D, G, V>::complex_image(const p_complex<D, G>& pc,
293  const metal::vec< D + 1,
294  std::vector<V> >& values)
295  {
296  init_(pc, values);
297  }
298 
299  template <unsigned D, typename G, typename V>
300  inline
301  void
302  complex_image<D, G, V>::init_(const p_complex<D, G>& pc,
303  const metal::vec< D + 1, std::vector<V> >& values)
304  {
305  mln_precondition(! this->is_valid());
306  this->data_ =
307  new internal::data< complex_image<D, G, V> >(pc, values);
308  }
309 
310  /*---------------.
311  | Manipulation. |
312  `---------------*/
313 
314  template <unsigned D, typename G, typename V>
315  inline
316  typename complex_image<D, G, V>::rvalue
318  {
319  mln_precondition(this->data_->pc_.has(p));
320  return this->data_->values_[p.n()][p.face_id()];
321  }
322 
323  template <unsigned D, typename G, typename V>
324  inline
327  {
328  mln_precondition(this->data_->pc_.has(p));
329  return this->data_->values_[p.n()][p.face_id()];
330  }
331 
332  template <unsigned D, typename G, typename V>
333  inline
334  const metal::vec< D + 1, std::vector< mlc_unbool(V) > >&
336  {
337  return this->data_->values_;
338  }
339 
340  template <unsigned D, typename G, typename V>
341  inline
342  const p_complex<D, G>&
344  {
345  mln_precondition(this->is_valid());
346  return this->data_->pc_;
347  }
348 
349 # endif // ! MLN_INCLUDE_ONLY
350 
351 } // end of namespace mln
352 
353 # undef mlc_unbool
354 
355 #endif // ! MLN_CORE_IMAGE_COMPLEX_IMAGE_HH