00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
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
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
00080
00081 template < unsigned i_L_, unsigned i_R_, typename ret_ >
00082 struct triplet_
00083 {
00084 typedef ret_ ret;
00085 };
00086
00087
00088
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
00119 struct helper_merge_triplets_same_ret_
00120 {
00121
00122
00123
00124
00125
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
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
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 <>
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
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,
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;
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_< not_found,
00197 Name, i_L, Category_L, L, i_R, Category_R, R >
00198 {
00199 typedef triplet_< 0, 0, not_found > ret;
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_< undefined,
00207 Name, i_L,Category_L, L, i_R,Category_R, R >
00208 {
00209
00210
00211
00212
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;
00238 typedef helper_get_binary_<user_ret, Name, i_L,Category_L,L,
00239 i_R,Category_R,R> helper;
00240 typedef mlc_ret(helper) ret;
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_
00249 {
00250 typedef precise_ret ret;
00251 };
00252
00253 template < typename Name,
00254 typename Category_L, typename L,
00255 typename Category_R, typename R >
00256 struct helper_choose_binary_wrt_< 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;
00262 typedef mlc_ret(triplet) ret;
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;
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 }
00277
00278
00279
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 }
00294
00295 }
00296
00297 }
00298
00299
00300 #endif // ! MLN_TRAIT_NEXT_SOLVE_BINARY_HH