Milena (Olena)  User documentation 2.0a Id
extension_fun.hh
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
 All Classes Namespaces Functions Variables Typedefs Enumerator