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_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
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
00076
00077 template < unsigned i_L_, unsigned i_R_, typename ret_ >
00078 struct triplet_
00079 {
00080 typedef ret_ ret;
00081 };
00082
00083
00084
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
00115 struct helper_merge_triplets_same_ret_
00116 {
00117
00118
00119
00120
00121
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
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
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 <>
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
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,
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;
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_< not_found,
00193 Name, i_L, Category_L, L, i_R, Category_R, R >
00194 {
00195 typedef triplet_< 0, 0, not_found > ret;
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_< undefined,
00203 Name, i_L,Category_L, L, i_R,Category_R, R >
00204 {
00205
00206
00207
00208
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;
00234 typedef helper_get_binary_<user_ret, Name, i_L,Category_L,L,
00235 i_R,Category_R,R> helper;
00236 typedef mlc_ret(helper) ret;
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_
00245 {
00246 typedef precise_ret ret;
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_< 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;
00258 typedef mlc_ret(triplet) ret;
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;
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 }
00273
00274
00275
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 }
00290
00291 }
00292
00293
00294 #endif // ! MLN_TRAIT_SOLVE_BINARY_HH