Milena (Olena)
User documentation 2.0a Id
|
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