[ 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> <vigra/functorexpression.hxx><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 program 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 maintenance
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 supported). 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  separated 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 typedef UnaryFunctor<ArgumentFunctor1> Identity;
474 
475 template <>
476 struct ResultTraits0<UnaryFunctor<ArgumentFunctor1> >
477 {
478  typedef ErrorType Res;
479 };
480 
481 template <class T1>
482 struct ResultTraits1<UnaryFunctor<ArgumentFunctor1>, T1>
483 {
484  typedef T1 Res;
485 };
486 
487 template <class T1, class T2>
488 struct ResultTraits2<UnaryFunctor<ArgumentFunctor1>, T1, T2>
489 {
490  typedef T1 Res;
491 };
492 
493 template <class T1, class T2, class T3>
494 struct ResultTraits3<UnaryFunctor<ArgumentFunctor1>, T1, T2, T3>
495 {
496  typedef T1 Res;
497 };
498 
499 /************************************************************/
500 
501 inline
502 UnaryFunctor<ArgumentFunctor1>
503 Arg1()
504 {
505  return UnaryFunctor<ArgumentFunctor1>();
506 }
507 
508 /************************************************************/
509 
510 template <>
511 struct UnaryFunctor<ArgumentFunctor2>
512 {
513  UnaryFunctor()
514  {}
515 
516  template <class T1, class T2>
517  T2 const & operator()(T1 const &, T2 const & v2) const
518  {
519  return v2;
520  }
521 
522  template <class T1, class T2, class T3>
523  T2 const & operator()(T1 const &, T2 const & v2, T3 const &) const
524  {
525  return v2;
526  }
527 
528  private:
529  UnaryFunctor & operator=(UnaryFunctor const &); // not implemented
530 };
531 
532 template <>
533 struct ResultTraits0<UnaryFunctor<ArgumentFunctor2> >
534 {
535  typedef ErrorType Res;
536 };
537 
538 template <class T1>
539 struct ResultTraits1<UnaryFunctor<ArgumentFunctor2>, T1>
540 {
541  typedef ErrorType Res;
542 };
543 
544 template <class T1, class T2>
545 struct ResultTraits2<UnaryFunctor<ArgumentFunctor2>, T1, T2>
546 {
547  typedef T2 Res;
548 };
549 
550 template <class T1, class T2, class T3>
551 struct ResultTraits3<UnaryFunctor<ArgumentFunctor2>, T1, T2, T3>
552 {
553  typedef T2 Res;
554 };
555 
556 /************************************************************/
557 
558 inline
559 UnaryFunctor<ArgumentFunctor2>
560 Arg2()
561 {
562  return UnaryFunctor<ArgumentFunctor2>();
563 }
564 
565 /************************************************************/
566 
567 template <>
568 struct UnaryFunctor<ArgumentFunctor3>
569 {
570  UnaryFunctor()
571  {}
572 
573  template <class T1, class T2, class T3>
574  T3 const & operator()(T1 const &, T2 const &, T3 const & v3) const
575  {
576  return v3;
577  }
578 
579  private:
580  UnaryFunctor & operator=(UnaryFunctor const &); // not implemented
581 };
582 
583 template <>
584 struct ResultTraits0<UnaryFunctor<ArgumentFunctor3> >
585 {
586  typedef ErrorType Res;
587 };
588 
589 template <class T1>
590 struct ResultTraits1<UnaryFunctor<ArgumentFunctor3>, T1>
591 {
592  typedef ErrorType Res;
593 };
594 
595 template <class T1, class T2>
596 struct ResultTraits2<UnaryFunctor<ArgumentFunctor3>, T1, T2>
597 {
598  typedef ErrorType Res;
599 };
600 
601 template <class T1, class T2, class T3>
602 struct ResultTraits3<UnaryFunctor<ArgumentFunctor3>, T1, T2, T3>
603 {
604  typedef T3 Res;
605 };
606 
607 /************************************************************/
608 
609 inline
610 UnaryFunctor<ArgumentFunctor3>
611 Arg3()
612 {
613  return UnaryFunctor<ArgumentFunctor3>();
614 }
615 
616 /************************************************************/
617 /* */
618 /* constant parameters */
619 /* */
620 /************************************************************/
621 
622 template <class T>
623 struct ParameterFunctor
624 {
625  ParameterFunctor(T v)
626  : value_(v)
627  {}
628 
629  T const & operator()() const
630  {
631  return value_;
632  }
633 
634  template <class U1>
635  T const & operator()(U1 const &) const
636  {
637  return value_;
638  }
639 
640  template <class U1, class U2>
641  T const & operator()(U1 const &, U2 const &) const
642  {
643  return value_;
644  }
645 
646  template <class U1, class U2, class U3>
647  T const & operator()(U1 const &, U2 const &, U3 const &) const
648  {
649  return value_;
650  }
651 
652  protected:
653  T value_;
654 
655  private:
656  ParameterFunctor & operator=(ParameterFunctor const &); // not implemented
657 };
658 
659 template <class T>
660 struct ResultTraits0<ParameterFunctor<T> >
661 {
662  typedef T Res;
663 };
664 
665 template <class T, class T1>
666 struct ResultTraits1<ParameterFunctor<T>, T1>
667 {
668  typedef T Res;
669 };
670 
671 template <class T, class T1, class T2>
672 struct ResultTraits2<ParameterFunctor<T>, T1, T2>
673 {
674  typedef T Res;
675 };
676 
677 template <class T, class T1, class T2, class T3>
678 struct ResultTraits3<ParameterFunctor<T>, T1, T2, T3>
679 {
680  typedef T Res;
681 };
682 
683 template <class T>
684 inline UnaryFunctor<ParameterFunctor<T> >
685 Param(T const & v)
686 {
687  ParameterFunctor<T> fv(v);
688  return UnaryFunctor<ParameterFunctor<T> >(fv);
689 }
690 
691 /************************************************************/
692 /* */
693 /* unary analyser base template */
694 /* */
695 /************************************************************/
696 
697 
698 template <class EXPR>
699 class UnaryAnalyser
700 {
701  public:
702  UnaryAnalyser(EXPR const & e)
703  : expr_(e)
704  {}
705 
706  void operator()() const
707  {
708  expr_();
709  }
710 
711  template <class T1>
712  void operator()(T1 const & v) const
713  {
714  expr_(v);
715  }
716 
717  template <class T1, class T2>
718  void operator()(T1 const & v1, T2 const & v2) const
719  {
720  expr_(v1, v2);
721  }
722 
723  template <class T1, class T2, class T3>
724  void operator()(T1 const & v1, T2 const & v2, T3 const & v3) const
725  {
726  expr_(v1, v2, v3);
727  }
728  protected:
729 
730  EXPR expr_;
731 
732  private:
733  UnaryAnalyser & operator=(UnaryAnalyser const &); // not implemented
734 };
735 
736 /************************************************************/
737 /* */
738 /* variable assignment */
739 /* */
740 /************************************************************/
741 
742 template <class T>
743 struct VarFunctor;
744 
745 template <class T>
746 struct UnaryFunctor<VarFunctor<T> >;
747 
748 /************************************************************/
749 
750 #define MAKE_ASSIGNMENT_FUNCTOR(name, op) \
751  template <class V, class EXPR> \
752  struct AssignmentFunctor_##name \
753  { \
754  AssignmentFunctor_##name(UnaryFunctor<VarFunctor<V> > v, \
755  UnaryFunctor<EXPR> const & e) \
756  : value_(v.value_), expr_(e) \
757  {} \
758  \
759  V & operator()() const \
760  { \
761  const_cast<V &>(value_) op expr_(); \
762  return const_cast<V &>(value_); \
763  } \
764  \
765  template <class T1> \
766  V & operator()(T1 const & v1) const \
767  { \
768  const_cast<V &>(value_) op expr_(v1); \
769  return const_cast<V &>(value_); \
770  } \
771  \
772  template <class T1, class T2> \
773  V & operator()(T1 const & v1, T2 const & v2) const \
774  { \
775  const_cast<V &>(value_) op expr_(v1, v2); \
776  return const_cast<V &>(value_); \
777  } \
778  \
779  template <class T1, class T2, class T3> \
780  V & operator()(T1 const & v1, T2 const & v2, T3 const & v3) const \
781  { \
782  const_cast<V &>(value_) op expr_(v1, v2, v3); \
783  return const_cast<V &>(value_); \
784  } \
785  \
786  private: \
787  V & value_; \
788  UnaryFunctor<EXPR> expr_; \
789  \
790  AssignmentFunctor_##name & operator=(AssignmentFunctor_##name const &);\
791  };
792 
793 /************************************************************/
794 
795 MAKE_ASSIGNMENT_FUNCTOR(assign, =)
796 MAKE_ASSIGNMENT_FUNCTOR(add, +=)
797 MAKE_ASSIGNMENT_FUNCTOR(subtract, -=)
798 MAKE_ASSIGNMENT_FUNCTOR(multiply, *=)
799 MAKE_ASSIGNMENT_FUNCTOR(divide, /=)
800 
801 #undef MAKE_ASSIGNMENT_FUNCTOR
802 
803 /************************************************************/
804 /* */
805 /* variables */
806 /* */
807 /************************************************************/
808 
809 template <class T>
810 struct UnaryFunctor<VarFunctor<T> >
811 {
812  typedef T Res;
813 
814  UnaryFunctor(T & v)
815  : value_(v)
816  {}
817 
818  template <class EXPR>
819  UnaryAnalyser< AssignmentFunctor_assign<T, UnaryFunctor<EXPR> > >
820  operator=(UnaryFunctor<EXPR> const & e)
821  {
822  AssignmentFunctor_assign<T, UnaryFunctor<EXPR> > va(*this, e);
823  return UnaryAnalyser< AssignmentFunctor_assign<T, UnaryFunctor<EXPR> > >(va);
824  }
825 
826  template <class EXPR>
827  UnaryAnalyser< AssignmentFunctor_add<T, UnaryFunctor<EXPR> > >
828  operator+=(UnaryFunctor<EXPR> const & e)
829  {
830  AssignmentFunctor_add<T, UnaryFunctor<EXPR> > va(*this, e);
831  return UnaryAnalyser< AssignmentFunctor_add<T, UnaryFunctor<EXPR> > >(va);
832  }
833 
834  template <class EXPR>
835  UnaryAnalyser< AssignmentFunctor_subtract<T, UnaryFunctor<EXPR> > >
836  operator-=(UnaryFunctor<EXPR> const & e)
837  {
838  AssignmentFunctor_subtract<T, UnaryFunctor<EXPR> > va(*this, e);
839  return UnaryAnalyser< AssignmentFunctor_subtract<T, UnaryFunctor<EXPR> > >(va);
840  }
841 
842  template <class EXPR>
843  UnaryAnalyser< AssignmentFunctor_multiply<T, UnaryFunctor<EXPR> > >
844  operator*=(UnaryFunctor<EXPR> const & e)
845  {
846  AssignmentFunctor_multiply<T, UnaryFunctor<EXPR> > va(*this, e);
847  return UnaryAnalyser< AssignmentFunctor_multiply<T, UnaryFunctor<EXPR> > >(va);
848  }
849 
850  template <class EXPR>
851  UnaryAnalyser< AssignmentFunctor_divide<T, UnaryFunctor<EXPR> > >
852  operator/=(UnaryFunctor<EXPR> const & e)
853  {
854  AssignmentFunctor_divide<T, UnaryFunctor<EXPR> > va(*this, e);
855  return UnaryAnalyser< AssignmentFunctor_divide<T, UnaryFunctor<EXPR> > >(va);
856  }
857 
858  T const & operator()() const
859  {
860  return value_;
861  }
862 
863  template <class U1>
864  T const & operator()(U1 const &) const
865  {
866  return value_;
867  }
868 
869  template <class U1, class U2>
870  T const & operator()(U1 const &, U2 const &) const
871  {
872  return value_;
873  }
874 
875  template <class U1, class U2, class U3>
876  T const & operator()(U1 const &, U2 const &, U3 const &) const
877  {
878  return value_;
879  }
880 
881  T & value_;
882 
883  private:
884  UnaryFunctor & operator=(UnaryFunctor const &); // not implemented
885 };
886 
887 template <class T>
888 struct ResultTraits0<UnaryFunctor<VarFunctor<T> > >
889 {
890  typedef T Res;
891 };
892 
893 template <class T, class T1>
894 struct ResultTraits1<UnaryFunctor<VarFunctor<T> >, T1>
895 {
896  typedef T Res;
897 };
898 
899 template <class T, class T1, class T2>
900 struct ResultTraits2<UnaryFunctor<VarFunctor<T> >, T1, T2>
901 {
902  typedef T Res;
903 };
904 
905 template <class T, class T1, class T2, class T3>
906 struct ResultTraits3<UnaryFunctor<VarFunctor<T> >, T1, T2, T3>
907 {
908  typedef T Res;
909 };
910 
911 template <class T>
912 inline UnaryFunctor<VarFunctor<T> >
913 Var(T & v)
914 {
915  return UnaryFunctor<VarFunctor<T> >(v);
916 }
917 
918 /************************************************************/
919 /* */
920 /* if then */
921 /* */
922 /************************************************************/
923 
924 template <class EXPR1, class EXPR2>
925 struct IfThenFunctor
926 {
927  typedef void Res;
928 
929  IfThenFunctor(EXPR1 const & e1, EXPR2 const & e2)
930  : expr1_(e1), expr2_(e2)
931  {}
932 
933  void operator()() const
934  {
935  if( expr1_() ) expr2_();
936  }
937 
938  template <class T>
939  void operator()(T const & v1) const
940  {
941  if( expr1_(v1) ) expr2_(v1);
942  }
943 
944  template <class T1, class T2>
945  void operator()(T1 const & v1, T2 const & v2) const
946  {
947  if( expr1_(v1, v2) ) expr2_(v1, v2);
948  }
949 
950  template <class T1, class T2, class T3>
951  void operator()(T1 const & v1, T2 const & v2, T3 const & v3) const
952  {
953  if( expr1_(v1, v2, v3) ) expr2_(v1, v2, v3);
954  }
955 
956  private:
957 
958  EXPR1 expr1_;
959  EXPR2 expr2_;
960 
961  private:
962  IfThenFunctor & operator=(IfThenFunctor const &); // not implemented
963 };
964 
965 template <class EXPR1, class EXPR2>
966 UnaryAnalyser<IfThenFunctor<UnaryFunctor<EXPR1>,
967  UnaryAnalyser<EXPR2> > >
968 ifThen(UnaryFunctor<EXPR1> const & e1,
969  UnaryAnalyser<EXPR2> const & e2)
970 {
971  IfThenFunctor<UnaryFunctor<EXPR1>,
972  UnaryAnalyser<EXPR2> > p(e1, e2);
973  return UnaryAnalyser<IfThenFunctor<UnaryFunctor<EXPR1>,
974  UnaryAnalyser<EXPR2> > >(p);
975 }
976 
977 /************************************************************/
978 /* */
979 /* if then else */
980 /* */
981 /************************************************************/
982 
983 template <class EXPR1, class EXPR2, class EXPR3>
984 struct IfThenElseFunctor;
985 
986 template <class EXPR1, class EXPR2, class EXPR3>
987 struct ResultTraits0<IfThenElseFunctor<EXPR1, EXPR2, EXPR3> >
988 {
989  typedef typename ResultTraits0<EXPR2>::Res R2;
990  typedef typename ResultTraits0<EXPR3>::Res R3;
991  typedef typename PromoteTraits<R2, R3>::Promote Res;
992 };
993 
994 template <class EXPR1, class EXPR2, class EXPR3, class T1>
995 struct ResultTraits1<IfThenElseFunctor<EXPR1, EXPR2, EXPR3>, T1>
996 {
997  typedef typename ResultTraits1<EXPR2, T1>::Res R2;
998  typedef typename ResultTraits1<EXPR3, T1>::Res R3;
999  typedef typename PromoteTraits<R2, R3>::Promote Res;
1000 };
1001 
1002 template <class EXPR1, class EXPR2, class EXPR3, class T1, class T2>
1003 struct ResultTraits2<IfThenElseFunctor<EXPR1, EXPR2, EXPR3>, T1, T2>
1004 {
1005  typedef typename ResultTraits2<EXPR2, T1, T2>::Res R2;
1006  typedef typename ResultTraits2<EXPR3, T1, T2>::Res R3;
1007  typedef typename PromoteTraits<R2, R3>::Promote Res;
1008 };
1009 
1010 template <class EXPR1, class EXPR2, class EXPR3, class T1, class T2, class T3>
1011 struct ResultTraits3<IfThenElseFunctor<EXPR1, EXPR2, EXPR3>, T1, T2, T3>
1012 {
1013  typedef typename ResultTraits3<EXPR2, T1, T2, T3>::Res R2;
1014  typedef typename ResultTraits3<EXPR3, T1, T2, T3>::Res R3;
1015  typedef typename PromoteTraits<R2, R3>::Promote Res;
1016 };
1017 
1018 template <class EXPR1, class EXPR2, class EXPR3>
1019 struct IfThenElseFunctor
1020 {
1021  IfThenElseFunctor(EXPR1 const & e1, EXPR2 const & e2, EXPR3 const & e3)
1022  : expr1_(e1), expr2_(e2), expr3_(e3)
1023  {}
1024 
1025  typename ResultTraits0<IfThenElseFunctor>::Res
1026  operator()() const
1027  {
1028  if(expr1_())
1029  {
1030  return typename ResultTraits0<IfThenElseFunctor>::Res(expr2_());
1031  }
1032  else
1033  {
1034  return typename ResultTraits0<IfThenElseFunctor>::Res(expr3_());
1035  }
1036  }
1037 
1038  template <class T>
1039  typename ResultTraits1<IfThenElseFunctor, T>::Res
1040  operator()(T const & v1) const
1041  {
1042  if(expr1_(v1))
1043  {
1044  return typename ResultTraits1<IfThenElseFunctor, T>::Res(expr2_(v1));
1045  }
1046  else
1047  {
1048  return typename ResultTraits1<IfThenElseFunctor, T>::Res(expr3_(v1));
1049  }
1050  }
1051 
1052  template <class T1, class T2>
1053  typename ResultTraits2<IfThenElseFunctor, T1, T2>::Res
1054  operator()(T1 const & v1, T2 const & v2) const
1055  {
1056  if(expr1_(v1, v2))
1057  {
1058  return typename ResultTraits2<IfThenElseFunctor, T1, T2>::Res(expr2_(v1, v2));
1059  }
1060  else
1061  {
1062  return typename ResultTraits2<IfThenElseFunctor, T1, T2>::Res(expr3_(v1, v2));
1063  }
1064  }
1065 
1066  template <class T1, class T2, class T3>
1067  typename ResultTraits3<IfThenElseFunctor, T1, T2, T3>::Res
1068  operator()(T1 const & v1, T2 const & v2, T3 const & v3) const
1069  {
1070  if(expr1_(v1, v2, v3))
1071  {
1072  return typename ResultTraits3<IfThenElseFunctor, T1, T2, T3>::Res(expr2_(v1, v2, v3));
1073  }
1074  else
1075  {
1076  return typename ResultTraits3<IfThenElseFunctor, T1, T2, T3>::Res(expr3_(v1, v2, v3));
1077  }
1078  }
1079 
1080  private:
1081 
1082  EXPR1 expr1_;
1083  EXPR2 expr2_;
1084  EXPR3 expr3_;
1085 
1086  IfThenElseFunctor & operator=(IfThenElseFunctor const &); // not implemented
1087 };
1088 
1089 template <class EXPR1, class EXPR2, class EXPR3>
1090 UnaryFunctor<IfThenElseFunctor<UnaryFunctor<EXPR1>,
1091  UnaryFunctor<EXPR2>,
1092  UnaryFunctor<EXPR3> > >
1093 ifThenElse(UnaryFunctor<EXPR1> const & e1,
1094  UnaryFunctor<EXPR2> const & e2,
1095  UnaryFunctor<EXPR3> const & e3)
1096 {
1097  IfThenElseFunctor<UnaryFunctor<EXPR1>,
1098  UnaryFunctor<EXPR2>,
1099  UnaryFunctor<EXPR3> > p(e1, e2, e3);
1100  return UnaryFunctor<IfThenElseFunctor<UnaryFunctor<EXPR1>,
1101  UnaryFunctor<EXPR2>,
1102  UnaryFunctor<EXPR3> > >(p);
1103 }
1104 
1105 /************************************************************/
1106 /* */
1107 /* functors for unary functions */
1108 /* */
1109 /************************************************************/
1110 
1111 #define MAKE_FUNCTOR_UNARY_FUNCTION(function, namespc, traitsClass, traitsValue) \
1112  using ::namespc::function; \
1113  template <class EXPR> \
1114  struct Functor_##function; \
1115  \
1116  template <class EXPR> \
1117  struct ResultTraits0<Functor_##function<EXPR> > \
1118  { \
1119  typedef typename ResultTraits0<EXPR>::Res R1; \
1120  typedef typename traitsClass<R1>::traitsValue Res; \
1121  }; \
1122  \
1123  template <class EXPR, class T1> \
1124  struct ResultTraits1<Functor_##function<EXPR>, T1> \
1125  { \
1126  typedef typename ResultTraits1<EXPR, T1>::Res R1; \
1127  typedef typename traitsClass<R1>::traitsValue Res; \
1128  }; \
1129  \
1130  template <class EXPR, class T1, class T2> \
1131  struct ResultTraits2<Functor_##function<EXPR>, T1, T2> \
1132  { \
1133  typedef typename ResultTraits2<EXPR, T1, T2>::Res R1; \
1134  typedef typename traitsClass<R1>::traitsValue Res; \
1135  }; \
1136  \
1137  template <class EXPR, class T1, class T2, class T3> \
1138  struct ResultTraits3<Functor_##function<EXPR>, T1, T2, T3> \
1139  { \
1140  typedef typename ResultTraits3<EXPR, T1, T2, T3>::Res R1; \
1141  typedef typename traitsClass<R1>::traitsValue Res; \
1142  }; \
1143  \
1144  template <class EXPR> \
1145  struct Functor_##function \
1146  { \
1147  Functor_##function(EXPR const & e) \
1148  : expr_(e) \
1149  {} \
1150  \
1151  typename ResultTraits0<Functor_##function>::Res \
1152  operator()() const \
1153  { \
1154  return function(expr_()); \
1155  } \
1156  \
1157  template <class T> \
1158  typename ResultTraits1<Functor_##function, T>::Res \
1159  operator()(T const & v1) const \
1160  { \
1161  return function(expr_(v1)); \
1162  } \
1163  \
1164  template <class T1, class T2> \
1165  typename ResultTraits2<Functor_##function, T1, T2>::Res \
1166  operator()(T1 const & v1, T2 const & v2) const \
1167  { \
1168  return function(expr_(v1, v2)); \
1169  } \
1170  \
1171  template <class T1, class T2, class T3> \
1172  typename ResultTraits3<Functor_##function, T1, T2, T3>::Res \
1173  operator()(T1 const & v1, T2 const & v2, T3 const & v3) const \
1174  { \
1175  return function(expr_(v1, v2, v3)); \
1176  } \
1177  \
1178  protected: \
1179  \
1180  EXPR expr_; \
1181  \
1182  private: \
1183  Functor_##function & operator=(Functor_##function const &); \
1184  }; \
1185  \
1186  template <class EXPR> \
1187  inline UnaryFunctor<Functor_##function<UnaryFunctor<EXPR> > > \
1188  function(UnaryFunctor<EXPR> const & e) \
1189  { \
1190  Functor_##function<UnaryFunctor<EXPR> > p(e); \
1191  return UnaryFunctor<Functor_##function<UnaryFunctor<EXPR> > >(p); \
1192  }
1193 
1194 /************************************************************/
1195 
1196 MAKE_FUNCTOR_UNARY_FUNCTION(sq, vigra, NumericTraits, RealPromote)
1197 MAKE_FUNCTOR_UNARY_FUNCTION(sqrt, std, NumericTraits, RealPromote)
1198 MAKE_FUNCTOR_UNARY_FUNCTION(exp, std, NumericTraits, RealPromote)
1199 MAKE_FUNCTOR_UNARY_FUNCTION(log, std, NumericTraits, RealPromote)
1200 MAKE_FUNCTOR_UNARY_FUNCTION(log10, std, NumericTraits, RealPromote)
1201 MAKE_FUNCTOR_UNARY_FUNCTION(sin, std, NumericTraits, RealPromote)
1202 MAKE_FUNCTOR_UNARY_FUNCTION(asin, std, NumericTraits, RealPromote)
1203 MAKE_FUNCTOR_UNARY_FUNCTION(cos, std, NumericTraits, RealPromote)
1204 MAKE_FUNCTOR_UNARY_FUNCTION(acos, std, NumericTraits, RealPromote)
1205 MAKE_FUNCTOR_UNARY_FUNCTION(tan, std, NumericTraits, RealPromote)
1206 MAKE_FUNCTOR_UNARY_FUNCTION(atan, std, NumericTraits, RealPromote)
1207 MAKE_FUNCTOR_UNARY_FUNCTION(floor, std, NumericTraits, RealPromote)
1208 MAKE_FUNCTOR_UNARY_FUNCTION(ceil, std, NumericTraits, RealPromote)
1209 MAKE_FUNCTOR_UNARY_FUNCTION(abs, vigra, NumericTraits, RealPromote)
1210 MAKE_FUNCTOR_UNARY_FUNCTION(norm, vigra, NormTraits, NormType)
1211 MAKE_FUNCTOR_UNARY_FUNCTION(squaredNorm, vigra, NormTraits, SquaredNormType)
1212 
1213 #undef MAKE_FUNCTOR_UNARY_FUNCTION
1214 
1215 /************************************************************/
1216 /* */
1217 /* functors for unary operators */
1218 /* */
1219 /************************************************************/
1220 
1221 #define MAKE_FUNCTOR_UNARY_OPERATOR(name, op) \
1222  template <class EXPR> \
1223  struct Functor_##name; \
1224  \
1225  template <class EXPR> \
1226  struct ResultTraits0<Functor_##name<EXPR> > \
1227  { \
1228  typedef typename ResultTraits0<EXPR>::Res Res; \
1229  }; \
1230  \
1231  template <class EXPR, class T1> \
1232  struct ResultTraits1<Functor_##name<EXPR>, T1> \
1233  { \
1234  typedef typename ResultTraits1<EXPR, T1>::Res Res; \
1235  }; \
1236  \
1237  template <class EXPR, class T1, class T2> \
1238  struct ResultTraits2<Functor_##name<EXPR>, T1, T2> \
1239  { \
1240  typedef typename ResultTraits2<EXPR, T1, T2>::Res Res; \
1241  }; \
1242  \
1243  template <class EXPR, class T1, class T2, class T3> \
1244  struct ResultTraits3<Functor_##name<EXPR>, T1, T2, T3> \
1245  { \
1246  typedef typename ResultTraits3<EXPR, T1, T2, T3>::Res Res; \
1247  }; \
1248  \
1249  template <class EXPR> \
1250  struct Functor_##name \
1251  { \
1252  Functor_##name(EXPR const & e) \
1253  : expr_(e) \
1254  {} \
1255  \
1256  typename ResultTraits0<Functor_##name>::Res \
1257  operator()() const \
1258  { \
1259  return op expr_(); \
1260  } \
1261  \
1262  template <class T> \
1263  typename ResultTraits1<Functor_##name, T>::Res \
1264  operator()(T const & v1) const \
1265  { \
1266  return op expr_(v1); \
1267  } \
1268  \
1269  template <class T1, class T2> \
1270  typename ResultTraits2<Functor_##name, T1, T2>::Res \
1271  operator()(T1 const & v1, T2 const & v2) const \
1272  { \
1273  return op expr_(v1, v2); \
1274  } \
1275  \
1276  template <class T1, class T2, class T3> \
1277  typename ResultTraits3<Functor_##name, T1, T2, T3>::Res \
1278  operator()(T1 const & v1, T2 const & v2, T3 const & v3) const \
1279  { \
1280  return op expr_(v1, v2, v3); \
1281  } \
1282  protected: \
1283  \
1284  EXPR expr_; \
1285  \
1286  private: \
1287  Functor_##name & operator=(Functor_##name const &);\
1288  }; \
1289  \
1290  template <class EXPR> \
1291  inline UnaryFunctor<Functor_##name<UnaryFunctor<EXPR> > > \
1292  operator op(UnaryFunctor<EXPR> const & e) \
1293  { \
1294  Functor_##name<UnaryFunctor<EXPR> > p(e); \
1295  return UnaryFunctor<Functor_##name<UnaryFunctor<EXPR> > >(p); \
1296  }
1297 
1298 
1299 /************************************************************/
1300 
1301 MAKE_FUNCTOR_UNARY_OPERATOR(minus, -)
1302 MAKE_FUNCTOR_UNARY_OPERATOR(negate, !)
1303 MAKE_FUNCTOR_UNARY_OPERATOR(bitNegate, ~)
1304 
1305 #undef MAKE_FUNCTOR_UNARY_OPERATOR
1306 
1307 /************************************************************/
1308 /* */
1309 /* functors for binary functions */
1310 /* */
1311 /************************************************************/
1312 
1313 #define MAKE_FUNCTOR_BINARY_FUNCTION(function) \
1314  using std::function; \
1315  template <class EXPR1, class EXPR2> \
1316  struct Functor_##function; \
1317  \
1318  template <class EXPR1, class EXPR2> \
1319  struct ResultTraits0<Functor_##function<EXPR1, EXPR2> > \
1320  { \
1321  typedef typename ResultTraits0<EXPR1>::Res R1; \
1322  typedef typename ResultTraits0<EXPR2>::Res R2; \
1323  typedef typename PromoteTraits<R1, R2>::Promote R3; \
1324  typedef typename NumericTraits<R3>::RealPromote Res; \
1325  }; \
1326  \
1327  template <class EXPR1, class EXPR2, class T1> \
1328  struct ResultTraits1<Functor_##function<EXPR1, EXPR2>, T1> \
1329  { \
1330  typedef typename ResultTraits1<EXPR1, T1>::Res R1; \
1331  typedef typename ResultTraits1<EXPR2, T1>::Res R2; \
1332  typedef typename PromoteTraits<R1, R2>::Promote R3; \
1333  typedef typename NumericTraits<R3>::RealPromote Res; \
1334  }; \
1335  \
1336  template <class EXPR1, class EXPR2, class T1, class T2> \
1337  struct ResultTraits2<Functor_##function<EXPR1, EXPR2>, T1, T2> \
1338  { \
1339  typedef typename ResultTraits2<EXPR1, T1, T2>::Res R1; \
1340  typedef typename ResultTraits2<EXPR2, T1, T2>::Res R2; \
1341  typedef typename PromoteTraits<R1, R2>::Promote R3; \
1342  typedef typename NumericTraits<R3>::RealPromote Res; \
1343  }; \
1344  \
1345  template <class EXPR1, class EXPR2, class T1, class T2, class T3> \
1346  struct ResultTraits3<Functor_##function<EXPR1, EXPR2>, T1, T2, T3> \
1347  { \
1348  typedef typename ResultTraits3<EXPR1, T1, T2, T3>::Res R1; \
1349  typedef typename ResultTraits3<EXPR2, T1, T2, T3>::Res R2; \
1350  typedef typename PromoteTraits<R1, R2>::Promote R3; \
1351  typedef typename NumericTraits<R3>::RealPromote Res; \
1352  }; \
1353  \
1354  template <class EXPR1, class EXPR2> \
1355  struct Functor_##function \
1356  { \
1357  Functor_##function(EXPR1 const & e1, EXPR2 const & e2) \
1358  : expr1_(e1), expr2_(e2) \
1359  {} \
1360  \
1361  typename ResultTraits0<Functor_##function>::Res \
1362  operator()() const \
1363  { \
1364  return function(expr1_(), expr2_()); \
1365  } \
1366  \
1367  template <class T> \
1368  typename ResultTraits1<Functor_##function, T>::Res \
1369  operator()(T const & v1) const \
1370  { \
1371  return function(expr1_(v1), expr2_(v1)); \
1372  } \
1373  \
1374  template <class T1, class T2> \
1375  typename ResultTraits2<Functor_##function, T1, T2>::Res \
1376  operator()(T1 const & v1, T2 const & v2) const \
1377  { \
1378  return function(expr1_(v1, v2), expr2_(v1, v2)); \
1379  } \
1380  \
1381  template <class T1, class T2, class T3> \
1382  typename ResultTraits3<Functor_##function, T1, T2, T3>::Res \
1383  operator()(T1 const & v1, T2 const & v2, T3 const & v3) const \
1384  { \
1385  return function(expr1_(v1, v2, v3), expr2_(v1, v2, v3)); \
1386  } \
1387  \
1388  private: \
1389  \
1390  EXPR1 expr1_; \
1391  EXPR2 expr2_; \
1392  \
1393  Functor_##function & operator=(Functor_##function const &); \
1394  }; \
1395  \
1396  template <class EXPR1, class EXPR2> \
1397  inline UnaryFunctor<Functor_##function<UnaryFunctor<EXPR1>, UnaryFunctor<EXPR2> > > \
1398  function(UnaryFunctor<EXPR1> const & e1, UnaryFunctor<EXPR2> const & e2) \
1399  { \
1400  Functor_##function<UnaryFunctor<EXPR1>, UnaryFunctor<EXPR2> > p(e1, e2); \
1401  return UnaryFunctor<Functor_##function<UnaryFunctor<EXPR1>, \
1402  UnaryFunctor<EXPR2> > >(p); \
1403  }
1404 
1405 /************************************************************/
1406 
1407 MAKE_FUNCTOR_BINARY_FUNCTION(pow)
1408 MAKE_FUNCTOR_BINARY_FUNCTION(atan2)
1409 MAKE_FUNCTOR_BINARY_FUNCTION(fmod)
1410 
1411 #undef MAKE_FUNCTOR_BINARY_FUNCTION
1412 
1413 /************************************************************/
1414 
1415 #define MAKE_FUNCTOR_MINMAX(name, op) \
1416  template <class EXPR1, class EXPR2> \
1417  struct Functor_##name; \
1418  \
1419  template <class EXPR1, class EXPR2> \
1420  struct ResultTraits0<Functor_##name<EXPR1, EXPR2> > \
1421  { \
1422  typedef typename ResultTraits0<EXPR1>::Res R1; \
1423  typedef typename ResultTraits0<EXPR2>::Res R2; \
1424  typedef typename PromoteTraits<R1, R2>::Promote Res; \
1425  }; \
1426  \
1427  template <class EXPR1, class EXPR2, class T1> \
1428  struct ResultTraits1<Functor_##name<EXPR1, EXPR2>, T1> \
1429  { \
1430  typedef typename ResultTraits1<EXPR1, T1>::Res R1; \
1431  typedef typename ResultTraits1<EXPR2, T1>::Res R2; \
1432  typedef typename PromoteTraits<R1, R2>::Promote Res; \
1433  }; \
1434  \
1435  template <class EXPR1, class EXPR2, class T1, class T2> \
1436  struct ResultTraits2<Functor_##name<EXPR1, EXPR2>, T1, T2> \
1437  { \
1438  typedef typename ResultTraits2<EXPR1, T1, T2>::Res R1; \
1439  typedef typename ResultTraits2<EXPR2, T1, T2>::Res R2; \
1440  typedef typename PromoteTraits<R1, R2>::Promote Res; \
1441  }; \
1442  \
1443  template <class EXPR1, class EXPR2, class T1, class T2, class T3> \
1444  struct ResultTraits3<Functor_##name<EXPR1, EXPR2>, T1, T2, T3> \
1445  { \
1446  typedef typename ResultTraits3<EXPR1, T1, T2, T3>::Res R1; \
1447  typedef typename ResultTraits3<EXPR2, T1, T2, T3>::Res R2; \
1448  typedef typename PromoteTraits<R1, R2>::Promote Res; \
1449  }; \
1450  \
1451  template <class EXPR1, class EXPR2> \
1452  struct Functor_##name \
1453  { \
1454  Functor_##name(EXPR1 const & e1, EXPR2 const & e2) \
1455  : expr1_(e1), expr2_(e2) \
1456  {} \
1457  \
1458  typename ResultTraits0<Functor_##name>::Res \
1459  operator()() const \
1460  { \
1461  typename \
1462  ResultTraits0<Functor_##name<EXPR1, EXPR2> >::R1 r1(expr1_()); \
1463  typename \
1464  ResultTraits0<Functor_##name<EXPR1, EXPR2> >::R2 r2(expr2_()); \
1465  return (r1 op r2) ? r1 : r2; \
1466  } \
1467  \
1468  template <class T> \
1469  typename ResultTraits1<Functor_##name, T>::Res \
1470  operator()(T const & v1) const \
1471  { \
1472  typename \
1473  ResultTraits1<Functor_##name<EXPR1, EXPR2>, T>::R1 r1(expr1_(v1)); \
1474  typename \
1475  ResultTraits1<Functor_##name<EXPR1, EXPR2>, T>::R2 r2(expr2_(v1)); \
1476  return (r1 op r2) ? r1 : r2; \
1477  } \
1478  \
1479  template <class T1, class T2> \
1480  typename ResultTraits2<Functor_##name, T1, T2>::Res \
1481  operator()(T1 const & v1, T2 const & v2) const \
1482  { \
1483  typename \
1484  ResultTraits2<Functor_##name<EXPR1, EXPR2>, T1, T2>::R1 r1(expr1_(v1, v2)); \
1485  typename \
1486  ResultTraits2<Functor_##name<EXPR1, EXPR2>, T1, T2>::R2 r2(expr2_(v1, v2)); \
1487  return (r1 op r2) ? r1 : r2; \
1488  } \
1489  \
1490  template <class T1, class T2, class T3> \
1491  typename ResultTraits3<Functor_##name, T1, T2, T3>::Res \
1492  operator()(T1 const & v1, T2 const & v2, T3 const & v3) const \
1493  { \
1494  typename \
1495  ResultTraits3<Functor_##name<EXPR1, EXPR2>, T1, T2, T3>::R1 r1(expr1_(v1, v2, v3)); \
1496  typename \
1497  ResultTraits3<Functor_##name<EXPR1, EXPR2>, T1, T2, T3>::R2 r2(expr2_(v1, v2, v3)); \
1498  return (r1 op r2) ? r1 : r2; \
1499  } \
1500  \
1501  private: \
1502  \
1503  EXPR1 expr1_; \
1504  EXPR2 expr2_; \
1505  \
1506  Functor_##name & operator=(Functor_##name const &); \
1507  }; \
1508  \
1509  template <class EXPR1, class EXPR2> \
1510  inline UnaryFunctor<Functor_##name<UnaryFunctor<EXPR1>, UnaryFunctor<EXPR2> > > \
1511  name(UnaryFunctor<EXPR1> const & e1, UnaryFunctor<EXPR2> const & e2) \
1512  { \
1513  Functor_##name<UnaryFunctor<EXPR1>, UnaryFunctor<EXPR2> > p(e1, e2); \
1514  return UnaryFunctor<Functor_##name<UnaryFunctor<EXPR1>, \
1515  UnaryFunctor<EXPR2> > >(p); \
1516  }
1517 
1518 MAKE_FUNCTOR_MINMAX(min, <)
1519 MAKE_FUNCTOR_MINMAX(max, >)
1520 
1521 #undef MAKE_FUNCTOR_MINMAX
1522 
1523 /************************************************************/
1524 /* */
1525 /* functors for binary operators */
1526 /* */
1527 /************************************************************/
1528 
1529 #define MAKE_FUNCTOR_BINARY_OPERATOR(name, op) \
1530  template <class EXPR1, class EXPR2> \
1531  struct Functor_##name; \
1532  \
1533  template <class EXPR1, class EXPR2> \
1534  struct ResultTraits0<Functor_##name<EXPR1, EXPR2> > \
1535  { \
1536  typedef typename ResultTraits0<EXPR1>::Res R1; \
1537  typedef typename ResultTraits0<EXPR2>::Res R2; \
1538  typedef typename PromoteTraits<R1, R2>::Promote Res; \
1539  }; \
1540  \
1541  template <class EXPR1, class EXPR2, class T1> \
1542  struct ResultTraits1<Functor_##name<EXPR1, EXPR2>, T1> \
1543  { \
1544  typedef typename ResultTraits1<EXPR1, T1>::Res R1; \
1545  typedef typename ResultTraits1<EXPR2, T1>::Res R2; \
1546  typedef typename PromoteTraits<R1, R2>::Promote Res; \
1547  }; \
1548  \
1549  template <class EXPR1, class EXPR2, class T1, class T2> \
1550  struct ResultTraits2<Functor_##name<EXPR1, EXPR2>, T1, T2> \
1551  { \
1552  typedef typename ResultTraits2<EXPR1, T1, T2>::Res R1; \
1553  typedef typename ResultTraits2<EXPR2, T1, T2>::Res R2; \
1554  typedef typename PromoteTraits<R1, R2>::Promote Res; \
1555  }; \
1556  \
1557  template <class EXPR1, class EXPR2, class T1, class T2, class T3> \
1558  struct ResultTraits3<Functor_##name<EXPR1, EXPR2>, T1, T2, T3> \
1559  { \
1560  typedef typename ResultTraits3<EXPR1, T1, T2, T3>::Res R1; \
1561  typedef typename ResultTraits3<EXPR2, T1, T2, T3>::Res R2; \
1562  typedef typename PromoteTraits<R1, R2>::Promote Res; \
1563  }; \
1564  \
1565  template <class EXPR1, class EXPR2> \
1566  struct Functor_##name \
1567  { \
1568  Functor_##name(EXPR1 const & e1, EXPR2 const & e2) \
1569  : expr1_(e1), expr2_(e2) \
1570  {} \
1571  \
1572  typename ResultTraits0<Functor_##name>::Res \
1573  operator()() const \
1574  { \
1575  return expr1_() op expr2_(); \
1576  } \
1577  \
1578  template <class T> \
1579  typename ResultTraits1<Functor_##name, T>::Res \
1580  operator()(T const & v1) const \
1581  { \
1582  return expr1_(v1) op expr2_(v1); \
1583  } \
1584  \
1585  template <class T1, class T2> \
1586  typename ResultTraits2<Functor_##name, T1, T2>::Res \
1587  operator()(T1 const & v1, T2 const & v2) const \
1588  { \
1589  return expr1_(v1, v2) op expr2_(v1, v2); \
1590  } \
1591  \
1592  template <class T1, class T2, class T3> \
1593  typename ResultTraits3<Functor_##name, T1, T2, T3>::Res \
1594  operator()(T1 const & v1, T2 const & v2, T3 const & v3) const \
1595  { \
1596  return expr1_(v1, v2, v3) op expr2_(v1, v2, v3); \
1597  } \
1598  \
1599  private: \
1600  \
1601  EXPR1 expr1_; \
1602  EXPR2 expr2_; \
1603  \
1604  Functor_##name & operator=(Functor_##name const &); \
1605  }; \
1606  \
1607  template <class EXPR1, class EXPR2> \
1608  inline UnaryFunctor<Functor_##name<UnaryFunctor<EXPR1>, UnaryFunctor<EXPR2> > > \
1609  operator op(UnaryFunctor<EXPR1> const & e1, UnaryFunctor<EXPR2> const & e2) \
1610  { \
1611  Functor_##name<UnaryFunctor<EXPR1>, UnaryFunctor<EXPR2> > p(e1, e2); \
1612  return UnaryFunctor<Functor_##name<UnaryFunctor<EXPR1>, \
1613  UnaryFunctor<EXPR2> > >(p); \
1614  }
1615 
1616 /************************************************************/
1617 
1618 MAKE_FUNCTOR_BINARY_OPERATOR(add, +)
1619 MAKE_FUNCTOR_BINARY_OPERATOR(subtract, -)
1620 MAKE_FUNCTOR_BINARY_OPERATOR(multiply, *)
1621 MAKE_FUNCTOR_BINARY_OPERATOR(divide, /)
1622 MAKE_FUNCTOR_BINARY_OPERATOR(modulo, %)
1623 MAKE_FUNCTOR_BINARY_OPERATOR(bitAnd, &)
1624 MAKE_FUNCTOR_BINARY_OPERATOR(bitOr, |)
1625 MAKE_FUNCTOR_BINARY_OPERATOR(bitXor, ^)
1626 
1627 #undef MAKE_FUNCTOR_BINARY_OPERATOR
1628 
1629 /************************************************************/
1630 
1631 #define MAKE_FUNCTOR_BINARY_OPERATOR_BOOL(name, op) \
1632  template <class EXPR1, class EXPR2> \
1633  struct Functor_##name; \
1634  \
1635  template <class EXPR1, class EXPR2> \
1636  struct ResultTraits0<Functor_##name<EXPR1, EXPR2> > \
1637  { \
1638  typedef bool Res; \
1639  }; \
1640  \
1641  template <class EXPR1, class EXPR2, class T1> \
1642  struct ResultTraits1<Functor_##name<EXPR1, EXPR2>, T1> \
1643  { \
1644  typedef bool Res; \
1645  }; \
1646  \
1647  template <class EXPR1, class EXPR2, class T1, class T2> \
1648  struct ResultTraits2<Functor_##name<EXPR1, EXPR2>, T1, T2> \
1649  { \
1650  typedef bool Res; \
1651  }; \
1652  \
1653  template <class EXPR1, class EXPR2, class T1, class T2, class T3> \
1654  struct ResultTraits3<Functor_##name<EXPR1, EXPR2>, T1, T2, T3> \
1655  { \
1656  typedef bool Res; \
1657  }; \
1658  \
1659  template <class EXPR1, class EXPR2> \
1660  struct Functor_##name \
1661  { \
1662  Functor_##name(EXPR1 const & e1, EXPR2 const & e2) \
1663  : expr1_(e1), expr2_(e2) \
1664  {} \
1665  \
1666  bool operator()() const \
1667  { \
1668  return expr1_() op expr2_(); \
1669  } \
1670  \
1671  template <class T> \
1672  bool operator()(T const & v1) const \
1673  { \
1674  return expr1_(v1) op expr2_(v1); \
1675  } \
1676  \
1677  template <class T1, class T2> \
1678  bool operator()(T1 const & v1, T2 const & v2) const \
1679  { \
1680  return expr1_(v1, v2) op expr2_(v1, v2); \
1681  } \
1682  \
1683  template <class T1, class T2, class T3> \
1684  bool operator()(T1 const & v1, T2 const & v2, T3 const & v3) const \
1685  { \
1686  return expr1_(v1, v2, v3) op expr2_(v1, v2, v3); \
1687  } \
1688  \
1689  private: \
1690  \
1691  EXPR1 expr1_; \
1692  EXPR2 expr2_; \
1693  \
1694  Functor_##name & operator=(Functor_##name const &); \
1695  }; \
1696  \
1697  template <class EXPR1, class EXPR2> \
1698  inline UnaryFunctor<Functor_##name<UnaryFunctor<EXPR1>, UnaryFunctor<EXPR2> > > \
1699  operator op(UnaryFunctor<EXPR1> const & e1, UnaryFunctor<EXPR2> const & e2) \
1700  { \
1701  Functor_##name<UnaryFunctor<EXPR1>, UnaryFunctor<EXPR2> > p(e1, e2); \
1702  return UnaryFunctor<Functor_##name<UnaryFunctor<EXPR1>, \
1703  UnaryFunctor<EXPR2> > >(p); \
1704  }
1705 
1706 /************************************************************/
1707 
1708 MAKE_FUNCTOR_BINARY_OPERATOR_BOOL(equals, ==)
1709 MAKE_FUNCTOR_BINARY_OPERATOR_BOOL(differs, !=)
1710 MAKE_FUNCTOR_BINARY_OPERATOR_BOOL(less, <)
1711 MAKE_FUNCTOR_BINARY_OPERATOR_BOOL(lessEqual, <=)
1712 MAKE_FUNCTOR_BINARY_OPERATOR_BOOL(greater, >)
1713 MAKE_FUNCTOR_BINARY_OPERATOR_BOOL(greaterEqual, >=)
1714 MAKE_FUNCTOR_BINARY_OPERATOR_BOOL(and, &&)
1715 MAKE_FUNCTOR_BINARY_OPERATOR_BOOL(or, ||)
1716 
1717 #undef MAKE_FUNCTOR_BINARY_OPERATOR_BOOL
1718 
1719 /************************************************************/
1720 /* */
1721 /* unary apply */
1722 /* */
1723 /************************************************************/
1724 
1725 template <class EXPR, class RES, class ARG>
1726 struct UnaryFctPtrFunctor
1727 {
1728  UnaryFctPtrFunctor(EXPR const & e, RES (*fct)(ARG))
1729  : expr_(e), f_(fct)
1730  {}
1731 
1732  RES operator()() const
1733  {
1734  return f_(expr_());
1735  }
1736 
1737  template <class T>
1738  RES operator()(T const & v1) const
1739  {
1740  return f_(expr_(v1));
1741  }
1742 
1743  template <class T1, class T2>
1744  RES operator()(T1 const & v1, T2 const & v2) const
1745  {
1746  return f_(expr_(v1, v2));
1747  }
1748 
1749  template <class T1, class T2, class T3>
1750  RES operator()(T1 const & v1, T2 const & v2, T3 const & v3) const
1751  {
1752  return f_(expr_(v1, v2, v3));
1753  }
1754  protected:
1755 
1756  EXPR expr_;
1757  RES (*f_)(ARG);
1758 
1759  private:
1760  UnaryFctPtrFunctor & operator=(UnaryFctPtrFunctor const &); // not implemented
1761 };
1762 
1763 template <class EXPR, class RES, class ARG>
1764 struct ResultTraits0<UnaryFctPtrFunctor<EXPR, RES, ARG> >
1765 {
1766  typedef RES Res;
1767 };
1768 
1769 template <class EXPR, class RES, class ARG, class T1>
1770 struct ResultTraits1<UnaryFctPtrFunctor<EXPR, RES, ARG>, T1>
1771 {
1772  typedef RES Res;
1773 };
1774 
1775 template <class EXPR, class RES, class ARG, class T1, class T2>
1776 struct ResultTraits2<UnaryFctPtrFunctor<EXPR, RES, ARG>, T1, T2>
1777 {
1778  typedef RES Res;
1779 };
1780 
1781 template <class EXPR, class RES, class ARG, class T1, class T2, class T3>
1782 struct ResultTraits3<UnaryFctPtrFunctor<EXPR, RES, ARG>, T1, T2, T3>
1783 {
1784  typedef RES Res;
1785 };
1786 
1787 template <class EXPR, class RES, class ARG>
1788 inline UnaryFunctor<UnaryFctPtrFunctor<UnaryFunctor<EXPR>, RES, ARG> >
1789 applyFct(RES (*f)(ARG), UnaryFunctor<EXPR> const & e)
1790 {
1791  UnaryFctPtrFunctor<UnaryFunctor<EXPR>, RES, ARG> p(e, f);
1792  return UnaryFunctor<UnaryFctPtrFunctor<UnaryFunctor<EXPR>, RES, ARG> >(p);
1793 }
1794 
1795 /************************************************************/
1796 /* */
1797 /* binary apply */
1798 /* */
1799 /************************************************************/
1800 
1801 template <class EXPR1, class EXPR2, class RES, class ARG1, class ARG2>
1802 struct BinaryFctPtrFunctor
1803 {
1804  BinaryFctPtrFunctor(EXPR1 const & e1, EXPR2 const & e2,
1805  RES (*f)(ARG1, ARG2))
1806  : expr1_(e1), expr2_(e2), f_(f)
1807  {}
1808 
1809  RES operator()() const
1810  {
1811  return f_(expr1_(), expr2_());
1812  }
1813 
1814  template <class T>
1815  RES operator()(T const & v1) const
1816  {
1817  return f_(expr1_(v1), expr2_(v1));
1818  }
1819 
1820  template <class T1, class T2>
1821  RES operator()(T1 const & v1, T2 const & v2) const
1822  {
1823  return f_(expr1_(v1, v2), expr2_(v1, v2));
1824  }
1825 
1826  template <class T1, class T2, class T3>
1827  RES operator()(T1 const & v1, T2 const & v2, T3 const & v3) const
1828  {
1829  return f_(expr1_(v1, v2, v3), expr2_(v1, v2, v3));
1830  }
1831 
1832  protected:
1833 
1834  EXPR1 expr1_;
1835  EXPR2 expr2_;
1836  RES (*f_)(ARG1, ARG2);
1837 
1838  private:
1839  BinaryFctPtrFunctor & operator=(BinaryFctPtrFunctor const &); // not implemented
1840 };
1841 
1842 template <class EXPR1, class EXPR2, class RES, class ARG1, class ARG2>
1843 struct ResultTraits0<BinaryFctPtrFunctor<EXPR1, EXPR2, RES, ARG1, ARG2> >
1844 {
1845  typedef RES Res;
1846 };
1847 
1848 template <class EXPR1, class EXPR2, class RES, class ARG1, class ARG2,
1849  class T1>
1850 struct ResultTraits1<BinaryFctPtrFunctor<EXPR1, EXPR2, RES, ARG1, ARG2>, T1>
1851 {
1852  typedef RES Res;
1853 };
1854 
1855 template <class EXPR1, class EXPR2, class RES, class ARG1, class ARG2,
1856  class T1, class T2>
1857 struct ResultTraits2<BinaryFctPtrFunctor<EXPR1, EXPR2, RES, ARG1, ARG2>, T1, T2>
1858 {
1859  typedef RES Res;
1860 };
1861 
1862 template <class EXPR1, class EXPR2, class RES, class ARG1, class ARG2,
1863  class T1, class T2, class T3>
1864 struct ResultTraits3<BinaryFctPtrFunctor<EXPR1, EXPR2, RES, ARG1, ARG2>, T1, T2, T3>
1865 {
1866  typedef RES Res;
1867 };
1868 
1869 template <class EXPR1, class EXPR2, class RES, class ARG1, class ARG2>
1870 inline UnaryFunctor<BinaryFctPtrFunctor<UnaryFunctor<EXPR1>,
1871  UnaryFunctor<EXPR2>,
1872  RES, ARG1, ARG2> >
1873 applyFct(RES (*f)(ARG1, ARG2), UnaryFunctor<EXPR1> const & e1,
1874  UnaryFunctor<EXPR2> const & e2)
1875 {
1876  BinaryFctPtrFunctor<UnaryFunctor<EXPR1>,
1877  UnaryFunctor<EXPR2>,
1878  RES, ARG1, ARG2> p(e1, e2, f);
1879  return UnaryFunctor<BinaryFctPtrFunctor<UnaryFunctor<EXPR1>,
1880  UnaryFunctor<EXPR2>,
1881  RES, ARG1, ARG2> >(p);
1882 }
1883 
1884 /************************************************************/
1885 /* */
1886 /* comma operator */
1887 /* */
1888 /************************************************************/
1889 
1890 template <class EXPR1, class EXPR2>
1891 struct CommaFunctor
1892 {
1893  CommaFunctor(EXPR1 const & e1, EXPR2 const & e2)
1894  : expr1_(e1), expr2_(e2)
1895  {}
1896 
1897  typename ResultTraits0<EXPR2>::Res
1898  operator()() const
1899  {
1900  expr1_();
1901  return expr2_();
1902  }
1903 
1904  template <class T>
1905  typename ResultTraits1<EXPR2, T>::Res
1906  operator()(T const & v1) const
1907  {
1908  expr1_(v1);
1909  return expr2_(v1);
1910  }
1911 
1912  template <class T1, class T2>
1913  typename ResultTraits2<EXPR2, T1, T2>::Res
1914  operator()(T1 const & v1, T2 const & v2) const
1915  {
1916  expr1_(v1, v2);
1917  return expr2_(v1, v2);
1918  }
1919 
1920  template <class T1, class T2, class T3>
1921  typename ResultTraits3<EXPR2, T1, T2, T3>::Res
1922  operator()(T1 const & v1, T2 const & v2, T3 const & v3) const
1923  {
1924  expr1_(v1, v2, v3);
1925  return expr2_(v1, v2, v3);
1926  }
1927 
1928  protected:
1929 
1930  EXPR1 expr1_;
1931  EXPR2 expr2_;
1932 
1933  private:
1934  CommaFunctor & operator=(CommaFunctor const &); // not implemented
1935 };
1936 
1937 template <class Expr1, class Expr2>
1938 struct ResultTraits0<CommaFunctor<Expr1, Expr2> >
1939 {
1940  typedef typename ResultTraits0<Expr2>::Res Res;
1941 };
1942 
1943 template <class Expr1, class Expr2, class T1>
1944 struct ResultTraits1<CommaFunctor<Expr1, Expr2>, T1>
1945 {
1946  typedef typename ResultTraits1<Expr2, T1>::Res Res;
1947 };
1948 
1949 template <class Expr1, class Expr2, class T1, class T2>
1950 struct ResultTraits2<CommaFunctor<Expr1, Expr2>, T1, T2>
1951 {
1952  typedef typename ResultTraits2<Expr2, T1, T2>::Res Res;
1953 };
1954 
1955 template <class Expr1, class Expr2, class T1, class T2, class T3>
1956 struct ResultTraits3<CommaFunctor<Expr1, Expr2>, T1, T2, T3>
1957 {
1958  typedef typename ResultTraits3<Expr2, T1, T2, T3>::Res Res;
1959 };
1960 
1961 template <class EXPR1, class EXPR2>
1962 inline UnaryFunctor<CommaFunctor<UnaryAnalyser<EXPR1>,
1963  UnaryFunctor<EXPR2> > >
1964 operator,(UnaryAnalyser<EXPR1> const & e1,
1965  UnaryFunctor<EXPR2> const & e2)
1966 {
1967  CommaFunctor<UnaryAnalyser<EXPR1>,
1968  UnaryFunctor<EXPR2> > p(e1, e2);
1969  return UnaryFunctor<CommaFunctor<UnaryAnalyser<EXPR1>,
1970  UnaryFunctor<EXPR2> > >(p);
1971 }
1972 
1973 /************************************************************/
1974 
1975 template <class EXPR1, class EXPR2>
1976 struct CommaAnalyser
1977 {
1978  CommaAnalyser(EXPR1 const & e1, EXPR2 const & e2)
1979  : expr1_(e1), expr2_(e2)
1980  {}
1981 
1982  void operator()() const
1983  {
1984  expr1_();
1985  expr2_();
1986  }
1987 
1988  template <class T>
1989  void operator()(T const & v1) const
1990  {
1991  expr1_(v1);
1992  expr2_(v1);
1993  }
1994 
1995  template <class T1, class T2>
1996  void operator()(T1 const & v1, T2 const & v2) const
1997  {
1998  expr1_(v1, v2);
1999  expr2_(v1, v2);
2000  }
2001 
2002  template <class T1, class T2, class T3>
2003  void operator()(T1 const & v1, T2 const & v2, T3 const & v3) const
2004  {
2005  expr1_(v1, v2, v3);
2006  expr2_(v1, v2, v3);
2007  }
2008 
2009  protected:
2010 
2011  EXPR1 expr1_;
2012  EXPR2 expr2_;
2013 
2014  private:
2015  CommaAnalyser & operator=(CommaAnalyser const &); // not implemented
2016 };
2017 
2018 template <class EXPR1, class EXPR2>
2019 inline UnaryAnalyser<CommaAnalyser<UnaryAnalyser<EXPR1>,
2020  UnaryAnalyser<EXPR2> > >
2021 operator,(UnaryAnalyser<EXPR1> const & e1,
2022  UnaryAnalyser<EXPR2> const & e2)
2023 {
2024  CommaAnalyser<UnaryAnalyser<EXPR1>,
2025  UnaryAnalyser<EXPR2> > p(e1, e2);
2026  return UnaryAnalyser<CommaAnalyser<UnaryAnalyser<EXPR1>,
2027  UnaryAnalyser<EXPR2> > >(p);
2028 }
2029 
2030 } // namespace functor
2031 
2032 #if defined(__GNUC__) && __GNUC__ < 3
2033 using functor::Arg1;
2034 using functor::Arg2;
2035 using functor::Arg3;
2036 using functor::Param;
2037 #endif
2038 
2039 template <class T>
2040 class FunctorTraits<functor::UnaryFunctor<T> >
2041 : public FunctorTraitsBase<functor::UnaryFunctor<T> >
2042 {
2043  public:
2044  typedef VigraTrueType isInitializer;
2045  typedef VigraTrueType isUnaryFunctor;
2046  typedef VigraTrueType isBinaryFunctor;
2047  typedef VigraTrueType isTernaryFunctor;
2048 };
2049 
2050 template <class T>
2051 class FunctorTraits<functor::UnaryAnalyser<T> >
2052 : public FunctorTraitsBase<functor::UnaryAnalyser<T> >
2053 {
2054  public:
2055  typedef VigraTrueType isUnaryAnalyser;
2056  typedef VigraTrueType isBinaryAnalyser;
2057  typedef VigraTrueType isTernaryAnalyser;
2058 };
2059 
2060 
2061 
2062 } // namespace vigra
2063 
2064 #endif /* NO_PARTIAL_TEMPLATE_SPECIALIZATION */
2065 
2066 #endif // DOXYGEN
2067 
2068 #endif /* VIGRA_FUNCTOREXPRESSION_HXX */
2069 
2070 

© 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.8.0 (Wed Sep 26 2012)