$extrastylesheet
Olena  User documentation 2.1
An Image Processing Platform
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
next/solve_binary.hh
1 // Copyright (C) 2006, 2008, 2009 EPITA Research and Development Laboratory (LRDE)
2 //
3 // This file is part of Olena.
4 //
5 // Olena is free software: you can redistribute it and/or modify it under
6 // the terms of the GNU General Public License as published by the Free
7 // Software Foundation, version 2 of the License.
8 //
9 // Olena is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with Olena. If not, see <http://www.gnu.org/licenses/>.
16 //
17 // As a special exception, you may use this file as part of a free
18 // software project without restriction. Specifically, if other files
19 // instantiate templates or use macros or inline functions from this
20 // file, or you compile this file and link it with other files to produce
21 // an executable, this file does not by itself cause the resulting
22 // executable to be covered by the GNU General Public License. This
23 // exception does not however invalidate any other reasons why the
24 // executable file might be covered by the GNU General Public License.
25 
26 #ifndef MLN_TRAIT_NEXT_SOLVE_BINARY_HH
27 # define MLN_TRAIT_NEXT_SOLVE_BINARY_HH
28 
32 
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>
38 # include <mln/trait/next/solve.hh>
39 
40 
41 // FIXME: Just for the record (use it...)
42 
43 # ifndef MLN_DEBUG_TRAITS
44 # endif // ! MLN_DEBUG_TRAITS
45 
46 
47 
48 namespace mln
49 {
50 
51  namespace trait
52  {
53 
54  namespace next
55  {
56 
57  namespace internal
58  {
59 
60 
61  template < typename Name,
62  typename Category_L, typename L,
63  typename Category_R, typename R >
64  struct trait_set_binary_;
65 
66  template < typename Name,
67  template <class> class Category_L, typename _l, typename L,
68  template <class> class Category_R, typename _r, typename R >
69  struct trait_set_binary_< Name,
70  Category_L<_l>, L,
71  Category_R<_r>, R >
72  {
73  typedef typename mln::trait::next::set_binary_<Name,
74  Category_L, L,
75  Category_R, R>::ret ret;
76  };
77 
78 
79  // triplet_ret_
80 
81  template < unsigned i_L_, unsigned i_R_, typename ret_ >
82  struct triplet_
83  {
84  typedef ret_ ret;
85  };
86 
87 
88  // merge_triplets_
89 
90  template < typename L_trp, typename R_trp >
91  struct merge_triplets_;
92 
93  template < unsigned L_i_L, unsigned L_i_R, typename L_ret,
94  unsigned R_i_L, unsigned R_i_R, typename R_ret >
95  struct merge_triplets_< triplet_<L_i_L, L_i_R, L_ret>,
96  triplet_<R_i_L, R_i_R, R_ret> >
97  {
98  typedef metal::bool_<(L_i_L <= R_i_L && L_i_R <= R_i_R)> take_L;
99  typedef metal::bool_<(R_i_L <= L_i_L && R_i_R <= L_i_R)> take_R;
100  typedef metal::or_<take_L, take_R> ok;
101  typedef typename metal::if_< metal::and_<ok, take_L>,
102  triplet_<L_i_L, L_i_R, L_ret>,
103  typename metal::if_< metal::and_<ok, take_R>,
104  triplet_<R_i_L, R_i_R, R_ret>,
105  triplet_<0,0, not_found> >::ret >::ret ret;
106  };
107 
108  template < unsigned i_L, unsigned i_R, typename LR_ret >
109  struct merge_triplets_< triplet_<i_L, i_R, LR_ret>,
110  triplet_<i_L, i_R, LR_ret> >
111  {
112  typedef triplet_<i_L, i_R, LR_ret> ret;
113  };
114 
115 
116  template < unsigned L_i_L, unsigned L_i_R, unsigned L_i_max,
117  unsigned R_i_L, unsigned R_i_R, unsigned R_i_max >
118  // L_i_max and R_i_max differ
119  struct helper_merge_triplets_same_ret_
120  {
121  // The winning couple between L_* and R_* is the one which
122  // maximum index is the smallest; for instance, with:
123  // left branch giving L_i_L = 5 and L_i_R = 1 so L_i_max = 5
124  // right branch giving L_i_L = 3 and L_i_R = 4 so R_i_max = 4
125  // the right branch wins.
126  enum { i_L = (L_i_max < R_i_max ? L_i_L : R_i_L),
127  i_R = (L_i_max < R_i_max ? L_i_R : R_i_R) };
128  };
129 
130  template < unsigned L_i_L, unsigned L_i_R, unsigned i_max,
131  unsigned R_i_L, unsigned R_i_R >
132  // L_i_max is equal to R_i_max
133  struct helper_merge_triplets_same_ret_< L_i_L, L_i_R, i_max,
134  R_i_L, R_i_R, i_max >
135  {
136  // The winning couple is the one with the minimum index.
137  enum { L_i_min = (L_i_L < L_i_R ? L_i_L : L_i_R),
138  R_i_min = (R_i_L < R_i_R ? R_i_L : R_i_R),
139  i_L = (L_i_min < R_i_min ? L_i_L : R_i_L),
140  i_R = (L_i_min < R_i_min ? L_i_R : R_i_R) };
141  };
142 
143 
144  template < unsigned L_i_L, unsigned L_i_R, typename LR_ret,
145  unsigned R_i_L, unsigned R_i_R >
146  struct merge_triplets_< triplet_<L_i_L, L_i_R, LR_ret>,
147  triplet_<R_i_L, R_i_R, LR_ret> >
148  {
149  typedef helper_merge_triplets_same_ret_< L_i_L, L_i_R, (L_i_L > L_i_R ? L_i_L : L_i_R),
150  R_i_L, R_i_R, (R_i_L > R_i_R ? R_i_L : R_i_R) > helper;
151  typedef triplet_<helper::i_L, helper::i_R, LR_ret> ret;
152  };
153 
154  template < unsigned L_i_L, unsigned L_i_R, typename L_ret >
155  struct merge_triplets_< triplet_<L_i_L, L_i_R, L_ret>,
156  triplet_< 0, 0, not_found> >
157  {
158  typedef triplet_<L_i_L, L_i_R, L_ret> ret;
159  };
160 
161  template < unsigned R_i_L, unsigned R_i_R, typename R_ret >
162  struct merge_triplets_< triplet_< 0, 0, not_found>,
163  triplet_<R_i_L, R_i_R, R_ret> >
164  {
165  typedef triplet_<R_i_L, R_i_R, R_ret> ret;
166  };
167 
168  template <> // To disambiguate.
169  struct merge_triplets_< triplet_<0, 0, not_found>,
170  triplet_<0, 0, not_found> >
171  {
172  typedef triplet_<0u,0u, not_found> ret;
173  };
174 
175 
176 
177  // Fwd decl.
178  template < typename Name,
179  unsigned i_L, typename Category_L, typename L,
180  unsigned i_R, typename Category_R, typename R >
181  struct get_binary_;
182 
183 
184  template < typename user_ret, /* != not_found and != undefined */
185  typename Name,
186  unsigned i_L, typename Category_L, typename L,
187  unsigned i_R, typename Category_R, typename R >
188  struct helper_get_binary_
189  {
190  typedef triplet_< i_L, i_R, user_ret > ret; // The user has defined 'ret' so we return it.
191  };
192 
193  template < typename Name,
194  unsigned i_L, typename Category_L, typename L,
195  unsigned i_R, typename Category_R, typename R >
196  struct helper_get_binary_< /* user_ret == */ not_found,
197  Name, i_L, Category_L, L, i_R, Category_R, R >
198  {
199  typedef triplet_< 0, 0, not_found > ret; // End of search due to a blocker; 'ret' is not found.
200  };
201 
202 
203  template < typename Name,
204  unsigned i_L, typename Category_L, typename L,
205  unsigned i_R, typename Category_R, typename R >
206  struct helper_get_binary_< /* user_ret == */ undefined,
207  Name, i_L,Category_L, L, i_R,Category_R, R >
208  {
209  // No user definition for 'ret' so treillis construction in a static recursive way.
210 
211  // FIXME: We *do* need to handle this search with a priority!
212  // FIXME: for a result can be found in both branches...
213 
214  typedef typename mln::internal::super_category_< Category_L, L >::ret Super_Category_L;
215  typedef typename mln::internal::super_category_< Category_R, R >::ret Super_Category_R;
216 
217  typedef get_binary_< Name,
218  i_L + 1, Super_Category_L, L,
219  i_R, Category_R, R > L_branch;
220  typedef mlc_ret(L_branch) L_trp;
221 
222  typedef get_binary_< Name,
223  i_L, Category_L, L,
224  i_R + 1, Super_Category_R, R > R_branch;
225  typedef mlc_ret(R_branch) R_trp;
226 
227  typedef typename merge_triplets_< L_trp, R_trp >::ret ret;
228  };
229 
230 
231  template < typename Name,
232  unsigned i_L, typename Category_L, typename L,
233  unsigned i_R, typename Category_R, typename R >
234  struct get_binary_
235  {
236  typedef typename trait_set_binary_<Name, Category_L,L,
237  Category_R,R>::ret user_ret; // First get 'user_ret'
238  typedef helper_get_binary_<user_ret, Name, i_L,Category_L,L,
239  i_R,Category_R,R> helper; // Set the helper to make a decision.
240  typedef mlc_ret(helper) ret; // Return a triplet.
241  };
242 
243 
244  template < typename precise_ret,
245  typename Name,
246  typename Category_L, typename L,
247  typename Category_R, typename R >
248  struct helper_choose_binary_wrt_ /* precise_ret != undefined */
249  {
250  typedef precise_ret ret; // -> A precise ret has been defined so it is it.
251  };
252 
253  template < typename Name,
254  typename Category_L, typename L,
255  typename Category_R, typename R >
256  struct helper_choose_binary_wrt_< /* precise_ret == */ undefined,
257  Name, Category_L, L, Category_R, R >
258  {
259  typedef typename get_binary_< Name,
260  0, Category_L, L,
261  0, Category_R, R >::ret triplet; // Browse upwards the category inheritance
262  typedef mlc_ret(triplet) ret; // to fetch ret from 'get_binary_'s.
263  };
264 
265 
266  template < typename Name,
267  typename Category_L, typename L,
268  typename Category_R, typename R >
269  struct helper_solve_binary_
270  {
271  typedef typename set_precise_binary_<Name, L, R>::ret precise_ret; /* undefined or not (?) */
272  typedef helper_choose_binary_wrt_<precise_ret, Name, Category_L,L, Category_R,R> helper;
273  typedef mlc_ret(helper) ret;
274  };
275 
276  } // end of namespace mln::trait::internal
277 
278 
279  // FIXME: Postfix solve_binary with a '-'(?)
280  template < typename Name,
281  typename L_,
282  typename R_ >
283  struct solve_binary
284  {
285  typedef mln_exact(L_) L;
286  typedef mln_exact(R_) R;
287  typedef typename mln::category<L>::ret Category_L;
288  typedef typename mln::category<R>::ret Category_R;
289  typedef internal::helper_solve_binary_< Name, Category_L, L, Category_R, R > meta_code;
290  typedef typename meta_code::ret ret;
291  };
292 
293  } // end of namespace mln::trait::next
294 
295  } // end of namespace mln::trait
296 
297 } // end of namespace mln
298 
299 
300 #endif // ! MLN_TRAIT_NEXT_SOLVE_BINARY_HH