• 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_NEXT_SOLVE_BINARY_HH
00027 # define MLN_TRAIT_NEXT_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 # include <mln/trait/next/solve.hh>
00039 
00040 
00041 // FIXME: Just for the record (use it...)
00042 
00043 #  ifndef MLN_DEBUG_TRAITS
00044 #  endif // ! MLN_DEBUG_TRAITS
00045 
00046 
00047 
00048 namespace mln
00049 {
00050 
00051   namespace trait
00052   {
00053 
00054     namespace next
00055     {
00056 
00057       namespace internal
00058       {
00059 
00060 
00061         template < typename Name,
00062                   typename Category_L, typename L,
00063                   typename Category_R, typename R >
00064         struct trait_set_binary_;
00065 
00066         template < typename Name,
00067                   template <class> class Category_L, typename _l, typename L,
00068                   template <class> class Category_R, typename _r, typename R >
00069         struct trait_set_binary_< Name,
00070                                 Category_L<_l>, L,
00071                                 Category_R<_r>, R >
00072         {
00073           typedef typename mln::trait::next::set_binary_<Name,
00074                                                          Category_L, L,
00075                                                          Category_R, R>::ret ret;
00076         };
00077 
00078 
00079         // triplet_ret_
00080 
00081         template < unsigned i_L_, unsigned i_R_, typename ret_ >
00082         struct triplet_
00083         {
00084           typedef ret_ ret;
00085         };
00086 
00087 
00088         // merge_triplets_
00089 
00090         template < typename L_trp, typename R_trp >
00091         struct merge_triplets_;
00092 
00093         template < unsigned L_i_L, unsigned L_i_R, typename L_ret,
00094                   unsigned R_i_L, unsigned R_i_R, typename R_ret >
00095         struct merge_triplets_< triplet_<L_i_L, L_i_R, L_ret>,
00096                                 triplet_<R_i_L, R_i_R, R_ret> >
00097         {
00098           typedef metal::bool_<(L_i_L <= R_i_L && L_i_R <= R_i_R)> take_L;
00099           typedef metal::bool_<(R_i_L <= L_i_L && R_i_R <= L_i_R)> take_R;
00100           typedef metal::or_<take_L, take_R> ok;
00101           typedef typename metal::if_< metal::and_<ok, take_L>,
00102                                       triplet_<L_i_L, L_i_R, L_ret>,
00103                                       typename metal::if_< metal::and_<ok, take_R>,
00104                                                             triplet_<R_i_L, R_i_R, R_ret>,
00105                                                             triplet_<0,0, not_found> >::ret >::ret ret;
00106         };
00107 
00108         template < unsigned i_L, unsigned i_R, typename LR_ret >
00109         struct merge_triplets_< triplet_<i_L, i_R, LR_ret>,
00110                                 triplet_<i_L, i_R, LR_ret> >
00111         {
00112           typedef triplet_<i_L, i_R, LR_ret> ret;
00113         };
00114 
00115 
00116         template < unsigned L_i_L, unsigned L_i_R, unsigned L_i_max,
00117                   unsigned R_i_L, unsigned R_i_R, unsigned R_i_max >
00118         // L_i_max and R_i_max differ
00119         struct helper_merge_triplets_same_ret_
00120         {
00121           // The winning couple between L_* and R_* is the one which
00122           // maximum index is the smallest; for instance, with:
00123           //   left  branch giving L_i_L = 5 and L_i_R = 1 so L_i_max = 5
00124           //   right branch giving L_i_L = 3 and L_i_R = 4 so R_i_max = 4
00125           // the right branch wins.
00126           enum { i_L = (L_i_max < R_i_max ? L_i_L : R_i_L),
00127                 i_R = (L_i_max < R_i_max ? L_i_R : R_i_R) };
00128         };
00129 
00130         template < unsigned L_i_L, unsigned L_i_R, unsigned i_max,
00131                   unsigned R_i_L, unsigned R_i_R >
00132         // L_i_max is equal to R_i_max
00133         struct helper_merge_triplets_same_ret_< L_i_L, L_i_R, i_max,
00134                                                 R_i_L, R_i_R, i_max >
00135         {
00136           // The winning couple is the one with the minimum index.
00137           enum { L_i_min = (L_i_L < L_i_R ? L_i_L : L_i_R),
00138                 R_i_min = (R_i_L < R_i_R ? R_i_L : R_i_R),
00139                 i_L = (L_i_min < R_i_min ? L_i_L : R_i_L),
00140                 i_R = (L_i_min < R_i_min ? L_i_R : R_i_R) };
00141         };
00142 
00143 
00144         template < unsigned L_i_L, unsigned L_i_R, typename LR_ret,
00145                   unsigned R_i_L, unsigned R_i_R >
00146         struct merge_triplets_< triplet_<L_i_L, L_i_R, LR_ret>,
00147                                 triplet_<R_i_L, R_i_R, LR_ret> >
00148         {
00149           typedef helper_merge_triplets_same_ret_< L_i_L, L_i_R, (L_i_L > L_i_R ? L_i_L : L_i_R),
00150                                                   R_i_L, R_i_R, (R_i_L > R_i_R ? R_i_L : R_i_R) > helper;
00151           typedef triplet_<helper::i_L, helper::i_R, LR_ret> ret;
00152         };
00153 
00154         template < unsigned L_i_L, unsigned L_i_R, typename L_ret >
00155         struct merge_triplets_< triplet_<L_i_L, L_i_R, L_ret>,
00156                                 triplet_<  0,     0,   not_found> >
00157         {
00158           typedef triplet_<L_i_L, L_i_R, L_ret> ret;
00159         };
00160 
00161         template < unsigned R_i_L, unsigned R_i_R, typename R_ret >
00162         struct merge_triplets_< triplet_<  0,     0,   not_found>,
00163                                 triplet_<R_i_L, R_i_R, R_ret> >
00164         {
00165           typedef triplet_<R_i_L, R_i_R, R_ret> ret;
00166         };
00167 
00168         template <> // To disambiguate.
00169         struct merge_triplets_< triplet_<0, 0, not_found>,
00170                                 triplet_<0, 0, not_found> >
00171         {
00172           typedef triplet_<0u,0u, not_found> ret;
00173         };
00174 
00175 
00176 
00177         // Fwd decl.
00178         template < typename Name,
00179                   unsigned i_L, typename Category_L, typename L,
00180                   unsigned i_R, typename Category_R, typename R >
00181         struct get_binary_;
00182 
00183 
00184         template < typename user_ret, /* != not_found and != undefined */
00185                   typename Name,
00186                   unsigned i_L, typename Category_L, typename L,
00187                   unsigned i_R, typename Category_R, typename R >
00188         struct helper_get_binary_
00189         {
00190           typedef triplet_< i_L, i_R, user_ret > ret; // The user has defined 'ret' so we return it.
00191         };
00192 
00193         template < typename Name,
00194                   unsigned i_L, typename Category_L, typename L,
00195                   unsigned i_R, typename Category_R, typename R >
00196         struct helper_get_binary_< /* user_ret == */ not_found,
00197                                   Name,  i_L, Category_L, L,  i_R, Category_R, R >
00198         {
00199           typedef triplet_< 0, 0, not_found > ret; // End of search due to a blocker; 'ret' is not found.
00200         };
00201 
00202 
00203         template < typename Name,
00204                   unsigned i_L, typename Category_L, typename L,
00205                   unsigned i_R, typename Category_R, typename R >
00206         struct helper_get_binary_< /* user_ret == */ undefined,
00207                                   Name, i_L,Category_L, L, i_R,Category_R, R >
00208         {
00209           // No user definition for 'ret' so treillis construction in a static recursive way.
00210 
00211           // FIXME: We *do* need to handle this search with a priority!
00212           // FIXME: for a result can be found in both branches...
00213 
00214           typedef typename mln::internal::super_category_< Category_L, L >::ret Super_Category_L;
00215           typedef typename mln::internal::super_category_< Category_R, R >::ret Super_Category_R;
00216 
00217           typedef get_binary_< Name,
00218                               i_L + 1, Super_Category_L, L,
00219                               i_R,     Category_R,       R > L_branch;
00220           typedef mlc_ret(L_branch) L_trp;
00221 
00222           typedef get_binary_< Name,
00223                               i_L,     Category_L,       L,
00224                               i_R + 1, Super_Category_R, R > R_branch;
00225           typedef mlc_ret(R_branch) R_trp;
00226 
00227           typedef typename merge_triplets_< L_trp, R_trp >::ret ret;
00228         };
00229 
00230 
00231         template < typename Name,
00232                   unsigned i_L, typename Category_L, typename L,
00233                   unsigned i_R, typename Category_R, typename R >
00234         struct get_binary_
00235         {
00236           typedef typename trait_set_binary_<Name, Category_L,L,
00237                                             Category_R,R>::ret user_ret;  // First get 'user_ret'
00238           typedef helper_get_binary_<user_ret, Name, i_L,Category_L,L,
00239                                                     i_R,Category_R,R> helper;        // Set the helper to make a decision.
00240           typedef mlc_ret(helper) ret;                                                // Return a triplet.
00241         };
00242 
00243 
00244         template < typename precise_ret,
00245                   typename Name,
00246                   typename Category_L, typename L,
00247                   typename Category_R, typename R >
00248         struct helper_choose_binary_wrt_ /* precise_ret != undefined */
00249         {
00250           typedef precise_ret ret;                                                 // -> A precise ret has been defined so it is it.
00251         };
00252 
00253         template < typename Name,
00254                   typename Category_L, typename L,
00255                   typename Category_R, typename R >
00256         struct helper_choose_binary_wrt_< /* precise_ret == */ undefined,
00257                                           Name, Category_L, L, Category_R, R >
00258         {
00259           typedef typename get_binary_< Name,
00260                                         0, Category_L, L,
00261                                         0, Category_R, R >::ret triplet;           // Browse upwards the category inheritance
00262           typedef mlc_ret(triplet) ret;                                            // to fetch ret from 'get_binary_'s.
00263         };
00264 
00265 
00266         template < typename Name,
00267                   typename Category_L, typename L,
00268                   typename Category_R, typename R >
00269         struct helper_solve_binary_
00270         {
00271           typedef typename set_precise_binary_<Name, L, R>::ret precise_ret; /* undefined or not (?) */
00272           typedef helper_choose_binary_wrt_<precise_ret, Name, Category_L,L, Category_R,R> helper;
00273           typedef mlc_ret(helper) ret;
00274         };
00275 
00276       } // end of namespace mln::trait::internal
00277 
00278 
00279       // FIXME: Postfix solve_binary with a '-'(?)
00280       template < typename Name,
00281                 typename L_,
00282                 typename R_ >
00283       struct solve_binary
00284       {
00285         typedef mln_exact(L_) L;
00286         typedef mln_exact(R_) R;
00287         typedef typename mln::category<L>::ret Category_L;
00288         typedef typename mln::category<R>::ret Category_R;
00289         typedef internal::helper_solve_binary_< Name, Category_L, L, Category_R, R > meta_code;
00290         typedef typename meta_code::ret ret;
00291       };
00292 
00293     } // end of namespace mln::trait::next
00294 
00295   } // end of namespace mln::trait
00296 
00297 } // end of namespace mln
00298 
00299 
00300 #endif // ! MLN_TRAIT_NEXT_SOLVE_BINARY_HH

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