Milena (Olena)
User documentation 2.0a Id
|
00001 // Copyright (C) 2008, 2009, 2011 EPITA Research and Development 00002 // Laboratory (LRDE) 00003 // 00004 // This file is part of Olena. 00005 // 00006 // Olena is free software: you can redistribute it and/or modify it under 00007 // the terms of the GNU General Public License as published by the Free 00008 // Software Foundation, version 2 of the License. 00009 // 00010 // Olena is distributed in the hope that it will be useful, 00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 // General Public License for more details. 00014 // 00015 // You should have received a copy of the GNU General Public License 00016 // along with Olena. If not, see <http://www.gnu.org/licenses/>. 00017 // 00018 // As a special exception, you may use this file as part of a free 00019 // software project without restriction. Specifically, if other files 00020 // instantiate templates or use macros or inline functions from this 00021 // file, or you compile this file and link it with other files to produce 00022 // an executable, this file does not by itself cause the resulting 00023 // executable to be covered by the GNU General Public License. This 00024 // exception does not however invalidate any other reasons why the 00025 // executable file might be covered by the GNU General Public License. 00026 00027 #ifndef MLN_CORE_IMAGE_DMORPH_EXTENSION_FUN_HH 00028 # define MLN_CORE_IMAGE_DMORPH_EXTENSION_FUN_HH 00029 00037 00038 # include <mln/core/internal/image_identity.hh> 00039 00040 00041 00042 namespace mln 00043 { 00044 00045 // Forward declaration. 00046 template <typename I, typename F> class extension_fun; 00047 00048 00049 namespace internal 00050 { 00051 00053 template <typename I, typename F> 00054 struct data< extension_fun<I, F> > 00055 { 00056 data(I& ima, const F& fun); 00057 00058 I ima_; 00059 const F fun_; 00060 }; 00061 00062 } // end of namespace mln::internal 00063 00064 00065 namespace trait 00066 { 00067 00068 template <typename I, typename F> 00069 struct image_< extension_fun<I, F> > : image_< I > // Same as I except... 00070 { 00071 // ...these changes. 00072 typedef trait::image::category::identity_morpher category; 00073 typedef mln_internal_trait_image_speed_from(I) speed; // Un-fastest. 00074 typedef trait::image::value_access::indirect value_access; 00075 00076 // extended domain 00077 typedef trait::image::ext_domain::infinite ext_domain; 00078 typedef trait::image::ext_value::multiple ext_value; 00079 typedef trait::image::ext_io::read_only ext_io; 00080 }; 00081 00082 template <typename I, typename F, typename V> 00083 struct ch_value< extension_fun<I, F>, V > 00084 { 00085 typedef mlc_converts_to(mln_result(F), V) keep_ext; 00086 typedef mln_ch_value(I, V) Iv; 00087 typedef extension_fun<Iv, F> Iv_ext; 00088 typedef mlc_if(keep_ext, Iv_ext, Iv) ret; 00089 }; 00090 00091 } // end of namespace mln::trait 00092 00093 00094 00098 // 00099 template <typename I, typename F> 00100 class extension_fun 00101 : public internal::image_identity< I, mln_domain(I), extension_fun<I, F> >, 00102 private mlc_converts_to(mln_result(F), mln_value(I))::check_t 00103 { 00104 public: 00105 00107 typedef extension_fun< tag::image_<I>, tag::function_<F> > skeleton; 00108 00110 typedef mln_value(I) value; 00111 00113 typedef mln_value(I) rvalue; 00114 00115 00117 extension_fun(); 00118 00120 extension_fun(I& ima, const F& fun); 00121 00124 void init_(I& ima, const F& fun); 00125 00126 00129 // Tech note: the 'template' allows for multiple input. 00130 template <typename P> 00131 bool has(const P& p) const; 00132 00133 00135 mln_value(I) operator()(const mln_psite(I)& p) const; 00136 00138 mln_morpher_lvalue(I) operator()(const mln_psite(I)& p); 00139 00140 00142 const F& extension() const; 00143 }; 00144 00145 00146 // init_ 00147 00148 template <typename I, typename F, typename J> 00149 void init_(tag::image_t, extension_fun<I,F>& target, const J& model); 00150 00151 template <typename F, typename I> 00152 void init_(tag::extension_t, F& target, const extension_fun<I,F>& model); 00153 00154 00155 00156 00157 # ifndef MLN_INCLUDE_ONLY 00158 00159 // internal::data< extension_fun<I,S> > 00160 00161 namespace internal 00162 { 00163 00164 template <typename I, typename F> 00165 inline 00166 data< extension_fun<I, F> >::data(I& ima, const F& fun) 00167 : ima_(ima), 00168 fun_(fun) 00169 { 00170 } 00171 00172 } // end of namespace mln::internal 00173 00174 00175 // extension_fun<I, F> 00176 00177 template <typename I, typename F> 00178 inline 00179 extension_fun<I, F>::extension_fun() 00180 { 00181 } 00182 00183 template <typename I, typename F> 00184 inline 00185 extension_fun<I, F>::extension_fun(I& ima, const F& fun) 00186 { 00187 init_(ima, fun); 00188 } 00189 00190 template <typename I, typename F> 00191 inline 00192 void 00193 extension_fun<I, F>::init_(I& ima, const F& fun) 00194 { 00195 this->data_ = new internal::data< extension_fun<I, F> >(ima, fun); 00196 } 00197 00198 template <typename I, typename F> 00199 template <typename P> 00200 inline 00201 bool 00202 extension_fun<I, F>::has(const P&) const 00203 { 00204 return true; 00205 } 00206 00207 template <typename I, typename F> 00208 inline 00209 mln_value(I) 00210 extension_fun<I, F>::operator()(const mln_psite(I)& p) const 00211 { 00212 mln_precondition(this->is_valid()); 00213 // if-else is preferred to the ternary op to allow for the 00214 // function result to convert towards the expected return type. 00215 if (this->data_->ima_.domain().has(p)) 00216 return this->data_->ima_(p); 00217 else 00218 return this->data_->fun_(p); 00219 } 00220 00221 template <typename I, typename F> 00222 inline 00223 mln_morpher_lvalue(I) 00224 extension_fun<I, F>::operator()(const mln_psite(I)& p) 00225 { 00226 static mln_value(I) cpy; 00227 mln_precondition(this->is_valid()); 00228 // See the above comment about if-else v. ternary. 00229 if (this->data_->ima_.domain().has(p)) 00230 return this->data_->ima_(p); 00231 else 00232 { 00233 // This hack makes this signature valid both in the image 00234 // domain and in its extension. It works even if 00235 // mln_morpher_lvalue(I) is a mutable reference. 00236 cpy = this->data_->fun_(p); 00237 return cpy; 00238 } 00239 } 00240 00241 template <typename I, typename F> 00242 inline 00243 const F& 00244 extension_fun<I, F>::extension() const 00245 { 00246 mln_precondition(this->is_valid()); 00247 return this->data_->fun_; 00248 } 00249 00250 00251 // init_ 00252 00253 template <typename I, typename F, typename J> 00254 void init_(tag::image_t, extension_fun<I,F>& target, const J& model) 00255 { 00256 I ima; 00257 init_(tag::image, ima, model); 00258 F fun; 00259 init_(tag::extension, fun, model); 00260 target.init_(ima, fun); 00261 } 00262 00263 template <typename F, typename I> 00264 void init_(tag::extension_t, F& target, const extension_fun<I,F>& model) 00265 { 00266 target = model.extension(); 00267 } 00268 00269 # endif // ! MLN_INCLUDE_ONLY 00270 00271 } // end of namespace mln 00272 00273 00274 #endif // ! MLN_CORE_IMAGE_DMORPH_EXTENSION_FUN_HH