[ VIGRA Homepage | Function Index | Class Index | Namespaces | File List | Main Page ]

functorexpression.hxx
1 /************************************************************************/
2 /* */
3 /* Copyright 1998-2002 by Ullrich Koethe */
4 /* */
5 /* This file is part of the VIGRA computer vision library. */
6 /* The VIGRA Website is */
7 /* http://hci.iwr.uni-heidelberg.de/vigra/ */
8 /* Please direct questions, bug reports, and contributions to */
9 /* ullrich.koethe@iwr.uni-heidelberg.de or */
10 /* vigra@informatik.uni-hamburg.de */
11 /* */
12 /* Permission is hereby granted, free of charge, to any person */
13 /* obtaining a copy of this software and associated documentation */
14 /* files (the "Software"), to deal in the Software without */
15 /* restriction, including without limitation the rights to use, */
16 /* copy, modify, merge, publish, distribute, sublicense, and/or */
17 /* sell copies of the Software, and to permit persons to whom the */
18 /* Software is furnished to do so, subject to the following */
19 /* conditions: */
20 /* */
21 /* The above copyright notice and this permission notice shall be */
22 /* included in all copies or substantial portions of the */
23 /* Software. */
24 /* */
25 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND */
26 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES */
27 /* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND */
28 /* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT */
29 /* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */
30 /* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */
31 /* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */
32 /* OTHER DEALINGS IN THE SOFTWARE. */
33 /* */
34 /************************************************************************/
35 
36 #ifndef VIGRA_FUNCTOREXPRESSION_HXX
37 #define VIGRA_FUNCTOREXPRESSION_HXX
38 
39 
40 /** \page FunctorExpressions Functor Expressions
41 
42  Simple automatic functor creation by means of expression templates
43  (also known as a "lambda library").
44 
45  <b>\#include</b> <<a href="functorexpression_8hxx-source.html">vigra/functorexpression.hxx</a>><br>
46  Namespace: vigra::functor
47 
48  <b> Motivation</b>
49 
50  Many generic algorithms are made more flexible by means of functors
51  which define part of the algorithms' behavior according to the
52  needs of a specific situation. For example, we can apply an exponential
53  to each pixel by passing a pointer to the <TT>exp</TT> function
54  to <TT>transformImage()</TT>:
55 
56  \code
57  vigra::FImage src(w,h), dest(w,h);
58  ... // fill src
59 
60  vigra::transformImage(srcImageRange(src), destImage(dest), &exp);
61  \endcode
62 
63  However, this only works for simple operations. If we wanted to
64  apply the exponential to a scaled pixel value (i.e. we want to execute
65  <TT>exp(-beta*v)</TT>), we first need to implement a new functor:
66 
67  \code
68  struct Exponential
69  {
70  Exponential(double b)
71  : beta(b)
72  {}
73 
74  template <class PixelType>
75  PixelType operator()(PixelType const& v) const
76  {
77  return exp(-beta*v);
78  }
79 
80  double beta;
81  };
82  \endcode
83 
84  This functor would be used like this:
85 
86  \code
87  double beta = ...;
88  vigra::transformImage(srcImageRange(src), destImage(dest),
89  Exponential(beta));
90  \endcode
91 
92  However, this approach has some disadvantages:
93 
94  <UL>
95 
96  <li> Writing a functor is more work then simply programm the loop
97  directly, i.e. non-generically. Programmers will tend to
98  avoid generic constructs, if they require so much writing.
99  <li> Often, functors are only needed for a single expression.
100  It is not desirable to get into the trouble of introducing
101  and documenting a new class if that class is used only once.
102  <li> Functors cannot be implemented directly at the point of use.
103  Thus, to find out exactly what a functor is doing, one needs
104  to look somewhere else. This complicates use and maintainance
105  ot generic code.
106 
107  </UL>
108 
109  Therefore, it is necessary to provide a means to generate functors on
110  the fly where they are needed. The C++ standard library contains so called
111  "functor combinators" that allow to construct complicated functors from
112  simpler ones. The above problem "apply <TT>exp(-beta*v)</TT> to every pixel"
113  would be solved like this:
114 
115  \code
116  float beta = ...;
117 
118  vigra::transformImage(srcImageRange(src), destImage(dest),
119  std::compose1(std::ptr_fun(exp),
120  std::bind1st(std::multiplies<float>(), -beta)));
121  \endcode
122 
123  I won't go into details on how this works. Suffice it to say that
124  this technique requires a functional programming style that is unfamiliar
125  to many programmers, and thus leads to code that is difficult to
126  understand. Moreover, this technique has some limitations that prevent
127  certain expressions from being implementable this way. Therefore, VIGRA
128  provides a better and simpler means to create functors on the fly.
129 
130  <b> Automatic Functor Creation</b>
131 
132  Automatic functor creation in VIGRA is based on a technique called
133  <a href="http://extreme.indiana.edu/~tveldhui/papers/Expression-Templates/exprtmpl.html">Expression Templates</a>.
134  This means that C++ operators are
135  overloaded so that they don't execute the specified operation directly,
136  but instead produce a functor which will later calculate the result.
137  This technique has the big advantage that the familiar operator notation
138  can be used, while all the flexibility of generic programming is preserved.
139 
140  The above problem "apply <TT>exp(-beta*v)</TT> to every pixel" will be solved
141  like this:
142 
143  \code
144  using namespace vigra::functor;
145 
146  float beta = ...;
147 
148  transformImage(srcImageRange(src), destImage(dest),
149  exp(Param(-beta)*Arg1()));
150  \endcode
151 
152  Here, four expression templates have been used to create the desired
153  functor:
154 
155  <DL>
156 
157  <DT><b><TT>Param(-beta):</TT></b><DD> creates a functor that represents a
158  constant (<TT>-beta</TT> in this case)
159 
160  <DT><b><TT>Arg1():</TT></b><DD> represents the first argument of the expression (i.e.
161  the pixels of image <TT>src</TT> in the example). Likewise, <TT>Arg2()</TT> and
162  <TT>Arg3()</TT> are defined to represent more arguments. These are needed
163  for algorithms that have multiple input images, such as
164  \ref combineTwoImages() and \ref combineThreeImages().
165 
166  <DT><b>* (multiplication):</b><DD> creates a functor that returns the product of
167  its arguments. Likewise, the other C++ operators (i.e.
168  <TT>+, -, *, /, %, ==, !=, <, <=, >, >=, &&, ||, &, |, ^, !, ~</TT>)
169  are overloaded.
170 
171  <DT><b><TT>exp():</TT></b><DD> creates a functor that takes the exponential of its
172  argument. Likewise, the other algebraic functions
173  (i.e. <TT>sq, sqrt, exp, log, log10, sin, asin, cos, acos, tan,
174  atan, abs, floor, ceil, pow, atan2, fmod, min, max</TT>)
175  are overloaded.
176 
177  </DL>
178 
179  We will explain additional capabilities of the functor creation mechanism
180  by means of examples.
181 
182  The same argument can be used several times in the expression.
183  For example, to calculate the gradient magnitude from the components
184  of the gradient vector, you may write:
185 
186  \code
187  using namespace vigra::functor;
188 
189  vigra::FImage gradient_x(w,h), gradient_y(w,h), magnitude(w,h);
190  ... // calculate gradient_x and gradient_y
191 
192  combineTwoImages(srcImageRange(gradient_x), srcImage(gradient_y),
193  destImage(magnitude),
194  sqrt(Arg1()*Arg1() + Arg2()*Arg2()));
195  \endcode
196 
197  It is also possible to build other functions into functor expressions. Suppose
198  you want to apply <TT>my_complicated_function()</TT> to the sum of two images:
199 
200  \code
201  using namespace vigra::functor;
202 
203  vigra::FImage src1(w,h), src2(w,h), dest(w,h);
204 
205  double my_complicated_function(double);
206 
207  combineTwoImages(srcImageRange(src1), srcImage(src2), destImage(dest),
208  applyFct(&my_complicated_function, Arg1()+Arg2()));
209  \endcode
210 
211  [Note that the arguments of the wrapped function are passed as additional
212  arguments to <TT>applyFct()</TT>]
213 
214  You can implement conditional expression by means of the <TT>ifThenElse()</TT>
215  functor. It corresponds to the "? :" operator that cannot be overloaded.
216  <TT>ifThenElse()</TT> can be used, for example, to threshold an image:
217 
218  \code
219  using namespace vigra::functor;
220 
221  vigra::FImage src(w,h), thresholded(w,h);
222  ...// fill src
223 
224  float threshold = ...;
225 
226  transformImage(srcImageRange(src), destImage(thresholded),
227  ifThenElse(Arg1() < Param(threshold),
228  Param(0.0), // yes branch
229  Param(1.0)) // no branch
230  );
231  \endcode
232 
233  You can use the <TT>Var()</TT> functor to assign values to a variable
234  (<TT>=, +=, -=, *=, /=</TT>&nbsp; are suported). For example, the average gray
235  value of the image is calculated like this:
236 
237  \code
238  using namespace vigra::functor;
239 
240  vigra::FImage src(w,h);
241  ...// fill src
242 
243  double sum = 0.0;
244 
245  inspectImage(srcImageRange(src), Var(sum) += Arg1());
246 
247  std::cout << "Average: " << (sum / (w*h)) << std::endl;
248  \endcode
249 
250  For use in \ref inspectImage() and its relatives, there is a second
251  conditional functor <TT>ifThen()</TT> that emulates the <TT>if()</TT> statement
252  and does not return a value. Using <TT>ifThen()</TT>, we can calculate the size
253  of an image region:
254 
255  \code
256  using namespace vigra::functor;
257 
258  vigra::IImage label_image(w,h);
259  ...// mark regions by labels in label_image
260 
261  int region_label = ...; // the region we want to inspect
262  int size = 0;
263 
264  inspectImage(srcImageRange(label_image),
265  ifThen(Arg1() == Param(region_label),
266  Var(size) += Param(1)));
267 
268  std::cout << "Size of region " << region_label << ": " << size << std::endl;
269  \endcode
270 
271  Often, we want to execute several commands in one functor. This can be done
272  by means of the overloaded <TT>operator,()</TT> ("operator comma"). Expressions
273  seperated by a comma will be executed in succession. We can thus
274  simultaneously find the size and the average gray value of a region:
275 
276  \code
277  using namespace vigra::functor;
278 
279  vigra::FImage src(w,h);
280  vigra::IImage label_image(w,h);
281  ...// segment src and mark regions in label_image
282 
283  int region_label = ...; // the region we want to inspect
284  int size = 0;
285  double sum = 0.0;
286 
287  inspectTwoImages(srcImageRange(src), srcImage(label_image),
288  ifThen(Arg2() == Param(region_label),
289  (
290  Var(size) += Param(1), // the comma operator is invoked
291  Var(sum) += Arg1()
292  )));
293 
294  std::cout << "Region " << region_label << ": size = " << size <<
295  ", average = " << sum / size << std::endl;
296  \endcode
297 
298  [Note that the list of comma-separated expressions must be enclosed in parentheses.]
299 
300  A comma separated list of expressions can also be applied in the context of
301  \ref transformImage() and its cousins. Here, a general rule of C++ applies: The
302  return value of a comma expression is the value of its last subexpression.
303  For example, we can initialize an image so that each pixel contains its
304  address in scan order:
305 
306  \code
307  using namespace vigra::functor;
308 
309  vigra::IImage img(w,h);
310 
311  int count = -1;
312 
313  initImageWithFunctor(destImageRange(img),
314  (
315  Var(count) += Param(1),
316  Var(count) // this is the result of the comma expression
317  ));
318  \endcode
319 
320  Further information about how this mechanism works can be found in
321  <a href="http://hci.iwr.uni-heidelberg.de/vigra/doc/vigra/documents/FunctorFactory.ps">this paper</a> (sorry, slightly out of date).
322 */
323 
324 #ifndef DOXYGEN
325 
326 #if !defined(NO_PARTIAL_TEMPLATE_SPECIALIZATION)
327 
328 #include <cmath>
329 #include "numerictraits.hxx"
330 #include "mathutil.hxx"
331 #include "functortraits.hxx"
332 
333 
334 namespace vigra {
335 
336 namespace functor {
337 
338 /************************************************************/
339 /* */
340 /* unary functor base template */
341 /* */
342 /************************************************************/
343 
344 
345 struct ErrorType;
346 
347 template <class Operation>
348 struct ResultTraits0;
349 
350 template <class Operation, class T1>
351 struct ResultTraits1
352 {
353  typedef T1 Res;
354 };
355 
356 template <class Operation, class T1, class T2>
357 struct ResultTraits2
358 {
359  typedef typename PromoteTraits<T1, T2>::Promote Res;
360 };
361 
362 template <class Operation, class T1, class T2, class T3>
363 struct ResultTraits3
364 {
365  typedef typename PromoteTraits<T1, T2>::Promote P1;
366  typedef typename PromoteTraits<P1, T3>::Promote Res;
367 };
368 
369 template <class EXPR>
370 struct UnaryFunctor
371 {
372  UnaryFunctor(EXPR const & e)
373  : expr_(e)
374  {}
375 
376 // typename ResultTraits0<EXPR>::Res
377  typename ResultTraits0<EXPR>::Res
378  operator()() const
379  {
380  return expr_();
381  }
382 
383  template <class T1>
384  typename ResultTraits1<EXPR, T1>::Res
385  operator()(T1 const & v) const
386  {
387  return expr_(v);
388  }
389 
390  template <class T1, class T2>
391  typename ResultTraits2<EXPR, T1, T2>::Res
392  operator()(T1 const & v1, T2 const & v2) const
393  {
394  return expr_(v1, v2);
395  }
396 
397  template <class T1, class T2, class T3>
398  typename ResultTraits3<EXPR, T1, T2, T3>::Res
399  operator()(T1 const & v1, T2 const & v2, T3 const & v3) const
400  {
401  return expr_(v1, v2, v3);
402  }
403 
404  protected:
405  EXPR expr_;
406 
407  private:
408  UnaryFunctor & operator=(UnaryFunctor const &); // not implemented
409 };
410 
411 template <class Expr>
412 struct ResultTraits0<UnaryFunctor<Expr> >
413 {
414  typedef typename ResultTraits0<Expr>::Res Res;
415 };
416 
417 template <class Expr, class T1>
418 struct ResultTraits1<UnaryFunctor<Expr>, T1>
419 {
420  typedef typename ResultTraits1<Expr, T1>::Res Res;
421 };
422 
423 template <class Expr, class T1, class T2>
424 struct ResultTraits2<UnaryFunctor<Expr>, T1, T2>
425 {
426  typedef typename ResultTraits2<Expr, T1, T2>::Res Res;
427 };
428 
429 template <class Expr, class T1, class T2, class T3>
430 struct ResultTraits3<UnaryFunctor<Expr>, T1, T2, T3>
431 {
432  typedef typename ResultTraits3<Expr, T1, T2, T3>::Res Res;
433 };
434 
435 /************************************************************/
436 /* */
437 /* unary functors for arguments */
438 /* */
439 /************************************************************/
440 
441 struct ArgumentFunctor1;
442 struct ArgumentFunctor2;
443 struct ArgumentFunctor3;
444 
445 template <>
446 struct UnaryFunctor<ArgumentFunctor1>
447 {
448  UnaryFunctor()
449  {}
450 
451  template <class T1>
452  T1 const & operator()(T1 const & v1) const
453  {
454  return v1;
455  }
456 
457  template <class T1, class T2>
458  T1 const & operator()(T1 const & v1, T2 const &) const
459  {
460  return v1;
461  }
462 
463  template <class T1, class T2, class T3>
464  T1 const & operator()(T1 const & v1, T2 const &, T3 const &) const
465  {
466  return v1;
467  }
468 
469  private:
470  UnaryFunctor & operator=(UnaryFunctor const &); // not implemented
471 };
472 
473 template <>
474 struct ResultTraits0<UnaryFunctor<ArgumentFunctor1> >
475 {
476  typedef ErrorType Res;
477 };
478 
479 template <class T1>
480 struct ResultTraits1<UnaryFunctor<ArgumentFunctor1>, T1>
481 {
482  typedef T1 Res;
483 };
484 
485 template <class T1, class T2>
486 struct ResultTraits2<UnaryFunctor<ArgumentFunctor1>, T1, T2>
487 {
488  typedef T1 Res;
489 };
490 
491 template <class T1, class T2, class T3>
492 struct ResultTraits3<UnaryFunctor<ArgumentFunctor1>, T1, T2, T3>
493 {
494  typedef T1 Res;
495 };
496 
497 /************************************************************/
498 
499 inline
500 UnaryFunctor<ArgumentFunctor1>
501 Arg1()
502 {
503  return UnaryFunctor<ArgumentFunctor1>();
504 }
505 
506 /************************************************************/
507 
508 template <>
509 struct UnaryFunctor<ArgumentFunctor2>
510 {
511  UnaryFunctor()
512  {}
513 
514  template <class T1, class T2>
515  T2 const & operator()(T1 const &, T2 const & v2) const
516  {
517  return v2;
518  }
519 
520  template <class T1, class T2, class T3>
521  T2 const & operator()(T1 const &, T2 const & v2, T3 const &) const
522  {
523  return v2;
524  }
525 
526  private:
527  UnaryFunctor & operator=(UnaryFunctor const &); // not implemented
528 };
529 
530 template <>
531 struct ResultTraits0<UnaryFunctor<ArgumentFunctor2> >
532 {
533  typedef ErrorType Res;
534 };
535 
536 template <class T1>
537 struct ResultTraits1<UnaryFunctor<ArgumentFunctor2>, T1>
538 {
539  typedef ErrorType Res;
540 };
541 
542 template <class T1, class T2>
543 struct ResultTraits2<UnaryFunctor<ArgumentFunctor2>, T1, T2>
544 {
545  typedef T2 Res;
546 };
547 
548 template <class T1, class T2, class T3>
549 struct ResultTraits3<UnaryFunctor<ArgumentFunctor2>, T1, T2, T3>
550 {
551  typedef T2 Res;
552 };
553 
554 /************************************************************/
555 
556 inline
557 UnaryFunctor<ArgumentFunctor2>
558 Arg2()
559 {
560  return UnaryFunctor<ArgumentFunctor2>();
561 }
562 
563 /************************************************************/
564 
565 template <>
566 struct UnaryFunctor<ArgumentFunctor3>
567 {
568  UnaryFunctor()
569  {}
570 
571  template <class T1, class T2, class T3>
572  T3 const & operator()(T1 const &, T2 const &, T3 const & v3) const
573  {
574  return v3;
575  }
576 
577  private:
578  UnaryFunctor & operator=(UnaryFunctor const &); // not implemented
579 };
580 
581 template <>
582 struct ResultTraits0<UnaryFunctor<ArgumentFunctor3> >
583 {
584  typedef ErrorType Res;
585 };
586 
587 template <class T1>
588 struct ResultTraits1<UnaryFunctor<ArgumentFunctor3>, T1>
589 {
590  typedef ErrorType Res;
591 };
592 
593 template <class T1, class T2>
594 struct ResultTraits2<UnaryFunctor<ArgumentFunctor3>, T1, T2>
595 {
596  typedef ErrorType Res;
597 };
598 
599 template <class T1, class T2, class T3>
600 struct ResultTraits3<UnaryFunctor<ArgumentFunctor3>, T1, T2, T3>
601 {
602  typedef T3 Res;
603 };
604 
605 /************************************************************/
606 
607 inline
608 UnaryFunctor<ArgumentFunctor3>
609 Arg3()
610 {
611  return UnaryFunctor<ArgumentFunctor3>();
612 }
613 
614 /************************************************************/
615 /* */
616 /* constant parameters */
617 /* */
618 /************************************************************/
619 
620 template <class T>
621 struct ParameterFunctor
622 {
623  ParameterFunctor(T v)
624  : value_(v)
625  {}
626 
627  T const & operator()() const
628  {
629  return value_;
630  }
631 
632  template <class U1>
633  T const & operator()(U1 const &) const
634  {
635  return value_;
636  }
637 
638  template <class U1, class U2>
639  T const & operator()(U1 const &, U2 const &) const
640  {
641  return value_;
642  }
643 
644  template <class U1, class U2, class U3>
645  T const & operator()(U1 const &, U2 const &, U3 const &) const
646  {
647  return value_;
648  }
649 
650  protected:
651  T value_;
652 
653  private:
654  ParameterFunctor & operator=(ParameterFunctor const &); // not implemented
655 };
656 
657 template <class T>
658 struct ResultTraits0<ParameterFunctor<T> >
659 {
660  typedef T Res;
661 };
662 
663 template <class T, class T1>
664 struct ResultTraits1<ParameterFunctor<T>, T1>
665 {
666  typedef T Res;
667 };
668 
669 template <class T, class T1, class T2>
670 struct ResultTraits2<ParameterFunctor<T>, T1, T2>
671 {
672  typedef T Res;
673 };
674 
675 template <class T, class T1, class T2, class T3>
676 struct ResultTraits3<ParameterFunctor<T>, T1, T2, T3>
677 {
678  typedef T Res;
679 };
680 
681 template <class T>
682 inline UnaryFunctor<ParameterFunctor<T> >
683 Param(T const & v)
684 {
685  ParameterFunctor<T> fv(v);
686  return UnaryFunctor<ParameterFunctor<T> >(fv);
687 }
688 
689 /************************************************************/
690 /* */
691 /* unary analyser base template */
692 /* */
693 /************************************************************/
694 
695 
696 template <class EXPR>
697 class UnaryAnalyser
698 {
699  public:
700  UnaryAnalyser(EXPR const & e)
701  : expr_(e)
702  {}
703 
704  void operator()() const
705  {
706  expr_();
707  }
708 
709  template <class T1>
710  void operator()(T1 const & v) const
711  {
712  expr_(v);
713  }
714 
715  template <class T1, class T2>
716  void operator()(T1 const & v1, T2 const & v2) const
717  {
718  expr_(v1, v2);
719  }
720 
721  template <class T1, class T2, class T3>
722  void operator()(T1 const & v1, T2 const & v2, T3 const & v3) const
723  {
724  expr_(v1, v2, v3);
725  }
726  protected:
727 
728  EXPR expr_;
729 
730  private:
731  UnaryAnalyser & operator=(UnaryAnalyser const &); // not implemented
732 };
733 
734 /************************************************************/
735 /* */
736 /* variable assignment */
737 /* */
738 /************************************************************/
739 
740 template <class T>
741 struct VarFunctor;
742 
743 template <class T>
744 struct UnaryFunctor<VarFunctor<T> >;
745 
746 /************************************************************/
747 
748 #define MAKE_ASSIGNMENT_FUNCTOR(name, op) \
749  template <class V, class EXPR> \
750  struct AssignmentFunctor_##name \
751  { \
752  AssignmentFunctor_##name(UnaryFunctor<VarFunctor<V> > v, \
753  UnaryFunctor<EXPR> const & e) \
754  : value_(v.value_), expr_(e) \
755  {} \
756  \
757  V & operator()() const \
758  { \
759  const_cast<V &>(value_) op expr_(); \
760  return const_cast<V &>(value_); \
761  } \
762  \
763  template <class T1> \
764  V & operator()(T1 const & v1) const \
765  { \
766  const_cast<V &>(value_) op expr_(v1); \
767  return const_cast<V &>(value_); \
768  } \
769  \
770  template <class T1, class T2> \
771  V & operator()(T1 const & v1, T2 const & v2) const \
772  { \
773  const_cast<V &>(value_) op expr_(v1, v2); \
774  return const_cast<V &>(value_); \
775  } \
776  \
777  template <class T1, class T2, class T3> \
778  V & operator()(T1 const & v1, T2 const & v2, T3 const & v3) const \
779  { \
780  const_cast<V &>(value_) op expr_(v1, v2, v3); \
781  return const_cast<V &>(value_); \
782  } \
783  \
784  private: \
785  V & value_; \
786  UnaryFunctor<EXPR> expr_; \
787  \
788  AssignmentFunctor_##name & operator=(AssignmentFunctor_##name const &);\
789  };
790 
791 /************************************************************/
792 
793 MAKE_ASSIGNMENT_FUNCTOR(assign, =)
794 MAKE_ASSIGNMENT_FUNCTOR(add, +=)
795 MAKE_ASSIGNMENT_FUNCTOR(subtract, -=)
796 MAKE_ASSIGNMENT_FUNCTOR(multiply, *=)
797 MAKE_ASSIGNMENT_FUNCTOR(divide, /=)
798 
799 #undef MAKE_ASSIGNMENT_FUNCTOR
800 
801 /************************************************************/
802 /* */
803 /* variables */
804 /* */
805 /************************************************************/
806 
807 template <class T>
808 struct UnaryFunctor<VarFunctor<T> >
809 {
810  typedef T Res;
811 
812  UnaryFunctor(T & v)
813  : value_(v)
814  {}
815 
816  template <class EXPR>
817  UnaryAnalyser< AssignmentFunctor_assign<T, UnaryFunctor<EXPR> > >
818  operator=(UnaryFunctor<EXPR> const & e)
819  {
820  AssignmentFunctor_assign<T, UnaryFunctor<EXPR> > va(*this, e);
821  return UnaryAnalyser< AssignmentFunctor_assign<T, UnaryFunctor<EXPR> > >(va);
822  }
823 
824  template <class EXPR>
825  UnaryAnalyser< AssignmentFunctor_add<T, UnaryFunctor<EXPR> > >
826  operator+=(UnaryFunctor<EXPR> const & e)
827  {
828  AssignmentFunctor_add<T, UnaryFunctor<EXPR> > va(*this, e);
829  return UnaryAnalyser< AssignmentFunctor_add<T, UnaryFunctor<EXPR> > >(va);
830  }
831 
832  template <class EXPR>
833  UnaryAnalyser< AssignmentFunctor_subtract<T, UnaryFunctor<EXPR> > >
834  operator-=(UnaryFunctor<EXPR> const & e)
835  {
836  AssignmentFunctor_subtract<T, UnaryFunctor<EXPR> > va(*this, e);
837  return UnaryAnalyser< AssignmentFunctor_subtract<T, UnaryFunctor<EXPR> > >(va);
838  }
839 
840  template <class EXPR>
841  UnaryAnalyser< AssignmentFunctor_multiply<T, UnaryFunctor<EXPR> > >
842  operator*=(UnaryFunctor<EXPR> const & e)
843  {
844  AssignmentFunctor_multiply<T, UnaryFunctor<EXPR> > va(*this, e);
845  return UnaryAnalyser< AssignmentFunctor_multiply<T, UnaryFunctor<EXPR> > >(va);
846  }
847 
848  template <class EXPR>
849  UnaryAnalyser< AssignmentFunctor_divide<T, UnaryFunctor<EXPR> > >
850  operator/=(UnaryFunctor<EXPR> const & e)
851  {
852  AssignmentFunctor_divide<T, UnaryFunctor<EXPR> > va(*this, e);
853  return UnaryAnalyser< AssignmentFunctor_divide<T, UnaryFunctor<EXPR> > >(va);
854  }
855 
856  T const & operator()() const
857  {
858  return value_;
859  }
860 
861  template <class U1>
862  T const & operator()(U1 const &) const
863  {
864  return value_;
865  }
866 
867  template <class U1, class U2>
868  T const & operator()(U1 const &, U2 const &) const
869  {
870  return value_;
871  }
872 
873  template <class U1, class U2, class U3>
874  T const & operator()(U1 const &, U2 const &, U3 const &) const
875  {
876  return value_;
877  }
878 
879  T & value_;
880 
881  private:
882  UnaryFunctor & operator=(UnaryFunctor const &); // not implemented
883 };
884 
885 template <class T>
886 struct ResultTraits0<UnaryFunctor<VarFunctor<T> > >
887 {
888  typedef T Res;
889 };
890 
891 template <class T, class T1>
892 struct ResultTraits1<UnaryFunctor<VarFunctor<T> >, T1>
893 {
894  typedef T Res;
895 };
896 
897 template <class T, class T1, class T2>
898 struct ResultTraits2<UnaryFunctor<VarFunctor<T> >, T1, T2>
899 {
900  typedef T Res;
901 };
902 
903 template <class T, class T1, class T2, class T3>
904 struct ResultTraits3<UnaryFunctor<VarFunctor<T> >, T1, T2, T3>
905 {
906  typedef T Res;
907 };
908 
909 template <class T>
910 inline UnaryFunctor<VarFunctor<T> >
911 Var(T & v)
912 {
913  return UnaryFunctor<VarFunctor<T> >(v);
914 }
915 
916 /************************************************************/
917 /* */
918 /* if then */
919 /* */
920 /************************************************************/
921 
922 template <class EXPR1, class EXPR2>
923 struct IfThenFunctor
924 {
925  typedef void Res;
926 
927  IfThenFunctor(EXPR1 const & e1, EXPR2 const & e2)
928  : expr1_(e1), expr2_(e2)
929  {}
930 
931  void operator()() const
932  {
933  if( expr1_() ) expr2_();
934  }
935 
936  template <class T>
937  void operator()(T const & v1) const
938  {
939  if( expr1_(v1) ) expr2_(v1);
940  }
941 
942  template <class T1, class T2>
943  void operator()(T1 const & v1, T2 const & v2) const
944  {
945  if( expr1_(v1, v2) ) expr2_(v1, v2);
946  }
947 
948  template <class T1, class T2, class T3>
949  void operator()(T1 const & v1, T2 const & v2, T3 const & v3) const
950  {
951  if( expr1_(v1, v2, v3) ) expr2_(v1, v2, v3);
952  }
953 
954  private:
955 
956  EXPR1 expr1_;
957  EXPR2 expr2_;
958 
959  private:
960  IfThenFunctor & operator=(IfThenFunctor const &); // not implemented
961 };
962 
963 template <class EXPR1, class EXPR2>
964 UnaryAnalyser<IfThenFunctor<UnaryFunctor<EXPR1>,
965  UnaryAnalyser<EXPR2> > >
966 ifThen(UnaryFunctor<EXPR1> const & e1,
967  UnaryAnalyser<EXPR2> const & e2)
968 {
969  IfThenFunctor<UnaryFunctor<EXPR1>,
970  UnaryAnalyser<EXPR2> > p(e1, e2);
971  return UnaryAnalyser<IfThenFunctor<UnaryFunctor<EXPR1>,
972  UnaryAnalyser<EXPR2> > >(p);
973 }
974 
975 /************************************************************/
976 /* */
977 /* if then else */
978 /* */
979 /************************************************************/
980 
981 template <class EXPR1, class EXPR2, class EXPR3>
982 struct IfThenElseFunctor;
983 
984 template <class EXPR1, class EXPR2, class EXPR3>
985 struct ResultTraits0<IfThenElseFunctor<EXPR1, EXPR2, EXPR3> >
986 {
987  typedef typename ResultTraits0<EXPR2>::Res R2;
988  typedef typename ResultTraits0<EXPR3>::Res R3;
989  typedef typename PromoteTraits<R2, R3>::Promote Res;
990 };
991 
992 template <class EXPR1, class EXPR2, class EXPR3, class T1>
993 struct ResultTraits1<IfThenElseFunctor<EXPR1, EXPR2, EXPR3>, T1>
994 {
995  typedef typename ResultTraits1<EXPR2, T1>::Res R2;
996  typedef typename ResultTraits1<EXPR3, T1>::Res R3;
997  typedef typename PromoteTraits<R2, R3>::Promote Res;
998 };
999 
1000 template <class EXPR1, class EXPR2, class EXPR3, class T1, class T2>
1001 struct ResultTraits2<IfThenElseFunctor<EXPR1, EXPR2, EXPR3>, T1, T2>
1002 {
1003  typedef typename ResultTraits2<EXPR2, T1, T2>::Res R2;
1004  typedef typename ResultTraits2<EXPR3, T1, T2>::Res R3;
1005  typedef typename PromoteTraits<R2, R3>::Promote Res;
1006 };
1007 
1008 template <class EXPR1, class EXPR2, class EXPR3, class T1, class T2, class T3>
1009 struct ResultTraits3<IfThenElseFunctor<EXPR1, EXPR2, EXPR3>, T1, T2, T3>
1010 {
1011  typedef typename ResultTraits3<EXPR2, T1, T2, T3>::Res R2;
1012  typedef typename ResultTraits3<EXPR3, T1, T2, T3>::Res R3;
1013  typedef typename PromoteTraits<R2, R3>::Promote Res;
1014 };
1015 
1016 template <class EXPR1, class EXPR2, class EXPR3>
1017 struct IfThenElseFunctor
1018 {
1019  IfThenElseFunctor(EXPR1 const & e1, EXPR2 const & e2, EXPR3 const & e3)
1020  : expr1_(e1), expr2_(e2), expr3_(e3)
1021  {}
1022 
1023  typename ResultTraits0<IfThenElseFunctor>::Res
1024  operator()() const
1025  {
1026  if(expr1_())
1027  {
1028  return typename ResultTraits0<IfThenElseFunctor>::Res(expr2_());
1029  }
1030  else
1031  {
1032  return typename ResultTraits0<IfThenElseFunctor>::Res(expr3_());
1033  }
1034  }
1035 
1036  template <class T>
1037  typename ResultTraits1<IfThenElseFunctor, T>::Res
1038  operator()(T const & v1) const
1039  {
1040  if(expr1_(v1))
1041  {
1042  return typename ResultTraits1<IfThenElseFunctor, T>::Res(expr2_(v1));
1043  }
1044  else
1045  {
1046  return typename ResultTraits1<IfThenElseFunctor, T>::Res(expr3_(v1));
1047  }
1048  }
1049 
1050  template <class T1, class T2>
1051  typename ResultTraits2<IfThenElseFunctor, T1, T2>::Res
1052  operator()(T1 const & v1, T2 const & v2) const
1053  {
1054  if(expr1_(v1, v2))
1055  {
1056  return typename ResultTraits2<IfThenElseFunctor, T1, T2>::Res(expr2_(v1, v2));
1057  }
1058  else
1059  {
1060  return typename ResultTraits2<IfThenElseFunctor, T1, T2>::Res(expr3_(v1, v2));
1061  }
1062  }
1063 
1064  template <class T1, class T2, class T3>
1065  typename ResultTraits3<IfThenElseFunctor, T1, T2, T3>::Res
1066  operator()(T1 const & v1, T2 const & v2, T3 const & v3) const
1067  {
1068  if(expr1_(v1, v2, v3))
1069  {
1070  return typename ResultTraits3<IfThenElseFunctor, T1, T2, T3>::Res(expr2_(v1, v2, v3));
1071  }
1072  else
1073  {
1074  return typename ResultTraits3<IfThenElseFunctor, T1, T2, T3>::Res(expr3_(v1, v2, v3));
1075  }
1076  }
1077 
1078  private:
1079 
1080  EXPR1 expr1_;
1081  EXPR2 expr2_;
1082  EXPR3 expr3_;
1083 
1084  IfThenElseFunctor & operator=(IfThenElseFunctor const &); // not implemented
1085 };
1086 
1087 template <class EXPR1, class EXPR2, class EXPR3>
1088 UnaryFunctor<IfThenElseFunctor<UnaryFunctor<EXPR1>,
1089  UnaryFunctor<EXPR2>,
1090  UnaryFunctor<EXPR3> > >
1091 ifThenElse(UnaryFunctor<EXPR1> const & e1,
1092  UnaryFunctor<EXPR2> const & e2,
1093  UnaryFunctor<EXPR3> const & e3)
1094 {
1095  IfThenElseFunctor<UnaryFunctor<EXPR1>,
1096  UnaryFunctor<EXPR2>,
1097  UnaryFunctor<EXPR3> > p(e1, e2, e3);
1098  return UnaryFunctor<IfThenElseFunctor<UnaryFunctor<EXPR1>,
1099  UnaryFunctor<EXPR2>,
1100  UnaryFunctor<EXPR3> > >(p);
1101 }
1102 
1103 /************************************************************/
1104 /* */
1105 /* functors for unary functions */
1106 /* */
1107 /************************************************************/
1108 
1109 #define MAKE_FUNCTOR_UNARY_FUNCTION(function, namespc, traitsClass, traitsValue) \
1110  using ::namespc::function; \
1111  template <class EXPR> \
1112  struct Functor_##function; \
1113  \
1114  template <class EXPR> \
1115  struct ResultTraits0<Functor_##function<EXPR> > \
1116  { \
1117  typedef typename ResultTraits0<EXPR>::Res R1; \
1118  typedef typename traitsClass<R1>::traitsValue Res; \
1119  }; \
1120  \
1121  template <class EXPR, class T1> \
1122  struct ResultTraits1<Functor_##function<EXPR>, T1> \
1123  { \
1124  typedef typename ResultTraits1<EXPR, T1>::Res R1; \
1125  typedef typename traitsClass<R1>::traitsValue Res; \
1126  }; \
1127  \
1128  template <class EXPR, class T1, class T2> \
1129  struct ResultTraits2<Functor_##function<EXPR>, T1, T2> \
1130  { \
1131  typedef typename ResultTraits2<EXPR, T1, T2>::Res R1; \
1132  typedef typename traitsClass<R1>::traitsValue Res; \
1133  }; \
1134  \
1135  template <class EXPR, class T1, class T2, class T3> \
1136  struct ResultTraits3<Functor_##function<EXPR>, T1, T2, T3> \
1137  { \
1138  typedef typename ResultTraits3<EXPR, T1, T2, T3>::Res R1; \
1139  typedef typename traitsClass<R1>::traitsValue Res; \
1140  }; \
1141  \
1142  template <class EXPR> \
1143  struct Functor_##function \
1144  { \
1145  Functor_##function(EXPR const & e) \
1146  : expr_(e) \
1147  {} \
1148  \
1149  typename ResultTraits0<Functor_##function>::Res \
1150  operator()() const \
1151  { \
1152  return function(expr_()); \
1153  } \
1154  \
1155  template <class T> \
1156  typename ResultTraits1<Functor_##function, T>::Res \
1157  operator()(T const & v1) const \
1158  { \
1159  return function(expr_(v1)); \
1160  } \
1161  \
1162  template <class T1, class T2> \
1163  typename ResultTraits2<Functor_##function, T1, T2>::Res \
1164  operator()(T1 const & v1, T2 const & v2) const \
1165  { \
1166  return function(expr_(v1, v2)); \
1167  } \
1168  \
1169  template <class T1, class T2, class T3> \
1170  typename ResultTraits3<Functor_##function, T1, T2, T3>::Res \
1171  operator()(T1 const & v1, T2 const & v2, T3 const & v3) const \
1172  { \
1173  return function(expr_(v1, v2, v3)); \
1174  } \
1175  \
1176  protected: \
1177  \
1178  EXPR expr_; \
1179  \
1180  private: \
1181  Functor_##function & operator=(Functor_##function const &); \
1182  }; \
1183  \
1184  template <class EXPR> \
1185  inline UnaryFunctor<Functor_##function<UnaryFunctor<EXPR> > > \
1186  function(UnaryFunctor<EXPR> const & e) \
1187  { \
1188  Functor_##function<UnaryFunctor<EXPR> > p(e); \
1189  return UnaryFunctor<Functor_##function<UnaryFunctor<EXPR> > >(p); \
1190  }
1191 
1192 /************************************************************/
1193 
1194 MAKE_FUNCTOR_UNARY_FUNCTION(sq, vigra, NumericTraits, RealPromote)
1195 MAKE_FUNCTOR_UNARY_FUNCTION(sqrt, std, NumericTraits, RealPromote)
1196 MAKE_FUNCTOR_UNARY_FUNCTION(exp, std, NumericTraits, RealPromote)
1197 MAKE_FUNCTOR_UNARY_FUNCTION(log, std, NumericTraits, RealPromote)
1198 MAKE_FUNCTOR_UNARY_FUNCTION(log10, std, NumericTraits, RealPromote)
1199 MAKE_FUNCTOR_UNARY_FUNCTION(sin, std, NumericTraits, RealPromote)
1200 MAKE_FUNCTOR_UNARY_FUNCTION(asin, std, NumericTraits, RealPromote)
1201 MAKE_FUNCTOR_UNARY_FUNCTION(cos, std, NumericTraits, RealPromote)
1202 MAKE_FUNCTOR_UNARY_FUNCTION(acos, std, NumericTraits, RealPromote)
1203 MAKE_FUNCTOR_UNARY_FUNCTION(tan, std, NumericTraits, RealPromote)
1204 MAKE_FUNCTOR_UNARY_FUNCTION(atan, std, NumericTraits, RealPromote)
1205 MAKE_FUNCTOR_UNARY_FUNCTION(floor, std, NumericTraits, RealPromote)
1206 MAKE_FUNCTOR_UNARY_FUNCTION(ceil, std, NumericTraits, RealPromote)
1207 MAKE_FUNCTOR_UNARY_FUNCTION(abs, vigra, NumericTraits, RealPromote)
1208 MAKE_FUNCTOR_UNARY_FUNCTION(norm, vigra, NormTraits, NormType)
1209 MAKE_FUNCTOR_UNARY_FUNCTION(squaredNorm, vigra, NormTraits, SquaredNormType)
1210 
1211 #undef MAKE_FUNCTOR_UNARY_FUNCTION
1212 
1213 /************************************************************/
1214 /* */
1215 /* functors for unary operators */
1216 /* */
1217 /************************************************************/
1218 
1219 #define MAKE_FUNCTOR_UNARY_OPERATOR(name, op) \
1220  template <class EXPR> \
1221  struct Functor_##name; \
1222  \
1223  template <class EXPR> \
1224  struct ResultTraits0<Functor_##name<EXPR> > \
1225  { \
1226  typedef typename ResultTraits0<EXPR>::Res Res; \
1227  }; \
1228  \
1229  template <class EXPR, class T1> \
1230  struct ResultTraits1<Functor_##name<EXPR>, T1> \
1231  { \
1232  typedef typename ResultTraits1<EXPR, T1>::Res Res; \
1233  }; \
1234  \
1235  template <class EXPR, class T1, class T2> \
1236  struct ResultTraits2<Functor_##name<EXPR>, T1, T2> \
1237  { \
1238  typedef typename ResultTraits2<EXPR, T1, T2>::Res Res; \
1239  }; \
1240  \
1241  template <class EXPR, class T1, class T2, class T3> \
1242  struct ResultTraits3<Functor_##name<EXPR>, T1, T2, T3> \
1243  { \
1244  typedef typename ResultTraits3<EXPR, T1, T2, T3>::Res Res; \
1245  }; \
1246  \
1247  template <class EXPR> \
1248  struct Functor_##name \
1249  { \
1250  Functor_##name(EXPR const & e) \
1251  : expr_(e) \
1252  {} \
1253  \
1254  typename ResultTraits0<Functor_##name>::Res \
1255  operator()() const \
1256  { \
1257  return op expr_(); \
1258  } \
1259  \
1260  template <class T> \
1261  typename ResultTraits1<Functor_##name, T>::Res \
1262  operator()(T const & v1) const \
1263  { \
1264  return op expr_(v1); \
1265  } \
1266  \
1267  template <class T1, class T2> \
1268  typename ResultTraits2<Functor_##name, T1, T2>::Res \
1269  operator()(T1 const & v1, T2 const & v2) const \
1270  { \
1271  return op expr_(v1, v2); \
1272  } \
1273  \
1274  template <class T1, class T2, class T3> \
1275  typename ResultTraits3<Functor_##name, T1, T2, T3>::Res \
1276  operator()(T1 const & v1, T2 const & v2, T3 const & v3) const \
1277  { \
1278  return op expr_(v1, v2, v3); \
1279  } \
1280  protected: \
1281  \
1282  EXPR expr_; \
1283  \
1284  private: \
1285  Functor_##name & operator=(Functor_##name const &);\
1286  }; \
1287  \
1288  template <class EXPR> \
1289  inline UnaryFunctor<Functor_##name<UnaryFunctor<EXPR> > > \
1290  operator op(UnaryFunctor<EXPR> const & e) \
1291  { \
1292  Functor_##name<UnaryFunctor<EXPR> > p(e); \
1293  return UnaryFunctor<Functor_##name<UnaryFunctor<EXPR> > >(p); \
1294  }
1295 
1296 
1297 /************************************************************/
1298 
1299 MAKE_FUNCTOR_UNARY_OPERATOR(minus, -)
1300 MAKE_FUNCTOR_UNARY_OPERATOR(negate, !)
1301 MAKE_FUNCTOR_UNARY_OPERATOR(bitNegate, ~)
1302 
1303 #undef MAKE_FUNCTOR_UNARY_OPERATOR
1304 
1305 /************************************************************/
1306 /* */
1307 /* functors for binary functions */
1308 /* */
1309 /************************************************************/
1310 
1311 #define MAKE_FUNCTOR_BINARY_FUNCTION(function) \
1312  using std::function; \
1313  template <class EXPR1, class EXPR2> \
1314  struct Functor_##function; \
1315  \
1316  template <class EXPR1, class EXPR2> \
1317  struct ResultTraits0<Functor_##function<EXPR1, EXPR2> > \
1318  { \
1319  typedef typename ResultTraits0<EXPR1>::Res R1; \
1320  typedef typename ResultTraits0<EXPR2>::Res R2; \
1321  typedef typename PromoteTraits<R1, R2>::Promote R3; \
1322  typedef typename NumericTraits<R3>::RealPromote Res; \
1323  }; \
1324  \
1325  template <class EXPR1, class EXPR2, class T1> \
1326  struct ResultTraits1<Functor_##function<EXPR1, EXPR2>, T1> \
1327  { \
1328  typedef typename ResultTraits1<EXPR1, T1>::Res R1; \
1329  typedef typename ResultTraits1<EXPR2, T1>::Res R2; \
1330  typedef typename PromoteTraits<R1, R2>::Promote R3; \
1331  typedef typename NumericTraits<R3>::RealPromote Res; \
1332  }; \
1333  \
1334  template <class EXPR1, class EXPR2, class T1, class T2> \
1335  struct ResultTraits2<Functor_##function<EXPR1, EXPR2>, T1, T2> \
1336  { \
1337  typedef typename ResultTraits2<EXPR1, T1, T2>::Res R1; \
1338  typedef typename ResultTraits2<EXPR2, T1, T2>::Res R2; \
1339  typedef typename PromoteTraits<R1, R2>::Promote R3; \
1340  typedef typename NumericTraits<R3>::RealPromote Res; \
1341  }; \
1342  \
1343  template <class EXPR1, class EXPR2, class T1, class T2, class T3> \
1344  struct ResultTraits3<Functor_##function<EXPR1, EXPR2>, T1, T2, T3> \
1345  { \
1346  typedef typename ResultTraits3<EXPR1, T1, T2, T3>::Res R1; \
1347  typedef typename ResultTraits3<EXPR2, T1, T2, T3>::Res R2; \
1348  typedef typename PromoteTraits<R1, R2>::Promote R3; \
1349  typedef typename NumericTraits<R3>::RealPromote Res; \
1350  }; \
1351  \
1352  template <class EXPR1, class EXPR2> \
1353  struct Functor_##function \
1354  { \
1355  Functor_##function(EXPR1 const & e1, EXPR2 const & e2) \
1356  : expr1_(e1), expr2_(e2) \
1357  {} \
1358  \
1359  typename ResultTraits0<Functor_##function>::Res \
1360  operator()() const \
1361  { \
1362  return function(expr1_(), expr2_()); \
1363  } \
1364  \
1365  template <class T> \
1366  typename ResultTraits1<Functor_##function, T>::Res \
1367  operator()(T const & v1) const \
1368  { \
1369  return function(expr1_(v1), expr2_(v1)); \
1370  } \
1371  \
1372  template <class T1, class T2> \
1373  typename ResultTraits2<Functor_##function, T1, T2>::Res \
1374  operator()(T1 const & v1, T2 const & v2) const \
1375  { \
1376  return function(expr1_(v1, v2), expr2_(v1, v2)); \
1377  } \
1378  \
1379  template <class T1, class T2, class T3> \
1380  typename ResultTraits3<Functor_##function, T1, T2, T3>::Res \
1381  operator()(T1 const & v1, T2 const & v2, T3 const & v3) const \
1382  { \
1383  return function(expr1_(v1, v2, v3), expr2_(v1, v2, v3)); \
1384  } \
1385  \
1386  private: \
1387  \
1388  EXPR1 expr1_; \
1389  EXPR2 expr2_; \
1390  \
1391  Functor_##function & operator=(Functor_##function const &); \
1392  }; \
1393  \
1394  template <class EXPR1, class EXPR2> \
1395  inline UnaryFunctor<Functor_##function<UnaryFunctor<EXPR1>, UnaryFunctor<EXPR2> > > \
1396  function(UnaryFunctor<EXPR1> const & e1, UnaryFunctor<EXPR2> const & e2) \
1397  { \
1398  Functor_##function<UnaryFunctor<EXPR1>, UnaryFunctor<EXPR2> > p(e1, e2); \
1399  return UnaryFunctor<Functor_##function<UnaryFunctor<EXPR1>, \
1400  UnaryFunctor<EXPR2> > >(p); \
1401  }
1402 
1403 /************************************************************/
1404 
1405 MAKE_FUNCTOR_BINARY_FUNCTION(pow)
1406 MAKE_FUNCTOR_BINARY_FUNCTION(atan2)
1407 MAKE_FUNCTOR_BINARY_FUNCTION(fmod)
1408 
1409 #undef MAKE_FUNCTOR_BINARY_FUNCTION
1410 
1411 /************************************************************/
1412 
1413 #define MAKE_FUNCTOR_MINMAX(name, op) \
1414  template <class EXPR1, class EXPR2> \
1415  struct Functor_##name; \
1416  \
1417  template <class EXPR1, class EXPR2> \
1418  struct ResultTraits0<Functor_##name<EXPR1, EXPR2> > \
1419  { \
1420  typedef typename ResultTraits0<EXPR1>::Res R1; \
1421  typedef typename ResultTraits0<EXPR2>::Res R2; \
1422  typedef typename PromoteTraits<R1, R2>::Promote Res; \
1423  }; \
1424  \
1425  template <class EXPR1, class EXPR2, class T1> \
1426  struct ResultTraits1<Functor_##name<EXPR1, EXPR2>, T1> \
1427  { \
1428  typedef typename ResultTraits1<EXPR1, T1>::Res R1; \
1429  typedef typename ResultTraits1<EXPR2, T1>::Res R2; \
1430  typedef typename PromoteTraits<R1, R2>::Promote Res; \
1431  }; \
1432  \
1433  template <class EXPR1, class EXPR2, class T1, class T2> \
1434  struct ResultTraits2<Functor_##name<EXPR1, EXPR2>, T1, T2> \
1435  { \
1436  typedef typename ResultTraits2<EXPR1, T1, T2>::Res R1; \
1437  typedef typename ResultTraits2<EXPR2, T1, T2>::Res R2; \
1438  typedef typename PromoteTraits<R1, R2>::Promote Res; \
1439  }; \
1440  \
1441  template <class EXPR1, class EXPR2, class T1, class T2, class T3> \
1442  struct ResultTraits3<Functor_##name<EXPR1, EXPR2>, T1, T2, T3> \
1443  { \
1444  typedef typename ResultTraits3<EXPR1, T1, T2, T3>::Res R1; \
1445  typedef typename ResultTraits3<EXPR2, T1, T2, T3>::Res R2; \
1446  typedef typename PromoteTraits<R1, R2>::Promote Res; \
1447  }; \
1448  \
1449  template <class EXPR1, class EXPR2> \
1450  struct Functor_##name \
1451  { \
1452  Functor_##name(EXPR1 const & e1, EXPR2 const & e2) \
1453  : expr1_(e1), expr2_(e2) \
1454  {} \
1455  \
1456  typename ResultTraits0<Functor_##name>::Res \
1457  operator()() const \
1458  { \
1459  typename \
1460  ResultTraits0<Functor_##name<EXPR1, EXPR2> >::R1 r1(expr1_()); \
1461  typename \
1462  ResultTraits0<Functor_##name<EXPR1, EXPR2> >::R2 r2(expr2_()); \
1463  return (r1 op r2) ? r1 : r2; \
1464  } \
1465  \
1466  template <class T> \
1467  typename ResultTraits1<Functor_##name, T>::Res \
1468  operator()(T const & v1) const \
1469  { \
1470  typename \
1471  ResultTraits1<Functor_##name<EXPR1, EXPR2>, T>::R1 r1(expr1_(v1)); \
1472  typename \
1473  ResultTraits1<Functor_##name<EXPR1, EXPR2>, T>::R2 r2(expr2_(v1)); \
1474  return (r1 op r2) ? r1 : r2; \
1475  } \
1476  \
1477  template <class T1, class T2> \
1478  typename ResultTraits2<Functor_##name, T1, T2>::Res \
1479  operator()(T1 const & v1, T2 const & v2) const \
1480  { \
1481  typename \
1482  ResultTraits2<Functor_##name<EXPR1, EXPR2>, T1, T2>::R1 r1(expr1_(v1, v2)); \
1483  typename \
1484  ResultTraits2<Functor_##name<EXPR1, EXPR2>, T1, T2>::R2 r2(expr2_(v1, v2)); \
1485  return (r1 op r2) ? r1 : r2; \
1486  } \
1487  \
1488  template <class T1, class T2, class T3> \
1489  typename ResultTraits3<Functor_##name, T1, T2, T3>::Res \
1490  operator()(T1 const & v1, T2 const & v2, T3 const & v3) const \
1491  { \
1492  typename \
1493  ResultTraits3<Functor_##name<EXPR1, EXPR2>, T1, T2, T3>::R1 r1(expr1_(v1, v2, v3)); \
1494  typename \
1495  ResultTraits3<Functor_##name<EXPR1, EXPR2>, T1, T2, T3>::R2 r2(expr2_(v1, v2, v3)); \
1496  return (r1 op r2) ? r1 : r2; \
1497  } \
1498  \
1499  private: \
1500  \
1501  EXPR1 expr1_; \
1502  EXPR2 expr2_; \
1503  \
1504  Functor_##name & operator=(Functor_##name const &); \
1505  }; \
1506  \
1507  template <class EXPR1, class EXPR2> \
1508  inline UnaryFunctor<Functor_##name<UnaryFunctor<EXPR1>, UnaryFunctor<EXPR2> > > \
1509  name(UnaryFunctor<EXPR1> const & e1, UnaryFunctor<EXPR2> const & e2) \
1510  { \
1511  Functor_##name<UnaryFunctor<EXPR1>, UnaryFunctor<EXPR2> > p(e1, e2); \
1512  return UnaryFunctor<Functor_##name<UnaryFunctor<EXPR1>, \
1513  UnaryFunctor<EXPR2> > >(p); \
1514  }
1515 
1516 MAKE_FUNCTOR_MINMAX(min, <)
1517 MAKE_FUNCTOR_MINMAX(max, >)
1518 
1519 #undef MAKE_FUNCTOR_MINMAX
1520 
1521 /************************************************************/
1522 /* */
1523 /* functors for binary operators */
1524 /* */
1525 /************************************************************/
1526 
1527 #define MAKE_FUNCTOR_BINARY_OPERATOR(name, op) \
1528  template <class EXPR1, class EXPR2> \
1529  struct Functor_##name; \
1530  \
1531  template <class EXPR1, class EXPR2> \
1532  struct ResultTraits0<Functor_##name<EXPR1, EXPR2> > \
1533  { \
1534  typedef typename ResultTraits0<EXPR1>::Res R1; \
1535  typedef typename ResultTraits0<EXPR2>::Res R2; \
1536  typedef typename PromoteTraits<R1, R2>::Promote Res; \
1537  }; \
1538  \
1539  template <class EXPR1, class EXPR2, class T1> \
1540  struct ResultTraits1<Functor_##name<EXPR1, EXPR2>, T1> \
1541  { \
1542  typedef typename ResultTraits1<EXPR1, T1>::Res R1; \
1543  typedef typename ResultTraits1<EXPR2, T1>::Res R2; \
1544  typedef typename PromoteTraits<R1, R2>::Promote Res; \
1545  }; \
1546  \
1547  template <class EXPR1, class EXPR2, class T1, class T2> \
1548  struct ResultTraits2<Functor_##name<EXPR1, EXPR2>, T1, T2> \
1549  { \
1550  typedef typename ResultTraits2<EXPR1, T1, T2>::Res R1; \
1551  typedef typename ResultTraits2<EXPR2, T1, T2>::Res R2; \
1552  typedef typename PromoteTraits<R1, R2>::Promote Res; \
1553  }; \
1554  \
1555  template <class EXPR1, class EXPR2, class T1, class T2, class T3> \
1556  struct ResultTraits3<Functor_##name<EXPR1, EXPR2>, T1, T2, T3> \
1557  { \
1558  typedef typename ResultTraits3<EXPR1, T1, T2, T3>::Res R1; \
1559  typedef typename ResultTraits3<EXPR2, T1, T2, T3>::Res R2; \
1560  typedef typename PromoteTraits<R1, R2>::Promote Res; \
1561  }; \
1562  \
1563  template <class EXPR1, class EXPR2> \
1564  struct Functor_##name \
1565  { \
1566  Functor_##name(EXPR1 const & e1, EXPR2 const & e2) \
1567  : expr1_(e1), expr2_(e2) \
1568  {} \
1569  \
1570  typename ResultTraits0<Functor_##name>::Res \
1571  operator()() const \
1572  { \
1573  return expr1_() op expr2_(); \
1574  } \
1575  \
1576  template <class T> \
1577  typename ResultTraits1<Functor_##name, T>::Res \
1578  operator()(T const & v1) const \
1579  { \
1580  return expr1_(v1) op expr2_(v1); \
1581  } \
1582  \
1583  template <class T1, class T2> \
1584  typename ResultTraits2<Functor_##name, T1, T2>::Res \
1585  operator()(T1 const & v1, T2 const & v2) const \
1586  { \
1587  return expr1_(v1, v2) op expr2_(v1, v2); \
1588  } \
1589  \
1590  template <class T1, class T2, class T3> \
1591  typename ResultTraits3<Functor_##name, T1, T2, T3>::Res \
1592  operator()(T1 const & v1, T2 const & v2, T3 const & v3) const \
1593  { \
1594  return expr1_(v1, v2, v3) op expr2_(v1, v2, v3); \
1595  } \
1596  \
1597  private: \
1598  \
1599  EXPR1 expr1_; \
1600  EXPR2 expr2_; \
1601  \
1602  Functor_##name & operator=(Functor_##name const &); \
1603  }; \
1604  \
1605  template <class EXPR1, class EXPR2> \
1606  inline UnaryFunctor<Functor_##name<UnaryFunctor<EXPR1>, UnaryFunctor<EXPR2> > > \
1607  operator op(UnaryFunctor<EXPR1> const & e1, UnaryFunctor<EXPR2> const & e2) \
1608  { \
1609  Functor_##name<UnaryFunctor<EXPR1>, UnaryFunctor<EXPR2> > p(e1, e2); \
1610  return UnaryFunctor<Functor_##name<UnaryFunctor<EXPR1>, \
1611  UnaryFunctor<EXPR2> > >(p); \
1612  }
1613 
1614 /************************************************************/
1615 
1616 MAKE_FUNCTOR_BINARY_OPERATOR(add, +)
1617 MAKE_FUNCTOR_BINARY_OPERATOR(subtract, -)
1618 MAKE_FUNCTOR_BINARY_OPERATOR(multiply, *)
1619 MAKE_FUNCTOR_BINARY_OPERATOR(divide, /)
1620 MAKE_FUNCTOR_BINARY_OPERATOR(modulo, %)
1621 MAKE_FUNCTOR_BINARY_OPERATOR(bitAnd, &)
1622 MAKE_FUNCTOR_BINARY_OPERATOR(bitOr, |)
1623 MAKE_FUNCTOR_BINARY_OPERATOR(bitXor, ^)
1624 
1625 #undef MAKE_FUNCTOR_BINARY_OPERATOR
1626 
1627 /************************************************************/
1628 
1629 #define MAKE_FUNCTOR_BINARY_OPERATOR_BOOL(name, op) \
1630  template <class EXPR1, class EXPR2> \
1631  struct Functor_##name; \
1632  \
1633  template <class EXPR1, class EXPR2> \
1634  struct ResultTraits0<Functor_##name<EXPR1, EXPR2> > \
1635  { \
1636  typedef bool Res; \
1637  }; \
1638  \
1639  template <class EXPR1, class EXPR2, class T1> \
1640  struct ResultTraits1<Functor_##name<EXPR1, EXPR2>, T1> \
1641  { \
1642  typedef bool Res; \
1643  }; \
1644  \
1645  template <class EXPR1, class EXPR2, class T1, class T2> \
1646  struct ResultTraits2<Functor_##name<EXPR1, EXPR2>, T1, T2> \
1647  { \
1648  typedef bool Res; \
1649  }; \
1650  \
1651  template <class EXPR1, class EXPR2, class T1, class T2, class T3> \
1652  struct ResultTraits3<Functor_##name<EXPR1, EXPR2>, T1, T2, T3> \
1653  { \
1654  typedef bool Res; \
1655  }; \
1656  \
1657  template <class EXPR1, class EXPR2> \
1658  struct Functor_##name \
1659  { \
1660  Functor_##name(EXPR1 const & e1, EXPR2 const & e2) \
1661  : expr1_(e1), expr2_(e2) \
1662  {} \
1663  \
1664  bool operator()() const \
1665  { \
1666  return expr1_() op expr2_(); \
1667  } \
1668  \
1669  template <class T> \
1670  bool operator()(T const & v1) const \
1671  { \
1672  return expr1_(v1) op expr2_(v1); \
1673  } \
1674  \
1675  template <class T1, class T2> \
1676  bool operator()(T1 const & v1, T2 const & v2) const \
1677  { \
1678  return expr1_(v1, v2) op expr2_(v1, v2); \
1679  } \
1680  \
1681  template <class T1, class T2, class T3> \
1682  bool operator()(T1 const & v1, T2 const & v2, T3 const & v3) const \
1683  { \
1684  return expr1_(v1, v2, v3) op expr2_(v1, v2, v3); \
1685  } \
1686  \
1687  private: \
1688  \
1689  EXPR1 expr1_; \
1690  EXPR2 expr2_; \
1691  \
1692  Functor_##name & operator=(Functor_##name const &); \
1693  }; \
1694  \
1695  template <class EXPR1, class EXPR2> \
1696  inline UnaryFunctor<Functor_##name<UnaryFunctor<EXPR1>, UnaryFunctor<EXPR2> > > \
1697  operator op(UnaryFunctor<EXPR1> const & e1, UnaryFunctor<EXPR2> const & e2) \
1698  { \
1699  Functor_##name<UnaryFunctor<EXPR1>, UnaryFunctor<EXPR2> > p(e1, e2); \
1700  return UnaryFunctor<Functor_##name<UnaryFunctor<EXPR1>, \
1701  UnaryFunctor<EXPR2> > >(p); \
1702  }
1703 
1704 /************************************************************/
1705 
1706 MAKE_FUNCTOR_BINARY_OPERATOR_BOOL(equals, ==)
1707 MAKE_FUNCTOR_BINARY_OPERATOR_BOOL(differs, !=)
1708 MAKE_FUNCTOR_BINARY_OPERATOR_BOOL(less, <)
1709 MAKE_FUNCTOR_BINARY_OPERATOR_BOOL(lessEqual, <=)
1710 MAKE_FUNCTOR_BINARY_OPERATOR_BOOL(greater, >)
1711 MAKE_FUNCTOR_BINARY_OPERATOR_BOOL(greaterEqual, >=)
1712 MAKE_FUNCTOR_BINARY_OPERATOR_BOOL(and, &&)
1713 MAKE_FUNCTOR_BINARY_OPERATOR_BOOL(or, ||)
1714 
1715 #undef MAKE_FUNCTOR_BINARY_OPERATOR_BOOL
1716 
1717 /************************************************************/
1718 /* */
1719 /* unary apply */
1720 /* */
1721 /************************************************************/
1722 
1723 template <class EXPR, class RES, class ARG>
1724 struct UnaryFctPtrFunctor
1725 {
1726  UnaryFctPtrFunctor(EXPR const & e, RES (*fct)(ARG))
1727  : expr_(e), f_(fct)
1728  {}
1729 
1730  RES operator()() const
1731  {
1732  return f_(expr_());
1733  }
1734 
1735  template <class T>
1736  RES operator()(T const & v1) const
1737  {
1738  return f_(expr_(v1));
1739  }
1740 
1741  template <class T1, class T2>
1742  RES operator()(T1 const & v1, T2 const & v2) const
1743  {
1744  return f_(expr_(v1, v2));
1745  }
1746 
1747  template <class T1, class T2, class T3>
1748  RES operator()(T1 const & v1, T2 const & v2, T3 const & v3) const
1749  {
1750  return f_(expr_(v1, v2, v3));
1751  }
1752  protected:
1753 
1754  EXPR expr_;
1755  RES (*f_)(ARG);
1756 
1757  private:
1758  UnaryFctPtrFunctor & operator=(UnaryFctPtrFunctor const &); // not implemented
1759 };
1760 
1761 template <class EXPR, class RES, class ARG>
1762 struct ResultTraits0<UnaryFctPtrFunctor<EXPR, RES, ARG> >
1763 {
1764  typedef RES Res;
1765 };
1766 
1767 template <class EXPR, class RES, class ARG, class T1>
1768 struct ResultTraits1<UnaryFctPtrFunctor<EXPR, RES, ARG>, T1>
1769 {
1770  typedef RES Res;
1771 };
1772 
1773 template <class EXPR, class RES, class ARG, class T1, class T2>
1774 struct ResultTraits2<UnaryFctPtrFunctor<EXPR, RES, ARG>, T1, T2>
1775 {
1776  typedef RES Res;
1777 };
1778 
1779 template <class EXPR, class RES, class ARG, class T1, class T2, class T3>
1780 struct ResultTraits3<UnaryFctPtrFunctor<EXPR, RES, ARG>, T1, T2, T3>
1781 {
1782  typedef RES Res;
1783 };
1784 
1785 template <class EXPR, class RES, class ARG>
1786 inline UnaryFunctor<UnaryFctPtrFunctor<UnaryFunctor<EXPR>, RES, ARG> >
1787 applyFct(RES (*f)(ARG), UnaryFunctor<EXPR> const & e)
1788 {
1789  UnaryFctPtrFunctor<UnaryFunctor<EXPR>, RES, ARG> p(e, f);
1790  return UnaryFunctor<UnaryFctPtrFunctor<UnaryFunctor<EXPR>, RES, ARG> >(p);
1791 }
1792 
1793 /************************************************************/
1794 /* */
1795 /* binary apply */
1796 /* */
1797 /************************************************************/
1798 
1799 template <class EXPR1, class EXPR2, class RES, class ARG1, class ARG2>
1800 struct BinaryFctPtrFunctor
1801 {
1802  BinaryFctPtrFunctor(EXPR1 const & e1, EXPR2 const & e2,
1803  RES (*f)(ARG1, ARG2))
1804  : expr1_(e1), expr2_(e2), f_(f)
1805  {}
1806 
1807  RES operator()() const
1808  {
1809  return f_(expr1_(), expr2_());
1810  }
1811 
1812  template <class T>
1813  RES operator()(T const & v1) const
1814  {
1815  return f_(expr1_(v1), expr2_(v1));
1816  }
1817 
1818  template <class T1, class T2>
1819  RES operator()(T1 const & v1, T2 const & v2) const
1820  {
1821  return f_(expr1_(v1, v2), expr2_(v1, v2));
1822  }
1823 
1824  template <class T1, class T2, class T3>
1825  RES operator()(T1 const & v1, T2 const & v2, T3 const & v3) const
1826  {
1827  return f_(expr1_(v1, v2, v3), expr2_(v1, v2, v3));
1828  }
1829 
1830  protected:
1831 
1832  EXPR1 expr1_;
1833  EXPR2 expr2_;
1834  RES (*f_)(ARG1, ARG2);
1835 
1836  private:
1837  BinaryFctPtrFunctor & operator=(BinaryFctPtrFunctor const &); // not implemented
1838 };
1839 
1840 template <class EXPR1, class EXPR2, class RES, class ARG1, class ARG2>
1841 struct ResultTraits0<BinaryFctPtrFunctor<EXPR1, EXPR2, RES, ARG1, ARG2> >
1842 {
1843  typedef RES Res;
1844 };
1845 
1846 template <class EXPR1, class EXPR2, class RES, class ARG1, class ARG2,
1847  class T1>
1848 struct ResultTraits1<BinaryFctPtrFunctor<EXPR1, EXPR2, RES, ARG1, ARG2>, T1>
1849 {
1850  typedef RES Res;
1851 };
1852 
1853 template <class EXPR1, class EXPR2, class RES, class ARG1, class ARG2,
1854  class T1, class T2>
1855 struct ResultTraits2<BinaryFctPtrFunctor<EXPR1, EXPR2, RES, ARG1, ARG2>, T1, T2>
1856 {
1857  typedef RES Res;
1858 };
1859 
1860 template <class EXPR1, class EXPR2, class RES, class ARG1, class ARG2,
1861  class T1, class T2, class T3>
1862 struct ResultTraits3<BinaryFctPtrFunctor<EXPR1, EXPR2, RES, ARG1, ARG2>, T1, T2, T3>
1863 {
1864  typedef RES Res;
1865 };
1866 
1867 template <class EXPR1, class EXPR2, class RES, class ARG1, class ARG2>
1868 inline UnaryFunctor<BinaryFctPtrFunctor<UnaryFunctor<EXPR1>,
1869  UnaryFunctor<EXPR2>,
1870  RES, ARG1, ARG2> >
1871 applyFct(RES (*f)(ARG1, ARG2), UnaryFunctor<EXPR1> const & e1,
1872  UnaryFunctor<EXPR2> const & e2)
1873 {
1874  BinaryFctPtrFunctor<UnaryFunctor<EXPR1>,
1875  UnaryFunctor<EXPR2>,
1876  RES, ARG1, ARG2> p(e1, e2, f);
1877  return UnaryFunctor<BinaryFctPtrFunctor<UnaryFunctor<EXPR1>,
1878  UnaryFunctor<EXPR2>,
1879  RES, ARG1, ARG2> >(p);
1880 }
1881 
1882 /************************************************************/
1883 /* */
1884 /* comma operator */
1885 /* */
1886 /************************************************************/
1887 
1888 template <class EXPR1, class EXPR2>
1889 struct CommaFunctor
1890 {
1891  CommaFunctor(EXPR1 const & e1, EXPR2 const & e2)
1892  : expr1_(e1), expr2_(e2)
1893  {}
1894 
1895  typename ResultTraits0<EXPR2>::Res
1896  operator()() const
1897  {
1898  expr1_();
1899  return expr2_();
1900  }
1901 
1902  template <class T>
1903  typename ResultTraits1<EXPR2, T>::Res
1904  operator()(T const & v1) const
1905  {
1906  expr1_(v1);
1907  return expr2_(v1);
1908  }
1909 
1910  template <class T1, class T2>
1911  typename ResultTraits2<EXPR2, T1, T2>::Res
1912  operator()(T1 const & v1, T2 const & v2) const
1913  {
1914  expr1_(v1, v2);
1915  return expr2_(v1, v2);
1916  }
1917 
1918  template <class T1, class T2, class T3>
1919  typename ResultTraits3<EXPR2, T1, T2, T3>::Res
1920  operator()(T1 const & v1, T2 const & v2, T3 const & v3) const
1921  {
1922  expr1_(v1, v2, v3);
1923  return expr2_(v1, v2, v3);
1924  }
1925 
1926  protected:
1927 
1928  EXPR1 expr1_;
1929  EXPR2 expr2_;
1930 
1931  private:
1932  CommaFunctor & operator=(CommaFunctor const &); // not implemented
1933 };
1934 
1935 template <class Expr1, class Expr2>
1936 struct ResultTraits0<CommaFunctor<Expr1, Expr2> >
1937 {
1938  typedef typename ResultTraits0<Expr2>::Res Res;
1939 };
1940 
1941 template <class Expr1, class Expr2, class T1>
1942 struct ResultTraits1<CommaFunctor<Expr1, Expr2>, T1>
1943 {
1944  typedef typename ResultTraits1<Expr2, T1>::Res Res;
1945 };
1946 
1947 template <class Expr1, class Expr2, class T1, class T2>
1948 struct ResultTraits2<CommaFunctor<Expr1, Expr2>, T1, T2>
1949 {
1950  typedef typename ResultTraits2<Expr2, T1, T2>::Res Res;
1951 };
1952 
1953 template <class Expr1, class Expr2, class T1, class T2, class T3>
1954 struct ResultTraits3<CommaFunctor<Expr1, Expr2>, T1, T2, T3>
1955 {
1956  typedef typename ResultTraits3<Expr2, T1, T2, T3>::Res Res;
1957 };
1958 
1959 template <class EXPR1, class EXPR2>
1960 inline UnaryFunctor<CommaFunctor<UnaryAnalyser<EXPR1>,
1961  UnaryFunctor<EXPR2> > >
1962 operator,(UnaryAnalyser<EXPR1> const & e1,
1963  UnaryFunctor<EXPR2> const & e2)
1964 {
1965  CommaFunctor<UnaryAnalyser<EXPR1>,
1966  UnaryFunctor<EXPR2> > p(e1, e2);
1967  return UnaryFunctor<CommaFunctor<UnaryAnalyser<EXPR1>,
1968  UnaryFunctor<EXPR2> > >(p);
1969 }
1970 
1971 /************************************************************/
1972 
1973 template <class EXPR1, class EXPR2>
1974 struct CommaAnalyser
1975 {
1976  CommaAnalyser(EXPR1 const & e1, EXPR2 const & e2)
1977  : expr1_(e1), expr2_(e2)
1978  {}
1979 
1980  void operator()() const
1981  {
1982  expr1_();
1983  expr2_();
1984  }
1985 
1986  template <class T>
1987  void operator()(T const & v1) const
1988  {
1989  expr1_(v1);
1990  expr2_(v1);
1991  }
1992 
1993  template <class T1, class T2>
1994  void operator()(T1 const & v1, T2 const & v2) const
1995  {
1996  expr1_(v1, v2);
1997  expr2_(v1, v2);
1998  }
1999 
2000  template <class T1, class T2, class T3>
2001  void operator()(T1 const & v1, T2 const & v2, T3 const & v3) const
2002  {
2003  expr1_(v1, v2, v3);
2004  expr2_(v1, v2, v3);
2005  }
2006 
2007  protected:
2008 
2009  EXPR1 expr1_;
2010  EXPR2 expr2_;
2011 
2012  private:
2013  CommaAnalyser & operator=(CommaAnalyser const &); // not implemented
2014 };
2015 
2016 template <class EXPR1, class EXPR2>
2017 inline UnaryAnalyser<CommaAnalyser<UnaryAnalyser<EXPR1>,
2018  UnaryAnalyser<EXPR2> > >
2019 operator,(UnaryAnalyser<EXPR1> const & e1,
2020  UnaryAnalyser<EXPR2> const & e2)
2021 {
2022  CommaAnalyser<UnaryAnalyser<EXPR1>,
2023  UnaryAnalyser<EXPR2> > p(e1, e2);
2024  return UnaryAnalyser<CommaAnalyser<UnaryAnalyser<EXPR1>,
2025  UnaryAnalyser<EXPR2> > >(p);
2026 }
2027 
2028 } // namespace functor
2029 
2030 #if defined(__GNUC__) && __GNUC__ < 3
2031 using functor::Arg1;
2032 using functor::Arg2;
2033 using functor::Arg3;
2034 using functor::Param;
2035 #endif
2036 
2037 template <class T>
2038 class FunctorTraits<functor::UnaryFunctor<T> >
2039 : public FunctorTraitsBase<functor::UnaryFunctor<T> >
2040 {
2041  public:
2042  typedef VigraTrueType isInitializer;
2043  typedef VigraTrueType isUnaryFunctor;
2044  typedef VigraTrueType isBinaryFunctor;
2045  typedef VigraTrueType isTernaryFunctor;
2046 };
2047 
2048 template <class T>
2049 class FunctorTraits<functor::UnaryAnalyser<T> >
2050 : public FunctorTraitsBase<functor::UnaryAnalyser<T> >
2051 {
2052  public:
2053  typedef VigraTrueType isUnaryAnalyser;
2054  typedef VigraTrueType isBinaryAnalyser;
2055  typedef VigraTrueType isTernaryAnalyser;
2056 };
2057 
2058 
2059 
2060 } // namespace vigra
2061 
2062 #endif /* NO_PARTIAL_TEMPLATE_SPECIALIZATION */
2063 
2064 #endif // DOXYGEN
2065 
2066 #endif /* VIGRA_FUNCTOREXPRESSION_HXX */
2067 
2068 

© Ullrich Köthe (ullrich.koethe@iwr.uni-heidelberg.de)
Heidelberg Collaboratory for Image Processing, University of Heidelberg, Germany

html generated using doxygen and Python
vigra 1.7.1 (Thu Jun 14 2012)