• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Classes
  • Files
  • File List

solve_binary.hh

00001 // Copyright (C) 2006, 2008, 2009 EPITA Research and Development Laboratory (LRDE)
00002 //
00003 // This file is part of Olena.
00004 //
00005 // Olena is free software: you can redistribute it and/or modify it under
00006 // the terms of the GNU General Public License as published by the Free
00007 // Software Foundation, version 2 of the License.
00008 //
00009 // Olena is distributed in the hope that it will be useful,
00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012 // General Public License for more details.
00013 //
00014 // You should have received a copy of the GNU General Public License
00015 // along with Olena.  If not, see <http://www.gnu.org/licenses/>.
00016 //
00017 // As a special exception, you may use this file as part of a free
00018 // software project without restriction.  Specifically, if other files
00019 // instantiate templates or use macros or inline functions from this
00020 // file, or you compile this file and link it with other files to produce
00021 // an executable, this file does not by itself cause the resulting
00022 // executable to be covered by the GNU General Public License.  This
00023 // exception does not however invalidate any other reasons why the
00024 // executable file might be covered by the GNU General Public License.
00025 
00026 #ifndef MLN_TRAIT_SOLVE_BINARY_HH
00027 # define MLN_TRAIT_SOLVE_BINARY_HH
00028 
00032 
00033 # include <mln/core/category.hh>
00034 # include <mln/core/routine/exact.hh>
00035 # include <mln/metal/equal.hh>
00036 # include <mln/metal/if.hh>
00037 # include <mln/metal/ret.hh>
00038 
00039 
00040 // FIXME: Just for the record (use it...)
00041 
00042 #  ifndef MLN_DEBUG_TRAITS 
00043 #  endif // ! MLN_DEBUG_TRAITS
00044 
00045 
00046 
00047 namespace mln
00048 {
00049 
00050   namespace trait
00051   {
00052 
00053     namespace internal
00054     {
00055 
00056 
00057       template < template <class, class> class Name,
00058                  typename Category_L, typename L,
00059                  typename Category_R, typename R >
00060       struct trait_set_binary_;
00061 
00062       template < template <class, class> class Name,
00063                  template <class> class Category_L, typename _l, typename L,
00064                  template <class> class Category_R, typename _r, typename R >
00065       struct trait_set_binary_< Name,
00066                                Category_L<_l>, L,
00067                                Category_R<_r>, R >
00068       {
00069         typedef typename mln::trait::set_binary_<Name,
00070                                                  Category_L, L,
00071                                                  Category_R, R>::ret ret;
00072       };
00073 
00074 
00075       // triplet_ret_
00076 
00077       template < unsigned i_L_, unsigned i_R_, typename ret_ >
00078       struct triplet_
00079       {
00080         typedef ret_ ret;
00081       };
00082 
00083 
00084       // merge_triplets_
00085 
00086       template < typename L_trp, typename R_trp >
00087       struct merge_triplets_;
00088 
00089       template < unsigned L_i_L, unsigned L_i_R, typename L_ret,
00090                  unsigned R_i_L, unsigned R_i_R, typename R_ret >
00091       struct merge_triplets_< triplet_<L_i_L, L_i_R, L_ret>, 
00092                               triplet_<R_i_L, R_i_R, R_ret> >
00093       {
00094         typedef metal::bool_<(L_i_L <= R_i_L && L_i_R <= R_i_R)> take_L;
00095         typedef metal::bool_<(R_i_L <= L_i_L && R_i_R <= L_i_R)> take_R;
00096         typedef metal::or_<take_L, take_R> ok;
00097         typedef typename metal::if_< metal::and_<ok, take_L>,
00098                                      triplet_<L_i_L, L_i_R, L_ret>,
00099                                      typename metal::if_< metal::and_<ok, take_R>,
00100                                                           triplet_<R_i_L, R_i_R, R_ret>,
00101                                                           triplet_<0,0, not_found> >::ret >::ret ret;
00102       };
00103 
00104       template < unsigned i_L, unsigned i_R, typename LR_ret >
00105       struct merge_triplets_< triplet_<i_L, i_R, LR_ret>, 
00106                               triplet_<i_L, i_R, LR_ret> >
00107       {
00108         typedef triplet_<i_L, i_R, LR_ret> ret;
00109       };
00110 
00111 
00112       template < unsigned L_i_L, unsigned L_i_R, unsigned L_i_max,
00113                  unsigned R_i_L, unsigned R_i_R, unsigned R_i_max >
00114       // L_i_max and R_i_max differ
00115       struct helper_merge_triplets_same_ret_
00116       {
00117         // The winning couple between L_* and R_* is the one which
00118         // maximum index is the smallest; for instance, with:
00119         //   left  branch giving L_i_L = 5 and L_i_R = 1 so L_i_max = 5
00120         //   right branch giving L_i_L = 3 and L_i_R = 4 so R_i_max = 4
00121         // the right branch wins.
00122         enum { i_L = (L_i_max < R_i_max ? L_i_L : R_i_L),
00123                i_R = (L_i_max < R_i_max ? L_i_R : R_i_R) };
00124       };
00125 
00126       template < unsigned L_i_L, unsigned L_i_R, unsigned i_max,
00127                  unsigned R_i_L, unsigned R_i_R >
00128       // L_i_max is equal to R_i_max
00129       struct helper_merge_triplets_same_ret_< L_i_L, L_i_R, i_max,
00130                                               R_i_L, R_i_R, i_max >
00131       {
00132         // The winning couple is the one with the minimum index.
00133         enum { L_i_min = (L_i_L < L_i_R ? L_i_L : L_i_R),
00134                R_i_min = (R_i_L < R_i_R ? R_i_L : R_i_R),
00135                i_L = (L_i_min < R_i_min ? L_i_L : R_i_L),
00136                i_R = (L_i_min < R_i_min ? L_i_R : R_i_R) };
00137       };
00138 
00139 
00140       template < unsigned L_i_L, unsigned L_i_R, typename LR_ret,
00141                  unsigned R_i_L, unsigned R_i_R >
00142       struct merge_triplets_< triplet_<L_i_L, L_i_R, LR_ret>, 
00143                               triplet_<R_i_L, R_i_R, LR_ret> >
00144       {
00145         typedef helper_merge_triplets_same_ret_< L_i_L, L_i_R, (L_i_L > L_i_R ? L_i_L : L_i_R),
00146                                                  R_i_L, R_i_R, (R_i_L > R_i_R ? R_i_L : R_i_R) > helper;
00147         typedef triplet_<helper::i_L, helper::i_R, LR_ret> ret;
00148       };
00149 
00150       template < unsigned L_i_L, unsigned L_i_R, typename L_ret >
00151       struct merge_triplets_< triplet_<L_i_L, L_i_R, L_ret>,
00152                               triplet_<  0,     0,   not_found> >
00153       {
00154         typedef triplet_<L_i_L, L_i_R, L_ret> ret;
00155       };
00156 
00157       template < unsigned R_i_L, unsigned R_i_R, typename R_ret >
00158       struct merge_triplets_< triplet_<  0,     0,   not_found>,
00159                               triplet_<R_i_L, R_i_R, R_ret> >
00160       {
00161         typedef triplet_<R_i_L, R_i_R, R_ret> ret;
00162       };
00163 
00164       template <> // To disambiguate.
00165       struct merge_triplets_< triplet_<0, 0, not_found>,
00166                               triplet_<0, 0, not_found> >
00167       {
00168         typedef triplet_<0u,0u, not_found> ret;
00169       };
00170 
00171 
00172 
00173       // Fwd decl.
00174       template < template <class, class> class Name,
00175                  unsigned i_L, typename Category_L, typename L,
00176                  unsigned i_R, typename Category_R, typename R >
00177       struct get_binary_;
00178 
00179 
00180       template < typename user_ret, /* != not_found and != undefined */
00181                  template <class, class> class Name,
00182                  unsigned i_L, typename Category_L, typename L,
00183                  unsigned i_R, typename Category_R, typename R >
00184       struct helper_get_binary_
00185       {
00186         typedef triplet_< i_L, i_R, user_ret > ret; // The user has defined 'ret' so we return it.
00187       };
00188 
00189       template < template <class, class> class Name,
00190                  unsigned i_L, typename Category_L, typename L,
00191                  unsigned i_R, typename Category_R, typename R >
00192       struct helper_get_binary_< /* user_ret == */ not_found,
00193                                  Name,  i_L, Category_L, L,  i_R, Category_R, R >
00194       {
00195         typedef triplet_< 0, 0, not_found > ret; // End of search due to a blocker; 'ret' is not found. 
00196       };
00197 
00198 
00199       template < template <class, class> class Name,
00200                  unsigned i_L, typename Category_L, typename L,
00201                  unsigned i_R, typename Category_R, typename R >
00202       struct helper_get_binary_< /* user_ret == */ undefined,
00203                                  Name, i_L,Category_L, L, i_R,Category_R, R >
00204       {
00205         // No user definition for 'ret' so treillis construction in a static recursive way.
00206 
00207         // FIXME: We *do* need to handle this search with a priority!
00208         // FIXME: for a result can be found in both branches... 
00209 
00210         typedef typename mln::internal::super_category_< Category_L, L >::ret Super_Category_L;
00211         typedef typename mln::internal::super_category_< Category_R, R >::ret Super_Category_R;
00212 
00213         typedef get_binary_< Name,
00214                              i_L + 1, Super_Category_L, L,
00215                              i_R,     Category_R,       R > L_branch;
00216         typedef mlc_ret(L_branch) L_trp;
00217 
00218         typedef get_binary_< Name,
00219                              i_L,     Category_L,       L,
00220                              i_R + 1, Super_Category_R, R > R_branch;
00221         typedef mlc_ret(R_branch) R_trp;
00222         
00223         typedef typename merge_triplets_< L_trp, R_trp >::ret ret;
00224       };
00225 
00226 
00227       template < template <class, class> class Name,
00228                  unsigned i_L, typename Category_L, typename L,
00229                  unsigned i_R, typename Category_R, typename R >
00230       struct get_binary_
00231       {
00232         typedef typename trait_set_binary_<Name, Category_L,L,
00233                                            Category_R,R>::ret user_ret;  // First get 'user_ret'
00234         typedef helper_get_binary_<user_ret, Name, i_L,Category_L,L,
00235                                                    i_R,Category_R,R> helper;        // Set the helper to make a decision.
00236         typedef mlc_ret(helper) ret;                                                // Return a triplet.
00237       };
00238 
00239 
00240       template < typename precise_ret,
00241                  template <class, class> class Name,
00242                  typename Category_L, typename L,
00243                  typename Category_R, typename R >
00244       struct helper_choose_binary_wrt_ /* precise_ret != undefined */
00245       {
00246         typedef precise_ret ret;                                                 // -> A precise ret has been defined so it is it.
00247       };
00248 
00249       template < template <class, class> class Name,
00250                  typename Category_L, typename L,
00251                  typename Category_R, typename R >
00252       struct helper_choose_binary_wrt_< /* precise_ret == */ undefined,
00253                                         Name, Category_L, L, Category_R, R >
00254       {
00255         typedef typename get_binary_< Name,
00256                                       0, Category_L, L,
00257                                       0, Category_R, R >::ret triplet;           // Browse upwards the category inheritance
00258         typedef mlc_ret(triplet) ret;                                            // to fetch ret from 'get_binary_'s.
00259       };
00260 
00261 
00262       template < template <class, class> class Name,
00263                  typename Category_L, typename L,
00264                  typename Category_R, typename R >
00265       struct helper_solve_binary_
00266       {
00267         typedef typename set_precise_binary_<Name, L, R>::ret precise_ret; /* undefined or not (?) */
00268         typedef helper_choose_binary_wrt_<precise_ret, Name, Category_L,L, Category_R,R> helper;
00269         typedef mlc_ret(helper) ret;
00270       };
00271 
00272     } // end of namespace mln::trait::internal
00273 
00274 
00275     // FIXME: Postfix solve_binary with a '-'(?)
00276     template < template <class, class> class Name,
00277                typename L_,
00278                typename R_ >
00279     struct solve_binary
00280     {
00281       typedef mln_exact(L_) L;
00282       typedef mln_exact(R_) R;
00283       typedef typename mln::category<L>::ret Category_L;
00284       typedef typename mln::category<R>::ret Category_R;
00285       typedef internal::helper_solve_binary_< Name, Category_L, L, Category_R, R > meta_code;
00286       typedef typename meta_code::ret ret;
00287     };
00288 
00289   } // end of namespace mln::trait
00290 
00291 } // end of namespace mln
00292 
00293 
00294 #endif // ! MLN_TRAIT_SOLVE_BINARY_HH

Generated on Tue Oct 4 2011 15:24:34 for Milena (Olena) by  doxygen 1.7.1