26 #ifndef MLN_TRAIT_SOLVE_BINARY_HH
27 # define MLN_TRAIT_SOLVE_BINARY_HH
33 # include <mln/core/category.hh>
34 # include <mln/core/routine/exact.hh>
35 # include <mln/metal/equal.hh>
36 # include <mln/metal/if.hh>
37 # include <mln/metal/ret.hh>
42 # ifndef MLN_DEBUG_TRAITS
43 # endif // ! MLN_DEBUG_TRAITS
57 template <
template <
class,
class>
class Name,
58 typename Category_L,
typename L,
59 typename Category_R,
typename R >
60 struct trait_set_binary_;
62 template <
template <
class,
class>
class Name,
63 template <
class>
class Category_L,
typename _l,
typename L,
64 template <
class>
class Category_R,
typename _r,
typename R >
65 struct trait_set_binary_< Name,
69 typedef typename mln::trait::set_binary_<Name,
77 template <
unsigned i_L_,
unsigned i_R_,
typename ret_ >
86 template <
typename L_trp,
typename R_trp >
87 struct merge_triplets_;
89 template <
unsigned L_i_L,
unsigned L_i_R,
typename L_ret,
90 unsigned R_i_L,
unsigned R_i_R,
typename R_ret >
91 struct merge_triplets_< triplet_<L_i_L, L_i_R, L_ret>,
92 triplet_<R_i_L, R_i_R, R_ret> >
94 typedef metal::bool_<(L_i_L <= R_i_L && L_i_R <= R_i_R)> take_L;
95 typedef metal::bool_<(R_i_L <= L_i_L && R_i_R <= L_i_R)> take_R;
96 typedef metal::or_<take_L, take_R> ok;
97 typedef typename metal::if_< metal::and_<ok, take_L>,
98 triplet_<L_i_L, L_i_R, L_ret>,
99 typename metal::if_< metal::and_<ok, take_R>,
100 triplet_<R_i_L, R_i_R, R_ret>,
104 template <
unsigned i_L,
unsigned i_R,
typename LR_ret >
105 struct merge_triplets_< triplet_<i_L, i_R, LR_ret>,
106 triplet_<i_L, i_R, LR_ret> >
108 typedef triplet_<i_L, i_R, LR_ret>
ret;
112 template <
unsigned L_i_L,
unsigned L_i_R,
unsigned L_i_max,
113 unsigned R_i_L,
unsigned R_i_R,
unsigned R_i_max >
115 struct helper_merge_triplets_same_ret_
122 enum { i_L = (L_i_max < R_i_max ? L_i_L : R_i_L),
123 i_R = (L_i_max < R_i_max ? L_i_R : R_i_R) };
126 template <
unsigned L_i_L,
unsigned L_i_R,
unsigned i_max,
127 unsigned R_i_L,
unsigned R_i_R >
129 struct helper_merge_triplets_same_ret_< L_i_L, L_i_R, i_max,
130 R_i_L, R_i_R, i_max >
133 enum { L_i_min = (L_i_L < L_i_R ? L_i_L : L_i_R),
134 R_i_min = (R_i_L < R_i_R ? R_i_L : R_i_R),
135 i_L = (L_i_min < R_i_min ? L_i_L : R_i_L),
136 i_R = (L_i_min < R_i_min ? L_i_R : R_i_R) };
140 template <
unsigned L_i_L,
unsigned L_i_R,
typename LR_ret,
141 unsigned R_i_L,
unsigned R_i_R >
142 struct merge_triplets_< triplet_<L_i_L, L_i_R, LR_ret>,
143 triplet_<R_i_L, R_i_R, LR_ret> >
145 typedef helper_merge_triplets_same_ret_< L_i_L, L_i_R, (L_i_L > L_i_R ? L_i_L : L_i_R),
146 R_i_L, R_i_R, (R_i_L > R_i_R ? R_i_L : R_i_R) > helper;
147 typedef triplet_<helper::i_L, helper::i_R, LR_ret>
ret;
150 template <
unsigned L_i_L,
unsigned L_i_R,
typename L_ret >
151 struct merge_triplets_< triplet_<L_i_L, L_i_R, L_ret>,
152 triplet_< 0, 0, not_found> >
154 typedef triplet_<L_i_L, L_i_R, L_ret>
ret;
157 template <
unsigned R_i_L,
unsigned R_i_R,
typename R_ret >
158 struct merge_triplets_< triplet_< 0, 0, not_found>,
159 triplet_<R_i_L, R_i_R, R_ret> >
161 typedef triplet_<R_i_L, R_i_R, R_ret>
ret;
165 struct merge_triplets_< triplet_<0, 0, not_found>,
166 triplet_<0, 0, not_found> >
168 typedef triplet_<0u,0u, not_found>
ret;
174 template <
template <
class,
class>
class Name,
175 unsigned i_L,
typename Category_L,
typename L,
176 unsigned i_R,
typename Category_R,
typename R >
180 template <
typename user_ret,
181 template <
class,
class>
class Name,
182 unsigned i_L,
typename Category_L,
typename L,
183 unsigned i_R,
typename Category_R,
typename R >
184 struct helper_get_binary_
186 typedef triplet_< i_L, i_R, user_ret >
ret;
189 template <
template <
class,
class>
class Name,
190 unsigned i_L,
typename Category_L,
typename L,
191 unsigned i_R,
typename Category_R,
typename R >
192 struct helper_get_binary_< not_found,
193 Name, i_L, Category_L, L, i_R, Category_R, R >
195 typedef triplet_< 0, 0, not_found >
ret;
199 template <
template <
class,
class>
class Name,
200 unsigned i_L,
typename Category_L,
typename L,
201 unsigned i_R,
typename Category_R,
typename R >
202 struct helper_get_binary_< undefined,
203 Name, i_L,Category_L, L, i_R,Category_R, R >
213 typedef get_binary_< Name,
214 i_L + 1, Super_Category_L, L,
215 i_R, Category_R, R > L_branch;
216 typedef mlc_ret(L_branch) L_trp;
218 typedef get_binary_< Name,
220 i_R + 1, Super_Category_R, R > R_branch;
221 typedef mlc_ret(R_branch) R_trp;
223 typedef typename merge_triplets_< L_trp, R_trp >::
ret ret;
227 template < template <class, class> class Name,
228 unsigned i_L, typename Category_L, typename L,
229 unsigned i_R, typename Category_R, typename R >
232 typedef typename trait_set_binary_<Name, Category_L,L,
233 Category_R,R>
::ret user_ret;
234 typedef helper_get_binary_<user_ret, Name, i_L,Category_L,L,
235 i_R,Category_R,R> helper;
236 typedef mlc_ret(helper) ret;
240 template < typename precise_ret,
241 template <class, class> class Name,
242 typename Category_L, typename L,
243 typename Category_R, typename R >
244 struct helper_choose_binary_wrt_
246 typedef precise_ret ret;
249 template <
template <
class,
class>
class Name,
250 typename Category_L,
typename L,
251 typename Category_R,
typename R >
252 struct helper_choose_binary_wrt_< undefined,
253 Name, Category_L, L, Category_R, R >
255 typedef typename get_binary_< Name,
257 0, Category_R, R >
::ret triplet;
258 typedef mlc_ret(triplet) ret;
262 template < template <class, class> class Name,
263 typename Category_L, typename L,
264 typename Category_R, typename R >
265 struct helper_solve_binary_
267 typedef typename set_precise_binary_<Name, L, R>::ret precise_ret;
268 typedef helper_choose_binary_wrt_<precise_ret, Name, Category_L,L, Category_R,R> helper;
269 typedef mlc_ret(helper) ret;
276 template < template <class, class> class Name,
281 typedef mln_exact(L_) L;
282 typedef mln_exact(R_) R;
285 typedef internal::helper_solve_binary_< Name, Category_L, L, Category_R, R >
meta_code;
286 typedef typename meta_code::ret
ret;
294 #endif // ! MLN_TRAIT_SOLVE_BINARY_HH