$extrastylesheet
Olena  User documentation 2.1
An Image Processing Platform
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
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_SOLVE_BINARY_HH
27 # define MLN_TRAIT_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 
39 
40 // FIXME: Just for the record (use it...)
41 
42 # ifndef MLN_DEBUG_TRAITS
43 # endif // ! MLN_DEBUG_TRAITS
44 
45 
46 
47 namespace mln
48 {
49 
50  namespace trait
51  {
52 
53  namespace internal
54  {
55 
56 
57  template < template <class, class> class Name,
58  typename Category_L, typename L,
59  typename Category_R, typename R >
60  struct trait_set_binary_;
61 
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,
66  Category_L<_l>, L,
67  Category_R<_r>, R >
68  {
69  typedef typename mln::trait::set_binary_<Name,
70  Category_L, L,
71  Category_R, R>::ret ret;
72  };
73 
74 
75  // triplet_ret_
76 
77  template < unsigned i_L_, unsigned i_R_, typename ret_ >
78  struct triplet_
79  {
80  typedef ret_ ret;
81  };
82 
83 
84  // merge_triplets_
85 
86  template < typename L_trp, typename R_trp >
87  struct merge_triplets_;
88 
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> >
93  {
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>,
101  triplet_<0,0, not_found> >::ret >::ret ret;
102  };
103 
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> >
107  {
108  typedef triplet_<i_L, i_R, LR_ret> ret;
109  };
110 
111 
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 >
114  // L_i_max and R_i_max differ
115  struct helper_merge_triplets_same_ret_
116  {
117  // The winning couple between L_* and R_* is the one which
118  // maximum index is the smallest; for instance, with:
119  // left branch giving L_i_L = 5 and L_i_R = 1 so L_i_max = 5
120  // right branch giving L_i_L = 3 and L_i_R = 4 so R_i_max = 4
121  // the right branch wins.
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) };
124  };
125 
126  template < unsigned L_i_L, unsigned L_i_R, unsigned i_max,
127  unsigned R_i_L, unsigned R_i_R >
128  // L_i_max is equal to R_i_max
129  struct helper_merge_triplets_same_ret_< L_i_L, L_i_R, i_max,
130  R_i_L, R_i_R, i_max >
131  {
132  // The winning couple is the one with the minimum index.
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) };
137  };
138 
139 
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> >
144  {
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;
148  };
149 
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> >
153  {
154  typedef triplet_<L_i_L, L_i_R, L_ret> ret;
155  };
156 
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> >
160  {
161  typedef triplet_<R_i_L, R_i_R, R_ret> ret;
162  };
163 
164  template <> // To disambiguate.
165  struct merge_triplets_< triplet_<0, 0, not_found>,
166  triplet_<0, 0, not_found> >
167  {
168  typedef triplet_<0u,0u, not_found> ret;
169  };
170 
171 
172 
173  // Fwd decl.
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 >
177  struct get_binary_;
178 
179 
180  template < typename user_ret, /* != not_found and != undefined */
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_
185  {
186  typedef triplet_< i_L, i_R, user_ret > ret; // The user has defined 'ret' so we return it.
187  };
188 
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_< /* user_ret == */ not_found,
193  Name, i_L, Category_L, L, i_R, Category_R, R >
194  {
195  typedef triplet_< 0, 0, not_found > ret; // End of search due to a blocker; 'ret' is not found.
196  };
197 
198 
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_< /* user_ret == */ undefined,
203  Name, i_L,Category_L, L, i_R,Category_R, R >
204  {
205  // No user definition for 'ret' so treillis construction in a static recursive way.
206 
207  // FIXME: We *do* need to handle this search with a priority!
208  // FIXME: for a result can be found in both branches...
209 
210  typedef typename mln::internal::super_category_< Category_L, L >::ret Super_Category_L;
211  typedef typename mln::internal::super_category_< Category_R, R >::ret Super_Category_R;
212 
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;
217 
218  typedef get_binary_< Name,
219  i_L, Category_L, L,
220  i_R + 1, Super_Category_R, R > R_branch;
221  typedef mlc_ret(R_branch) R_trp;
222 
223  typedef typename merge_triplets_< L_trp, R_trp >::ret ret;
224  };
225 
226 
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 >
230  struct get_binary_
231  {
232  typedef typename trait_set_binary_<Name, Category_L,L,
233  Category_R,R>::ret user_ret; // First get 'user_ret'
234  typedef helper_get_binary_<user_ret, Name, i_L,Category_L,L,
235  i_R,Category_R,R> helper; // Set the helper to make a decision.
236  typedef mlc_ret(helper) ret; // Return a triplet.
237  };
238 
239 
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_ /* precise_ret != undefined */
245  {
246  typedef precise_ret ret; // -> A precise ret has been defined so it is it.
247  };
248 
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_< /* precise_ret == */ undefined,
253  Name, Category_L, L, Category_R, R >
254  {
255  typedef typename get_binary_< Name,
256  0, Category_L, L,
257  0, Category_R, R >::ret triplet; // Browse upwards the category inheritance
258  typedef mlc_ret(triplet) ret; // to fetch ret from 'get_binary_'s.
259  };
260 
261 
262  template < template <class, class> class Name,
263  typename Category_L, typename L,
264  typename Category_R, typename R >
265  struct helper_solve_binary_
266  {
267  typedef typename set_precise_binary_<Name, L, R>::ret precise_ret; /* undefined or not (?) */
268  typedef helper_choose_binary_wrt_<precise_ret, Name, Category_L,L, Category_R,R> helper;
269  typedef mlc_ret(helper) ret;
270  };
271 
272  } // end of namespace mln::trait::internal
273 
274 
275  // FIXME: Postfix solve_binary with a '-'(?)
276  template < template <class, class> class Name,
277  typename L_,
278  typename R_ >
280  {
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;
287  };
288 
289  } // end of namespace mln::trait
290 
291 } // end of namespace mln
292 
293 
294 #endif // ! MLN_TRAIT_SOLVE_BINARY_HH