aimstil  5.0.5
globalTraits.h
Go to the documentation of this file.
1 #ifndef _GLOBALTRAITS_H_
2 #define _GLOBALTRAITS_H_
3 
4 // includes from STL
5 #include <algorithm> // transform
6 #include <cassert>
7 #include <cmath> // sqrt
8 #include <functional> // mul, bind2nd
9 #include <limits> // numeric_limits
10 #include <vector>
11 
12 // includes from BOOST
13 #include <boost/array.hpp>
14 #include <boost/call_traits.hpp>
15 #include <boost/type_traits.hpp>
16 #include <boost/utility/enable_if.hpp>
17 
18 // includes from TIL
19 #include "til/til_declarations.h"
20 #include "til/is_traits.h"
21 #include "til/templateTools.h"
22 #include "til/TExpr.h"
23 #include "til/traits.h"
24 
25 // includes from TIL
26 #include "stditerator.h"
27 
28 
31 #define TIL_FOR_ALL_NUMERICAL_TYPES(macro) \
32 macro (double); \
33 macro (float); \
34 macro (long); \
35 macro (int); \
36 macro (short); \
37 macro (unsigned short); \
38 macro (char); \
39 macro (unsigned char);
40 
41 
42 namespace til
43 {
44 
45  namespace functor
46  {
47  struct Size
48  {
49  typedef std::size_t result_type;
50 
51  template < typename TCollection >
52  std::size_t operator()(const TCollection & c)
53  {
54  return size(c);
55  }
56  };
57  }
58 
59  namespace detail
60  {
61  template < class TContainer1, class TContainer2, typename TBinaryFunctor >
62  void
63  loop_cc(const TContainer1 & c1, TContainer2 &res, TBinaryFunctor f)
64  {
65  assert(size(c1) == size(res));
66  typename TContainer1::const_iterator iC1 = c1.begin();
67  typename TContainer2::iterator iRes = res.begin();
68  for (; iC1 != c1.end(); ++iC1, ++iRes)
69  {
70  loop(*iC1, *iRes, f);
71  }
72  }
73  }
74 
75 
76 
77 
79  template < typename TMap1, typename TMap2, typename TFunctor >
81  {
82  public: // operators
83 
84  void operator()(const TMap1 & map1, const TMap2 & map2, TFunctor f)
85  {
86  typename TMap1::const_iterator i1 = map1.begin();
87  typename TMap2::const_iterator i2 = map2.begin();
88 
89  for(;;)
90  {
91  if (i1->first < i2->first)
92  {
93  if (++i1 == map1.end()) return;
94  }
95  else if (i1->first > i2->first)
96  {
97  if (++i2 == map2.end()) return;
98  }
99  else
100  {
101  //res.insert(res.end(), std::make_pair(i1->first, i1->second * i2->second));
102  //f(i1->first, i1->second, i2->second);
103  f(*i1, *i2);
104  if (++i1 == map1.end()) return;
105  if (++i2 == map2.end()) return;
106  }
107  }
108  }
109 
110  private: // checks
111 
112  typedef typename boost::enable_if<is_map<typename naked_type<TMap1>::type > >::type CheckTMap1isMap;
113  typedef typename boost::enable_if<is_map<typename naked_type<TMap2>::type > >::type CheckTMap2isMap;
114  };
115 
116 
117 
118  template < typename TMap1, typename TMap2, typename TFunctor >
119  //typename boost::enable_if<boost::is_stateless<TFunctor> >::type
120  typename boost::enable_if<boost::is_empty<TFunctor> >::type
121  loop_mapPairs(TMap1 & map1, TMap2 & map2, TFunctor f)
122  {
123  Loop_mapPairs<TMap1, TMap2, TFunctor>()(map1, map2, f);
124  }
125 
126 
127  template < typename TMap1, typename TMap2, typename TFunctor >
128  //typename boost::disable_if<boost::is_stateless<TFunctor> >::type
129  typename boost::disable_if<boost::is_empty<TFunctor> >::type
130  loop_mapPairs(TMap1 & map1, TMap2 & map2, TFunctor & f)
131  {
133  }
134 
135 
137  template < typename TMap1, typename TMap2, typename TFunctor >
139  {
140  public: // operators
141 
142  //TODO: I think it should really use iterator arguments instead. And those iterators probably
143  // should be private data so that no argument passing between functions
144  void operator()(TMap1 & map1, TMap2 & map2, TFunctor f)
145  {
146  typename TMap1::const_iterator i1 = map1.begin();
147  typename TMap2::const_iterator i2 = map2.begin();
148 
149  if (i1 == map1.end()) goto map1over_checkmap2;
150  if (i2 == map2.end()) goto map2over;
151 
152  // NB: not using goto's would me to have additional end checks at each if's. This function is
153  // very low-level thus time critical, so let's stick with goto's.
154  for (;;)
155  {
156  if (i1->first < i2->first)
157  {
158  //res.insert(res.end(), std::make_pair(i1->first, f(i1->second, T())));
159  //f(i1->first, i1->second, T());
160  // TODO: This is probably no good. Imagine that mapped_type is something heavy to allocate.
161  // Probably better to instanciate a default somewhere. Policy here?
162  f(*i1, typename TMap2::mapped_type());
163  if (++i1 == map1.end())
164  //return this->map1over(map2, f);
165  goto map1over;
166  }
167  else if (i1->first > i2->first)
168  {
169  //res.insert(res.end(), std::make_pair(i2->first, f(i2->second, T())));
170  //f(i2->first, i2->second, T());
171  f(typename TMap1::mapped_type(), *i2);
172  if (++i2 == map2.end())
173  //return this->map2over(map1, f);
174  goto map2over;
175  }
176  else
177  {
178  //res.insert(res.end(), std::make_pair(i1->first, f(i1->second, i2->second)));
179  //f(i1->first, i1->second, i2->second);
180  f(*i1, *i2);
181  if (++i1 == map1.end())
182  {
183  ++i2;
184  //return this->map1over_checkmap2(map2, f);
185  goto map1over_checkmap2;
186  }
187  if (++i2 == map2.end())
188  //return this->map2over(map1, f);
189  goto map2over;
190  }
191  }
192 
193  return;
194 
195  map1over_checkmap2:
196  if (i2 == map2.end()) return;
197 
198  map1over:
199  do
200  {
201  f(typename TMap1::mapped_type(), *i2);
202  }
203  while (++i2 != map2.end());
204  return;
205 
206  map2over:
207  do
208  {
209  f(*i1, typename TMap2::mapped_type());
210  }
211  while (++i1 != map1.end());
212  return;
213  }
214 
215  /*
216  private: // functions
217 
218  void map1over_checkmap2(TMap2 & map2, TFunctor f)
219  {
220  if (++i2 == map2.end()) return;
221  this->map1over(map2, f);
222  }
223 
224  void map1over(TMap2 & map2, TFunctor f)
225  {
226  do
227  {
228  f(typename TMap1::mapped_type(), *i2);
229  }
230  while (++i2 != map2.end());
231  }
232 
233  void map2over(TMap1 & map1, TFunctor f)
234  {
235  do
236  {
237  f(*i1, typename TMap2::mapped_type());
238  }
239  while (++i1 != map1.end());
240  }
241  */
242  };
243 
244 
245  template < typename TMap1, typename TMap2, typename TFunctor >
246  //typename boost::enable_if<boost::is_stateless<TFunctor> >::type
247  typename boost::enable_if<boost::is_empty<TFunctor> >::type
248  loop_mapEach(TMap1 & map1, TMap2 & map2, TFunctor f)
249  {
250  Loop_mapEach<TMap1, TMap2, TFunctor>()(map1, map2, f);
251  }
252 
253 
254  template < typename TMap1, typename TMap2, typename TFunctor >
255  //typename boost::disable_if<boost::is_stateless<TFunctor> >::type
256  typename boost::disable_if<boost::is_empty<TFunctor> >::type
257  loop_mapEach(TMap1 & map1, TMap2 & map2, TFunctor & f)
258  {
260  }
261 
262 
263 
264 
265  template < typename TMap1, typename TMap2, typename TFunctor >
266  /*typename boost::enable_if_c<
267  is_map<TMap1>::value && is_map<TMap2>::value
268  >::type*/
270  {
271  public:
272  void operator()(TMap1 &map1, TMap2 &map2, TFunctor f)
273  {
274  typename TMap1::const_iterator i1 = map1.begin();
275  typename TMap2::const_iterator i2 = map2.begin();
276 
277  // NB: not using goto's would me to have additional end checks at each if's. This function is
278  // very low-level thus time critical, so let's stick with goto's.
279  for (;;)
280  {
281  if (i1->first < i2->first)
282  {
283  //res.insert(res.end(), std::make_pair(i1->first, f(i1->second, T())));
284  //f(i1->first, i1->second, T());
285  // TODO: This is probably no good. Imagine that mapped_type is something heavy to allocate.
286  // Probably better to instanciate a default somewhere. Policy here?
287  if (f(*i1, typename TMap2::mapped_type())) return;
288  if (++i1 == map1.end()) goto map1over;
289  }
290  else if (i1->first > i2->first)
291  {
292  //res.insert(res.end(), std::make_pair(i2->first, f(i2->second, T())));
293  //f(i2->first, i2->second, T());
294  f(typename TMap1::mapped_type(), *i2);
295  if (++i2 == map2.end()) goto map2over;
296  }
297  else
298  {
299  //res.insert(res.end(), std::make_pair(i1->first, f(i1->second, i2->second)));
300  //f(i1->first, i1->second, i2->second);
301  f(*i1, *i2);
302  if (++i1 == map1.end()) goto map1over_checkmap2;
303  if (++i2 == map2.end()) goto map2over;
304  }
305  }
306  return;
307 
308  map1over_checkmap2:
309 
310  if (++i2 == map2.end()) return;
311 
312  map1over:
313  do
314  {
315  f(typename TMap1::mapped_type(), *i2);
316  }
317  while (++i2 != map2.end());
318  return;
319 
320  map2over:
321  do
322  {
323  f(*i1, typename TMap2::mapped_type());
324  }
325  while (++i1 != map1.end());
326  return;
327  }
328  };
329 
330 
331  // Actually this should not be made available as soone as type T has operator*
332  // This is precisely because operator* sucks (return value) that this mul
333  // functions are introduced.
334  template < typename T1, typename T2, typename T3 >
335  inline
336  typename boost::enable_if_c<
337  std::numeric_limits<T1>::is_specialized &&
338  std::numeric_limits<T2>::is_specialized
339  >::type
340  sub(T1 x, T2 y, T3& z)
341  {
342  z = x - y;
343  }
344 
345  template < typename T >
346  inline
347  typename boost::enable_if_c<std::numeric_limits<T>::is_specialized>::type
348  mul(T &x, T y)
349  {
350  x *= y;
351  }
352 
353  // Actually this should not be made available as soone as type T has operator*
354  // This is precisely because operator* sucks (return value) that this mul
355  // functions are introduced.
356  template < typename T1, typename T2, typename T3 >
357  inline
358  typename boost::enable_if_c<
359  std::numeric_limits<T1>::is_specialized &&
360  std::numeric_limits<T2>::is_specialized
361  >::type
362  mul(T1 x, T2 y, T3& z)
363  {
364  z = x * y;
365  }
366 
367  template < typename T1, typename T2 >
368  typename boost::enable_if_c<is_container<T1>::value>::type
369  mul(T1 & x, const T2 & y)
370  {
371  loop(x,y,functor::Mul<T1,T2>());
372  }
373 
374  template < typename T1, typename T2, typename T3 >
375  typename boost::enable_if_c<is_container<T1>::value>::type
376  mul(const T1 & x, const T2 & y, T3 & z)
377  {
378  loop(x,y,z,functor::Mul<T1,T2>());
379  }
380 
381  template < typename TContainer >
382  inline void resize(TContainer & c, std::size_t n)
383  {
384  c.resize(n);
385  }
386 
387  template < typename T, std::size_t D >
388  inline void resize(boost::array<T, D>, std::size_t n)
389  {
390  if (D != n)
391  {
392  throw std::length_error("boost::array can't be resized to a different size");
393  }
394  }
395 
396 } // namespace til
397 
398 #endif //_GLOBALTRAITS_H_
Apply a functor to two sparse vectors only where they both have data.
Definition: globalTraits.h:80
Belongs to package Box Do not include directly, include til/Box.h instead.
Definition: Accumulator.h:10
void resize(numeric_array< T, D > &, std::size_t newSize) __attribute__((__deprecated__))
boost::enable_if< boost::is_empty< TFunctor > >::type loop_mapPairs(TMap1 &map1, TMap2 &map2, TFunctor f)
Definition: globalTraits.h:121
numeric_array< T, D > size(const Box< T, D > &box)
Return the size of a box.
Definition: boxTools.h:56
boost::enable_if_c< std::numeric_limits< T1 >::is_specialized &&std::numeric_limits< T2 >::is_specialized >::type sub(T1 x, T2 y, T3 &z)
Definition: basicFunctors.h:32
This file contains forward declarations of classes defined in the TIL library.
void operator()(TMap1 &map1, TMap2 &map2, TFunctor f)
Definition: globalTraits.h:144
std::size_t operator()(const TCollection &c)
Definition: globalTraits.h:52
void operator()(TMap1 &map1, TMap2 &map2, TFunctor f)
Definition: globalTraits.h:272
Apply a functor to a pair of sparse vectors where either one has data.
Definition: globalTraits.h:138
This file contains all the material a library user should need to use template expressions.
Multiplication functor.
Definition: functors.h:293
void loop_cc(const TContainer1 &c1, TContainer2 &res, TBinaryFunctor f)
Definition: globalTraits.h:63
void operator()(const TMap1 &map1, const TMap2 &map2, TFunctor f)
Definition: globalTraits.h:84
boost::enable_if_c< is_container< TContainer >::value &&!is_container< T >::value >::type loop(TContainer &c, T v, TBinaryFunctor f)
Apply a binary functor to a collection and a constant.
Definition: loop.h:32
Collects template tools used for library implementation.
std::size_t result_type
Definition: globalTraits.h:49
boost::enable_if< boost::is_empty< TFunctor > >::type loop_mapEach(TMap1 &map1, TMap2 &map2, TFunctor f)
Definition: globalTraits.h:248
boost::enable_if_c< std::numeric_limits< T1 >::is_specialized &&std::numeric_limits< T2 >::is_specialized >::type mul(T1 x, T2 y, T3 &z)
Definition: basicFunctors.h:43