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

© 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.12.1 (Thu Feb 27 2025)