Milena (Olena)  User documentation 2.0a Id
 All Classes Namespaces Functions Variables Typedefs Enumerator Groups Pages
extension_fun.hh
1 // Copyright (C) 2008, 2009, 2011 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_IMAGE_DMORPH_EXTENSION_FUN_HH
28 # define MLN_CORE_IMAGE_DMORPH_EXTENSION_FUN_HH
29 
37 
38 # include <mln/core/internal/image_identity.hh>
39 
40 
41 
42 namespace mln
43 {
44 
45  // Forward declaration.
46  template <typename I, typename F> class extension_fun;
47 
48 
49  namespace internal
50  {
51 
53  template <typename I, typename F>
54  struct data< extension_fun<I, F> >
55  {
56  data(I& ima, const F& fun);
57 
58  I ima_;
59  const F fun_;
60  };
61 
62  } // end of namespace mln::internal
63 
64 
65  namespace trait
66  {
67 
68  template <typename I, typename F>
69  struct image_< extension_fun<I, F> > : image_< I > // Same as I except...
70  {
71  // ...these changes.
72  typedef trait::image::category::identity_morpher category;
73  typedef mln_internal_trait_image_speed_from(I) speed; // Un-fastest.
74  typedef trait::image::value_access::indirect value_access;
75 
76  // extended domain
77  typedef trait::image::ext_domain::infinite ext_domain;
78  typedef trait::image::ext_value::multiple ext_value;
79  typedef trait::image::ext_io::read_only ext_io;
80  };
81 
82  template <typename I, typename F, typename V>
83  struct ch_value< extension_fun<I, F>, V >
84  {
85  typedef mlc_converts_to(mln_result(F), V) keep_ext;
86  typedef mln_ch_value(I, V) Iv;
87  typedef extension_fun<Iv, F> Iv_ext;
88  typedef mlc_if(keep_ext, Iv_ext, Iv) ret;
89  };
90 
91  } // end of namespace mln::trait
92 
93 
94 
98  //
99  template <typename I, typename F>
101  : public internal::image_identity< I, mln_domain(I), extension_fun<I, F> >,
102  private mlc_converts_to(mln_result(F), mln_value(I))::check_t
103  {
104  public:
105 
107  typedef extension_fun< tag::image_<I>, tag::function_<F> > skeleton;
108 
110  typedef mln_value(I) value;
111 
113  typedef mln_value(I) rvalue;
114 
115 
117  extension_fun();
118 
120  extension_fun(I& ima, const F& fun);
121 
124  void init_(I& ima, const F& fun);
125 
126 
129  // Tech note: the 'template' allows for multiple input.
130  template <typename P>
131  bool has(const P& p) const;
132 
133 
135  mln_value(I) operator()(const mln_psite(I)& p) const;
136 
138  mln_morpher_lvalue(I) operator()(const mln_psite(I)& p);
139 
140 
142  const F& extension() const;
143  };
144 
145 
146  // init_
147 
148  template <typename I, typename F, typename J>
149  void init_(tag::image_t, extension_fun<I,F>& target, const J& model);
150 
151  template <typename F, typename I>
152  void init_(tag::extension_t, F& target, const extension_fun<I,F>& model);
153 
154 
155 
156 
157 # ifndef MLN_INCLUDE_ONLY
158 
159  // internal::data< extension_fun<I,S> >
160 
161  namespace internal
162  {
163 
164  template <typename I, typename F>
165  inline
166  data< extension_fun<I, F> >::data(I& ima, const F& fun)
167  : ima_(ima),
168  fun_(fun)
169  {
170  }
171 
172  } // end of namespace mln::internal
173 
174 
175  // extension_fun<I, F>
176 
177  template <typename I, typename F>
178  inline
180  {
181  }
182 
183  template <typename I, typename F>
184  inline
186  {
187  init_(ima, fun);
188  }
189 
190  template <typename I, typename F>
191  inline
192  void
193  extension_fun<I, F>::init_(I& ima, const F& fun)
194  {
195  this->data_ = new internal::data< extension_fun<I, F> >(ima, fun);
196  }
197 
198  template <typename I, typename F>
199  template <typename P>
200  inline
201  bool
202  extension_fun<I, F>::has(const P&) const
203  {
204  return true;
205  }
206 
207  template <typename I, typename F>
208  inline
209  mln_value(I)
210  extension_fun<I, F>::operator()(const mln_psite(I)& p) const
211  {
212  mln_precondition(this->is_valid());
213  // if-else is preferred to the ternary op to allow for the
214  // function result to convert towards the expected return type.
215  if (this->data_->ima_.domain().has(p))
216  return this->data_->ima_(p);
217  else
218  return this->data_->fun_(p);
219  }
220 
221  template <typename I, typename F>
222  inline
223  mln_morpher_lvalue(I)
224  extension_fun<I, F>::operator()(const mln_psite(I)& p)
225  {
226  static mln_value(I) cpy;
227  mln_precondition(this->is_valid());
228  // See the above comment about if-else v. ternary.
229  if (this->data_->ima_.domain().has(p))
230  return this->data_->ima_(p);
231  else
232  {
233  // This hack makes this signature valid both in the image
234  // domain and in its extension. It works even if
235  // mln_morpher_lvalue(I) is a mutable reference.
236  cpy = this->data_->fun_(p);
237  return cpy;
238  }
239  }
240 
241  template <typename I, typename F>
242  inline
243  const F&
245  {
246  mln_precondition(this->is_valid());
247  return this->data_->fun_;
248  }
249 
250 
251  // init_
252 
253  template <typename I, typename F, typename J>
254  void init_(tag::image_t, extension_fun<I,F>& target, const J& model)
255  {
256  I ima;
257  init_(tag::image, ima, model);
258  F fun;
259  init_(tag::extension, fun, model);
260  target.init_(ima, fun);
261  }
262 
263  template <typename F, typename I>
264  void init_(tag::extension_t, F& target, const extension_fun<I,F>& model)
265  {
266  target = model.extension();
267  }
268 
269 # endif // ! MLN_INCLUDE_ONLY
270 
271 } // end of namespace mln
272 
273 
274 #endif // ! MLN_CORE_IMAGE_DMORPH_EXTENSION_FUN_HH