VIGRA - VIGRA: vigra/functorexpression.hxx Source File

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

# vigra/functorexpression.hxx

    00001 /************************************************************************/
    00002 /*                                                                      */
    00003 /*               Copyright 1998-2002 by Ullrich Koethe                  */
    00004 /*       Cognitive Systems Group, University of Hamburg, Germany        */
    00005 /*                                                                      */
    00006 /*    This file is part of the VIGRA computer vision library.           */
    00007 /*    ( Version 1.6.0, Aug 13 2008 )                                    */
    00008 /*    The VIGRA Website is                                              */
    00009 /*        http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/      */
    00010 /*    Please direct questions, bug reports, and contributions to        */
    00011 /*        ullrich.koethe@iwr.uni-heidelberg.de    or                    */
    00012 /*        vigra@informatik.uni-hamburg.de                               */
    00013 /*                                                                      */
    00014 /*    Permission is hereby granted, free of charge, to any person       */
    00015 /*    obtaining a copy of this software and associated documentation    */
    00016 /*    files (the "Software"), to deal in the Software without           */
    00017 /*    restriction, including without limitation the rights to use,      */
    00018 /*    copy, modify, merge, publish, distribute, sublicense, and/or      */
    00019 /*    sell copies of the Software, and to permit persons to whom the    */
    00020 /*    Software is furnished to do so, subject to the following          */
    00021 /*    conditions:                                                       */
    00022 /*                                                                      */
    00023 /*    The above copyright notice and this permission notice shall be    */
    00024 /*    included in all copies or substantial portions of the             */
    00025 /*    Software.                                                         */
    00026 /*                                                                      */
    00027 /*    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND    */
    00028 /*    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES   */
    00029 /*    OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND          */
    00030 /*    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT       */
    00031 /*    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,      */
    00032 /*    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING      */
    00033 /*    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR     */
    00034 /*    OTHER DEALINGS IN THE SOFTWARE.                                   */
    00035 /*                                                                      */
    00036 /************************************************************************/
    00037
    00038 #ifndef VIGRA_FUNCTOREXPRESSION_HXX
    00039 #define VIGRA_FUNCTOREXPRESSION_HXX
    00040
    00041
    00042 /** \page FunctorExpressions Functor Expressions
    00043
    00044     Simple automatic functor creation by means of expression templates
    00045     (also known as a "lambda library").
    00046
    00047     <b>\#include</b> <<a href="functorexpression_8hxx-source.html">vigra/functorexpression.hxx</a>><br>
    00048     Namespace: vigra::functor
    00049
    00050     <b> Note:</b> This functionality is not available under Microsoft Visual C++,
    00051     because support for partial template specialization is required.
    00052
    00053     <b> Motivation</b>
    00054
    00055     Many generic algorithms are made more flexible by means of functors
    00056     which define part of the algorithms' behavior according to the
    00057     needs of a specific situation. For example, we can apply an exponential
    00058     to each pixel by passing a pointer to the <TT>exp</TT> function
    00059     to <TT>transformImage()</TT>:
    00060
    00061     \code
    00062     vigra::FImage src(w,h), dest(w,h);
    00063     ... // fill src
    00064
    00065     vigra::transformImage(srcImageRange(src), destImage(dest), &exp);
    00066     \endcode
    00067
    00068     However, this only works for simple operations. If we wanted to
    00069     apply the exponential to a scaled pixel value (i.e. we want to execute
    00070     <TT>exp(-beta*v)</TT>), we first need to implement a new functor:
    00071
    00072     \code
    00073     struct Exponential
    00074     {
    00075         Exponential(double b)
    00076         : beta(b)
    00077         {}
    00078
    00079         template <class PixelType>
    00080         PixelType operator()(PixelType const& v) const
    00081         {
    00082             return exp(-beta*v);
    00083         }
    00084
    00085         double beta;
    00086     };
    00087     \endcode
    00088
    00089     This functor would be used like this:
    00090
    00091     \code
    00092     double beta =  ...;
    00093     vigra::transformImage(srcImageRange(src), destImage(dest),
    00094                    Exponential(beta));
    00095     \endcode
    00096
    00097     However, this approach has some disadvantages:
    00098
    00099     <UL>
    00100
    00101     <li> Writing a functor is more work then simply programm the loop
    00102           directly, i.e. non-generically. Programmers will tend to
    00103           avoid generic constructs, if they require so much writing.
    00104     <li> Often, functors are only needed for a single expression.
    00105           It is not desirable to get into the trouble of introducing
    00106           and documenting a new class if that class is used only once.
    00107     <li> Functors cannot be implemented directly at the point of use.
    00108           Thus, to find out exactly what a functor is doing, one needs
    00109           to look somewhere else. This complicates use and maintainance
    00110           ot generic code.
    00111
    00112     </UL>
    00113
    00114     Therefore, it is necessary to provide a means to generate functors on
    00115     the fly where they are needed. The C++ standard library contains so called
    00116     "functor combinators" that allow to construct complicated functors from
    00117     simpler ones. The above problem "apply <TT>exp(-beta*v)</TT> to every pixel"
    00118     would be solved like this:
    00119
    00120     \code
    00121     float beta = ...;
    00122
    00123     vigra::transformImage(srcImageRange(src), destImage(dest),
    00124                    std::compose1(std::ptr_fun(exp),
    00125                                  std::bind1st(std::multiplies<float>(), -beta)));
    00126     \endcode
    00127
    00128     I won't go into details on how this works. Suffice it to say that
    00129     this technique requires a functional programming style that is unfamiliar
    00130     to many programmers, and thus leads to code that is difficult to
    00131     understand. Moreover, this technique has some limitations that prevent
    00132     certain expressions from being implementable this way. Therefore, VIGRA
    00133     provides a better and simpler means to create functors on the fly.
    00134
    00135     <b> Automatic Functor Creation</b>
    00136
    00137     Automatic functor creation in VIGRA is based on a technique called
    00138     <a href="http://extreme.indiana.edu/~tveldhui/papers/Expression-Templates/exprtmpl.html">Expression Templates</a>.
    00139     This means that C++ operators are
    00140     overloaded so that they don't execute the specified operation directly,
    00141     but instead produce a functor which will later calculate the result.
    00142     This technique has the big advantage that the familiar operator notation
    00143     can be used, while all the flexibility of generic programming is preserved.
    00144     Unfortunately, it requires partial template specialization, so these capabilities
    00145     are not available on compilers that dont support this C++ feature
    00146     (in particular, on Microsoft Visual C++).
    00147
    00148     The above problem "apply <TT>exp(-beta*v)</TT> to every pixel" will be solved
    00149     like this:
    00150
    00151     \code
    00152     using namespace vigra::functor;
    00153
    00154     float beta = ...;
    00155
    00156     transformImage(srcImageRange(src), destImage(dest),
    00157                    exp(Param(-beta)*Arg1()));
    00158     \endcode
    00159
    00160     Here, four expression templates have been used to create the desired
    00161     functor:
    00162
    00163     <DL>
    00164
    00165     <DT><b><TT>Param(-beta):</TT></b><DD> creates a functor that represents a
    00166          constant (<TT>-beta</TT> in this case)
    00167
    00168     <DT><b><TT>Arg1():</TT></b><DD> represents the first argument of the expression (i.e.
    00169          the pixels of image <TT>src</TT> in the example). Likewise, <TT>Arg2()</TT> and
    00170          <TT>Arg3()</TT> are defined to represent more arguments. These are needed
    00171          for algorithms that have multiple input images, such as
    00172          \ref combineTwoImages() and \ref combineThreeImages().
    00173
    00174     <DT><b>* (multiplication):</b><DD> creates a functor that returns the product of
    00175          its arguments. Likewise, the other C++ operators (i.e.
    00176          <TT>+, -, *, /, %, ==, !=, <, <=, >, >=, &&, ||, &, |, ^, !, ~</TT>)
    00177          are overloaded.
    00178
    00179     <DT><b><TT>exp():</TT></b><DD> creates a functor that takes the exponential of its
    00180         argument. Likewise, the other algebraic functions
    00181         (i.e. <TT>sqrt, exp, log, log10, sin, asin, cos, acos, tan,
    00182         atan, abs, floor, ceil, pow, atan2, fmod, min, max</TT>)
    00183         are overloaded.
    00184
    00185     </DL>
    00186
    00187     We will explain additional capabilities of the functor creation mechanism
    00188     by means of examples.
    00189
    00190     The same argument can be used several times in the expression.
    00191     For example, to calculate the gradient magnitude from the components
    00192     of the gradient vector, you may write:
    00193
    00194     \code
    00195     using namespace vigra::functor;
    00196
    00197     vigra::FImage gradient_x(w,h), gradient_y(w,h), magnitude(w,h);
    00198     ... // calculate gradient_x and gradient_y
    00199
    00200     combineTwoImages(srcImageRange(gradient_x), srcImage(gradient_y),
    00201                      destImage(magnitude),
    00202                      sqrt(Arg1()*Arg1() + Arg2()*Arg2()));
    00203     \endcode
    00204
    00205     It is also possible to build other functions into functor expressions. Suppose
    00206     you want to apply <TT>my_complicated_function()</TT> to the sum of two images:
    00207
    00208     \code
    00209     using namespace vigra::functor;
    00210
    00211     vigra::FImage src1(w,h), src2(w,h), dest(w,h);
    00212
    00213     double my_complicated_function(double);
    00214
    00215     combineTwoImages(srcImageRange(src1), srcImage(src2), destImage(dest),
    00216                      applyFct(&my_complicated_function, Arg1()+Arg2()));
    00217     \endcode
    00218
    00219     [Note that the arguments of the wrapped function are passed as additional
    00220     arguments to <TT>applyFct()</TT>]
    00221
    00222     You can implement conditional expression by means of the <TT>ifThenElse()</TT>
    00223     functor. It corresponds to the "? :" operator that cannot be overloaded.
    00224     <TT>ifThenElse()</TT> can be used, for example, to threshold an image:
    00225
    00226     \code
    00227     using namespace vigra::functor;
    00228
    00229     vigra::FImage src(w,h), thresholded(w,h);
    00230     ...// fill src
    00231
    00232     float threshold = ...;
    00233
    00234     transformImage(srcImageRange(src), destImage(thresholded),
    00235                    ifThenElse(Arg1() < Param(threshold),
    00236                               Param(0.0),    // yes branch
    00237                               Param(1.0))    // no  branch
    00238                   );
    00239     \endcode
    00240
    00241     You can use the <TT>Var()</TT> functor to assign values to a variable
    00242     (<TT>=, +=, -=, *=, /=</TT>&nbsp; are suported). For example, the average gray
    00243     value of the image is calculated like this:
    00244
    00245     \code
    00246     using namespace vigra::functor;
    00247
    00248     vigra::FImage src(w,h);
    00249     ...// fill src
    00250
    00251     double sum = 0.0;
    00252
    00253     inspectImage(srcImageRange(src), Var(sum) += Arg1());
    00254
    00255     std::cout << "Average: " << (sum / (w*h)) << std::endl;
    00256     \endcode
    00257
    00258     For use in \ref inspectImage() and its relatives, there is a second
    00259     conditional functor <TT>ifThen()</TT> that emulates the <TT>if()</TT> statement
    00260     and does not return a value. Using <TT>ifThen()</TT>, we can calculate the size
    00261     of an image region:
    00262
    00263     \code
    00264     using namespace vigra::functor;
    00265
    00266     vigra::IImage label_image(w,h);
    00267     ...// mark regions by labels in label_image
    00268
    00269     int region_label = ...; // the region we want to inspect
    00270     int size = 0;
    00271
    00272     inspectImage(srcImageRange(label_image),
    00273                  ifThen(Arg1() == Param(region_label),
    00274                         Var(size) += Param(1)));
    00275
    00276     std::cout << "Size of region " << region_label << ": " << size << std::endl;
    00277     \endcode
    00278
    00279     Often, we want to execute several commands in one functor. This can be done
    00280     by means of the overloaded <TT>operator,()</TT> ("operator comma"). Expressions
    00281     seperated by a comma will be executed in succession. We can thus
    00282     simultaneously find the size and the average gray value of a region:
    00283
    00284     \code
    00285     using namespace vigra::functor;
    00286
    00287     vigra::FImage src(w,h);
    00288     vigra::IImage label_image(w,h);
    00289     ...// segment src and mark regions in label_image
    00290
    00291     int region_label = ...; // the region we want to inspect
    00292     int size = 0;
    00293     double sum = 0.0;
    00294
    00295     inspectTwoImages(srcImageRange(src), srcImage(label_image),
    00296                      ifThen(Arg2() == Param(region_label),
    00297                      (
    00298                         Var(size) += Param(1), // the comma operator is invoked
    00299                         Var(sum) += Arg1()
    00300                      )));
    00301
    00302     std::cout << "Region " << region_label << ": size = " << size <<
    00303                                               ", average = " << sum / size << std::endl;
    00304     \endcode
    00305
    00306     [Note that the list of comma-separated expressions must be enclosed in parentheses.]
    00307
    00308     A comma separated list of expressions can also be applied in the context of
    00309     \ref transformImage() and its cousins. Here, a general rule of C++ applies: The
    00310     return value of a comma expression is the value of its last subexpression.
    00311     For example, we can initialize an image so that each pixel contains its
    00312     address in scan order:
    00313
    00314     \code
    00315     using namespace vigra::functor;
    00316
    00317     vigra::IImage img(w,h);
    00318
    00319     int count = -1;
    00320
    00321     initImageWithFunctor(destImageRange(img),
    00322                          (
    00323                               Var(count) += Param(1),
    00324                               Var(count)     // this is the result of the comma expression
    00325                          ));
    00326     \endcode
    00327
    00328     Further information about how this mechanism works can be found in
    00329     <a href="documents/FunctorFactory.ps">this paper</a> (sorry, slightly out of date).
    00330 */
    00331
    00332 #ifndef DOXYGEN
    00333
    00334 #if !defined(NO_PARTIAL_TEMPLATE_SPECIALIZATION)
    00335
    00336 #include <cmath>
    00337 #include "numerictraits.hxx"
    00338 #include "mathutil.hxx"
    00339 #include "functortraits.hxx"
    00340
    00341
    00342 namespace vigra {
    00343
    00344 namespace functor {
    00345
    00346 /************************************************************/
    00347 /*                                                          */
    00348 /*                 unary functor base template              */
    00349 /*                                                          */
    00350 /************************************************************/
    00351
    00352
    00353 struct ErrorType;
    00354
    00355 template <class Operation>
    00356 struct ResultTraits0;
    00357
    00358 template <class Operation, class T1>
    00359 struct ResultTraits1
    00360 {
    00361     typedef T1 Res;
    00362 };
    00363
    00364 template <class Operation, class T1, class T2>
    00365 struct ResultTraits2
    00366 {
    00367     typedef typename PromoteTraits<T1, T2>::Promote Res;
    00368 };
    00369
    00370 template <class Operation, class T1, class T2, class T3>
    00371 struct ResultTraits3
    00372 {
    00373     typedef typename PromoteTraits<T1, T2>::Promote P1;
    00374     typedef typename PromoteTraits<P1, T3>::Promote Res;
    00375 };
    00376
    00377 template <class EXPR>
    00378 struct UnaryFunctor
    00379 {
    00380     UnaryFunctor(EXPR const & e)
    00381     : expr_(e)
    00382     {}
    00383
    00384 //    typename ResultTraits0<EXPR>::Res
    00385     typename ResultTraits0<EXPR>::Res
    00386     operator()() const
    00387     {
    00388         return expr_();
    00389     }
    00390
    00391     template <class T1>
    00392     typename ResultTraits1<EXPR, T1>::Res
    00393     operator()(T1 const & v) const
    00394     {
    00395         return expr_(v);
    00396     }
    00397
    00398     template <class T1, class T2>
    00399     typename ResultTraits2<EXPR, T1, T2>::Res
    00400     operator()(T1 const & v1, T2 const & v2) const
    00401     {
    00402         return expr_(v1, v2);
    00403     }
    00404
    00405     template <class T1, class T2, class T3>
    00406     typename ResultTraits3<EXPR, T1, T2, T3>::Res
    00407     operator()(T1 const & v1, T2 const & v2, T3 const & v3) const
    00408     {
    00409         return expr_(v1, v2, v3);
    00410     }
    00411
    00412   protected:
    00413     EXPR expr_;
    00414
    00415   private:
    00416     UnaryFunctor & operator=(UnaryFunctor const &); // not implemented
    00417 };
    00418
    00419 template <class Expr>
    00420 struct ResultTraits0<UnaryFunctor<Expr> >
    00421 {
    00422     typedef typename ResultTraits0<Expr>::Res Res;
    00423 };
    00424
    00425 template <class Expr, class T1>
    00426 struct ResultTraits1<UnaryFunctor<Expr>, T1>
    00427 {
    00428     typedef typename ResultTraits1<Expr, T1>::Res Res;
    00429 };
    00430
    00431 template <class Expr, class T1, class T2>
    00432 struct ResultTraits2<UnaryFunctor<Expr>, T1, T2>
    00433 {
    00434     typedef typename ResultTraits2<Expr, T1, T2>::Res Res;
    00435 };
    00436
    00437 template <class Expr, class T1, class T2, class T3>
    00438 struct ResultTraits3<UnaryFunctor<Expr>, T1, T2, T3>
    00439 {
    00440     typedef typename ResultTraits3<Expr, T1, T2, T3>::Res Res;
    00441 };
    00442
    00443 /************************************************************/
    00444 /*                                                          */
    00445 /*                 unary functors for arguments             */
    00446 /*                                                          */
    00447 /************************************************************/
    00448
    00449 struct ArgumentFunctor1;
    00450 struct ArgumentFunctor2;
    00451 struct ArgumentFunctor3;
    00452
    00453 template <>
    00454 struct UnaryFunctor<ArgumentFunctor1>
    00455 {
    00456     UnaryFunctor()
    00457     {}
    00458
    00459     template <class T1>
    00460     T1 const & operator()(T1 const & v1) const
    00461     {
    00462         return v1;
    00463     }
    00464
    00465     template <class T1, class T2>
    00466     T1 const & operator()(T1 const & v1, T2 const &) const
    00467     {
    00468         return v1;
    00469     }
    00470
    00471     template <class T1, class T2, class T3>
    00472     T1 const & operator()(T1 const & v1, T2 const &, T3 const &) const
    00473     {
    00474         return v1;
    00475     }
    00476
    00477   private:
    00478     UnaryFunctor & operator=(UnaryFunctor const &); // not implemented
    00479 };
    00480
    00481 template <>
    00482 struct ResultTraits0<UnaryFunctor<ArgumentFunctor1> >
    00483 {
    00484     typedef ErrorType Res;
    00485 };
    00486
    00487 template <class T1>
    00488 struct ResultTraits1<UnaryFunctor<ArgumentFunctor1>, T1>
    00489 {
    00490     typedef T1 Res;
    00491 };
    00492
    00493 template <class T1, class T2>
    00494 struct ResultTraits2<UnaryFunctor<ArgumentFunctor1>, T1, T2>
    00495 {
    00496     typedef T1 Res;
    00497 };
    00498
    00499 template <class T1, class T2, class T3>
    00500 struct ResultTraits3<UnaryFunctor<ArgumentFunctor1>, T1, T2, T3>
    00501 {
    00502     typedef T1 Res;
    00503 };
    00504
    00505 /************************************************************/
    00506
    00507 inline
    00508 UnaryFunctor<ArgumentFunctor1>
    00509 Arg1()
    00510 {
    00511     return UnaryFunctor<ArgumentFunctor1>();
    00512 }
    00513
    00514 /************************************************************/
    00515
    00516 template <>
    00517 struct UnaryFunctor<ArgumentFunctor2>
    00518 {
    00519     UnaryFunctor()
    00520     {}
    00521
    00522     template <class T1, class T2>
    00523     T2 const & operator()(T1 const &, T2 const & v2) const
    00524     {
    00525         return v2;
    00526     }
    00527
    00528     template <class T1, class T2, class T3>
    00529     T2 const & operator()(T1 const &, T2 const & v2, T3 const &) const
    00530     {
    00531         return v2;
    00532     }
    00533
    00534   private:
    00535     UnaryFunctor & operator=(UnaryFunctor const &); // not implemented
    00536 };
    00537
    00538 template <>
    00539 struct ResultTraits0<UnaryFunctor<ArgumentFunctor2> >
    00540 {
    00541     typedef ErrorType Res;
    00542 };
    00543
    00544 template <class T1>
    00545 struct ResultTraits1<UnaryFunctor<ArgumentFunctor2>, T1>
    00546 {
    00547     typedef ErrorType Res;
    00548 };
    00549
    00550 template <class T1, class T2>
    00551 struct ResultTraits2<UnaryFunctor<ArgumentFunctor2>, T1, T2>
    00552 {
    00553     typedef T2 Res;
    00554 };
    00555
    00556 template <class T1, class T2, class T3>
    00557 struct ResultTraits3<UnaryFunctor<ArgumentFunctor2>, T1, T2, T3>
    00558 {
    00559     typedef T2 Res;
    00560 };
    00561
    00562 /************************************************************/
    00563
    00564 inline
    00565 UnaryFunctor<ArgumentFunctor2>
    00566 Arg2()
    00567 {
    00568     return UnaryFunctor<ArgumentFunctor2>();
    00569 }
    00570
    00571 /************************************************************/
    00572
    00573 template <>
    00574 struct UnaryFunctor<ArgumentFunctor3>
    00575 {
    00576     UnaryFunctor()
    00577     {}
    00578
    00579     template <class T1, class T2, class T3>
    00580     T3 const & operator()(T1 const &, T2 const &, T3 const & v3) const
    00581     {
    00582         return v3;
    00583     }
    00584
    00585   private:
    00586     UnaryFunctor & operator=(UnaryFunctor const &); // not implemented
    00587 };
    00588
    00589 template <>
    00590 struct ResultTraits0<UnaryFunctor<ArgumentFunctor3> >
    00591 {
    00592     typedef ErrorType Res;
    00593 };
    00594
    00595 template <class T1>
    00596 struct ResultTraits1<UnaryFunctor<ArgumentFunctor3>, T1>
    00597 {
    00598     typedef ErrorType Res;
    00599 };
    00600
    00601 template <class T1, class T2>
    00602 struct ResultTraits2<UnaryFunctor<ArgumentFunctor3>, T1, T2>
    00603 {
    00604     typedef ErrorType Res;
    00605 };
    00606
    00607 template <class T1, class T2, class T3>
    00608 struct ResultTraits3<UnaryFunctor<ArgumentFunctor3>, T1, T2, T3>
    00609 {
    00610     typedef T3 Res;
    00611 };
    00612
    00613 /************************************************************/
    00614
    00615 inline
    00616 UnaryFunctor<ArgumentFunctor3>
    00617 Arg3()
    00618 {
    00619     return UnaryFunctor<ArgumentFunctor3>();
    00620 }
    00621
    00622 /************************************************************/
    00623 /*                                                          */
    00624 /*                    constant parameters                   */
    00625 /*                                                          */
    00626 /************************************************************/
    00627
    00628 template <class T>
    00629 struct ParameterFunctor
    00630 {
    00631     ParameterFunctor(T v)
    00632     : value_(v)
    00633     {}
    00634
    00635     T const & operator()() const
    00636     {
    00637         return value_;
    00638     }
    00639
    00640     template <class U1>
    00641     T const & operator()(U1 const &) const
    00642     {
    00643         return value_;
    00644     }
    00645
    00646     template <class U1, class U2>
    00647     T const & operator()(U1 const &, U2 const &) const
    00648     {
    00649         return value_;
    00650     }
    00651
    00652     template <class U1, class U2, class U3>
    00653     T const & operator()(U1 const &, U2 const &, U3 const &) const
    00654     {
    00655         return value_;
    00656     }
    00657
    00658   protected:
    00659     T value_;
    00660
    00661   private:
    00662     ParameterFunctor & operator=(ParameterFunctor const &); // not implemented
    00663 };
    00664
    00665 template <class T>
    00666 struct ResultTraits0<ParameterFunctor<T> >
    00667 {
    00668     typedef T Res;
    00669 };
    00670
    00671 template <class T, class T1>
    00672 struct ResultTraits1<ParameterFunctor<T>, T1>
    00673 {
    00674     typedef T Res;
    00675 };
    00676
    00677 template <class T, class T1, class T2>
    00678 struct ResultTraits2<ParameterFunctor<T>, T1, T2>
    00679 {
    00680     typedef T Res;
    00681 };
    00682
    00683 template <class T, class T1, class T2, class T3>
    00684 struct ResultTraits3<ParameterFunctor<T>, T1, T2, T3>
    00685 {
    00686     typedef T Res;
    00687 };
    00688
    00689 template <class T>
    00690 inline UnaryFunctor<ParameterFunctor<T> >
    00691 Param(T const & v)
    00692 {
    00693     ParameterFunctor<T> fv(v);
    00694     return UnaryFunctor<ParameterFunctor<T> >(fv);
    00695 }
    00696
    00697 /************************************************************/
    00698 /*                                                          */
    00699 /*                unary analyser base template              */
    00700 /*                                                          */
    00701 /************************************************************/
    00702
    00703
    00704 template <class EXPR>
    00705 class UnaryAnalyser
    00706 {
    00707   public:
    00708     UnaryAnalyser(EXPR const & e)
    00709     : expr_(e)
    00710     {}
    00711
    00712     void operator()() const
    00713     {
    00714         expr_();
    00715     }
    00716
    00717     template <class T1>
    00718     void operator()(T1 const & v) const
    00719     {
    00720         expr_(v);
    00721     }
    00722
    00723     template <class T1, class T2>
    00724     void operator()(T1 const & v1, T2 const & v2) const
    00725     {
    00726         expr_(v1, v2);
    00727     }
    00728
    00729     template <class T1, class T2, class T3>
    00730     void operator()(T1 const & v1, T2 const & v2, T3 const & v3) const
    00731     {
    00732         expr_(v1, v2, v3);
    00733     }
    00734   protected:
    00735
    00736     EXPR expr_;
    00737
    00738   private:
    00739     UnaryAnalyser & operator=(UnaryAnalyser const &); // not implemented
    00740 };
    00741
    00742 /************************************************************/
    00743 /*                                                          */
    00744 /*                     variable assignment                  */
    00745 /*                                                          */
    00746 /************************************************************/
    00747
    00748 template <class T>
    00749 struct VarFunctor;
    00750
    00751 template <class T>
    00752 struct UnaryFunctor<VarFunctor<T> >;
    00753
    00754 /************************************************************/
    00755
    00756 #define MAKE_ASSIGNMENT_FUNCTOR(name, op) \
    00757     template <class V, class EXPR> \
    00758     struct AssignmentFunctor_##name \
    00759     { \
    00760         AssignmentFunctor_##name(UnaryFunctor<VarFunctor<V> > v,  \
    00761                                  UnaryFunctor<EXPR> const & e) \
    00762         : value_(v.value_), expr_(e) \
    00763         {} \
    00764          \
    00765         V & operator()() const \
    00766         { \
    00767             const_cast<V &>(value_) op expr_(); \
    00768             return const_cast<V &>(value_); \
    00769         } \
    00770          \
    00771         template <class T1>  \
    00772         V & operator()(T1 const & v1) const \
    00773         { \
    00774             const_cast<V &>(value_) op expr_(v1); \
    00775             return const_cast<V &>(value_); \
    00776         } \
    00777          \
    00778         template <class T1, class T2>  \
    00779         V & operator()(T1 const & v1, T2 const & v2) const \
    00780         { \
    00781             const_cast<V &>(value_) op expr_(v1, v2); \
    00782             return const_cast<V &>(value_); \
    00783         } \
    00784          \
    00785         template <class T1, class T2, class T3>  \
    00786         V & operator()(T1 const & v1, T2 const & v2, T3 const & v3) const \
    00787         { \
    00788             const_cast<V &>(value_) op expr_(v1, v2, v3); \
    00789             return const_cast<V &>(value_); \
    00790         } \
    00791          \
    00792       private: \
    00793         V & value_; \
    00794         UnaryFunctor<EXPR> expr_; \
    00795         \
    00796         AssignmentFunctor_##name & operator=(AssignmentFunctor_##name const &);\
    00797     };
    00798
    00799 /************************************************************/
    00800
    00801 MAKE_ASSIGNMENT_FUNCTOR(assign, =)
    00802 MAKE_ASSIGNMENT_FUNCTOR(add, +=)
    00803 MAKE_ASSIGNMENT_FUNCTOR(subtract, -=)
    00804 MAKE_ASSIGNMENT_FUNCTOR(multiply, *=)
    00805 MAKE_ASSIGNMENT_FUNCTOR(divide, /=)
    00806
    00807 #undef MAKE_ASSIGNMENT_FUNCTOR
    00808
    00809 /************************************************************/
    00810 /*                                                          */
    00811 /*                          variables                       */
    00812 /*                                                          */
    00813 /************************************************************/
    00814
    00815 template <class T>
    00816 struct UnaryFunctor<VarFunctor<T> >
    00817 {
    00818     typedef T Res;
    00819
    00820     UnaryFunctor(T & v)
    00821     : value_(v)
    00822     {}
    00823
    00824     template <class EXPR>
    00825     UnaryAnalyser< AssignmentFunctor_assign<T, UnaryFunctor<EXPR> > >
    00826     operator=(UnaryFunctor<EXPR> const & e)
    00827     {
    00828         AssignmentFunctor_assign<T, UnaryFunctor<EXPR> > va(*this, e);
    00829         return UnaryAnalyser< AssignmentFunctor_assign<T, UnaryFunctor<EXPR> > >(va);
    00830     }
    00831
    00832     template <class EXPR>
    00833     UnaryAnalyser< AssignmentFunctor_add<T, UnaryFunctor<EXPR> > >
    00834     operator+=(UnaryFunctor<EXPR> const & e)
    00835     {
    00836         AssignmentFunctor_add<T, UnaryFunctor<EXPR> > va(*this, e);
    00837         return UnaryAnalyser< AssignmentFunctor_add<T, UnaryFunctor<EXPR> > >(va);
    00838     }
    00839
    00840     template <class EXPR>
    00841     UnaryAnalyser< AssignmentFunctor_subtract<T, UnaryFunctor<EXPR> > >
    00842     operator-=(UnaryFunctor<EXPR> const & e)
    00843     {
    00844         AssignmentFunctor_subtract<T, UnaryFunctor<EXPR> > va(*this, e);
    00845         return UnaryAnalyser< AssignmentFunctor_subtract<T, UnaryFunctor<EXPR> > >(va);
    00846     }
    00847
    00848     template <class EXPR>
    00849     UnaryAnalyser< AssignmentFunctor_multiply<T, UnaryFunctor<EXPR> > >
    00850     operator*=(UnaryFunctor<EXPR> const & e)
    00851     {
    00852         AssignmentFunctor_multiply<T, UnaryFunctor<EXPR> > va(*this, e);
    00853         return UnaryAnalyser< AssignmentFunctor_multiply<T, UnaryFunctor<EXPR> > >(va);
    00854     }
    00855
    00856     template <class EXPR>
    00857     UnaryAnalyser< AssignmentFunctor_divide<T, UnaryFunctor<EXPR> > >
    00858     operator/=(UnaryFunctor<EXPR> const & e)
    00859     {
    00860         AssignmentFunctor_divide<T, UnaryFunctor<EXPR> > va(*this, e);
    00861         return UnaryAnalyser< AssignmentFunctor_divide<T, UnaryFunctor<EXPR> > >(va);
    00862     }
    00863
    00864     T const & operator()() const
    00865     {
    00866         return value_;
    00867     }
    00868
    00869     template <class U1>
    00870     T const & operator()(U1 const &) const
    00871     {
    00872         return value_;
    00873     }
    00874
    00875     template <class U1, class U2>
    00876     T const & operator()(U1 const &, U2 const &) const
    00877     {
    00878         return value_;
    00879     }
    00880
    00881     template <class U1, class U2, class U3>
    00882     T const & operator()(U1 const &, U2 const &, U3 const &) const
    00883     {
    00884         return value_;
    00885     }
    00886
    00887     T & value_;
    00888
    00889   private:
    00890     UnaryFunctor & operator=(UnaryFunctor const &); // not implemented
    00891 };
    00892
    00893 template <class T>
    00894 struct ResultTraits0<UnaryFunctor<VarFunctor<T> > >
    00895 {
    00896     typedef T Res;
    00897 };
    00898
    00899 template <class T, class T1>
    00900 struct ResultTraits1<UnaryFunctor<VarFunctor<T> >, T1>
    00901 {
    00902     typedef T Res;
    00903 };
    00904
    00905 template <class T, class T1, class T2>
    00906 struct ResultTraits2<UnaryFunctor<VarFunctor<T> >, T1, T2>
    00907 {
    00908     typedef T Res;
    00909 };
    00910
    00911 template <class T, class T1, class T2, class T3>
    00912 struct ResultTraits3<UnaryFunctor<VarFunctor<T> >, T1, T2, T3>
    00913 {
    00914     typedef T Res;
    00915 };
    00916
    00917 template <class T>
    00918 inline UnaryFunctor<VarFunctor<T> >
    00919 Var(T & v)
    00920 {
    00921     return UnaryFunctor<VarFunctor<T> >(v);
    00922 }
    00923
    00924 /************************************************************/
    00925 /*                                                          */
    00926 /*                          if then                         */
    00927 /*                                                          */
    00928 /************************************************************/
    00929
    00930 template <class EXPR1, class EXPR2>
    00931 struct IfThenFunctor
    00932 {
    00933     typedef void Res;
    00934
    00935     IfThenFunctor(EXPR1 const & e1, EXPR2 const & e2)
    00936     : expr1_(e1), expr2_(e2)
    00937     {}
    00938
    00939     void operator()() const
    00940     {
    00941         if( expr1_() ) expr2_();
    00942     }
    00943
    00944     template <class T>
    00945     void operator()(T const & v1) const
    00946     {
    00947         if( expr1_(v1) ) expr2_(v1);
    00948     }
    00949
    00950     template <class T1, class T2>
    00951     void operator()(T1 const & v1, T2 const & v2) const
    00952     {
    00953         if( expr1_(v1, v2) ) expr2_(v1, v2);
    00954     }
    00955
    00956     template <class T1, class T2, class T3>
    00957     void operator()(T1 const & v1, T2 const & v2, T3 const & v3) const
    00958     {
    00959         if( expr1_(v1, v2, v3) ) expr2_(v1, v2, v3);
    00960     }
    00961
    00962   private:
    00963
    00964     EXPR1 expr1_;
    00965     EXPR2 expr2_;
    00966
    00967   private:
    00968     IfThenFunctor & operator=(IfThenFunctor const &); // not implemented
    00969 };
    00970
    00971 template <class EXPR1, class EXPR2>
    00972 UnaryAnalyser<IfThenFunctor<UnaryFunctor<EXPR1>,
    00973                             UnaryAnalyser<EXPR2> > >
    00974 ifThen(UnaryFunctor<EXPR1> const & e1,
    00975        UnaryAnalyser<EXPR2> const & e2)
    00976 {
    00977     IfThenFunctor<UnaryFunctor<EXPR1>,
    00978                   UnaryAnalyser<EXPR2> > p(e1, e2);
    00979     return UnaryAnalyser<IfThenFunctor<UnaryFunctor<EXPR1>,
    00980                                        UnaryAnalyser<EXPR2> > >(p);
    00981 }
    00982
    00983 /************************************************************/
    00984 /*                                                          */
    00985 /*                         if then else                     */
    00986 /*                                                          */
    00987 /************************************************************/
    00988
    00989 template <class EXPR1, class EXPR2, class EXPR3>
    00990 struct IfThenElseFunctor;
    00991
    00992 template <class EXPR1, class EXPR2, class EXPR3>
    00993 struct ResultTraits0<IfThenElseFunctor<EXPR1, EXPR2, EXPR3> >
    00994 {
    00995     typedef typename ResultTraits0<EXPR2>::Res R2;
    00996     typedef typename ResultTraits0<EXPR3>::Res R3;
    00997     typedef typename PromoteTraits<R2, R3>::Promote Res;
    00998 };
    00999
    01000 template <class EXPR1, class EXPR2, class EXPR3, class T1>
    01001 struct ResultTraits1<IfThenElseFunctor<EXPR1, EXPR2, EXPR3>, T1>
    01002 {
    01003     typedef typename ResultTraits1<EXPR2, T1>::Res R2;
    01004     typedef typename ResultTraits1<EXPR3, T1>::Res R3;
    01005     typedef typename PromoteTraits<R2, R3>::Promote Res;
    01006 };
    01007
    01008 template <class EXPR1, class EXPR2, class EXPR3, class T1, class T2>
    01009 struct ResultTraits2<IfThenElseFunctor<EXPR1, EXPR2, EXPR3>, T1, T2>
    01010 {
    01011     typedef typename ResultTraits2<EXPR2, T1, T2>::Res R2;
    01012     typedef typename ResultTraits2<EXPR3, T1, T2>::Res R3;
    01013     typedef typename PromoteTraits<R2, R3>::Promote Res;
    01014 };
    01015
    01016 template <class EXPR1, class EXPR2, class EXPR3, class T1, class T2, class T3>
    01017 struct ResultTraits3<IfThenElseFunctor<EXPR1, EXPR2, EXPR3>, T1, T2, T3>
    01018 {
    01019     typedef typename ResultTraits3<EXPR2, T1, T2, T3>::Res R2;
    01020     typedef typename ResultTraits3<EXPR3, T1, T2, T3>::Res R3;
    01021     typedef typename PromoteTraits<R2, R3>::Promote Res;
    01022 };
    01023
    01024 template <class EXPR1, class EXPR2, class EXPR3>
    01025 struct IfThenElseFunctor
    01026 {
    01027     IfThenElseFunctor(EXPR1 const & e1, EXPR2 const & e2, EXPR3 const & e3)
    01028     : expr1_(e1), expr2_(e2), expr3_(e3)
    01029     {}
    01030
    01031     typename ResultTraits0<IfThenElseFunctor>::Res
    01032     operator()() const
    01033     {
    01034         typename
    01035             ResultTraits0<IfThenElseFunctor>::Res
    01036             r2(expr2_());
    01037         typename
    01038             ResultTraits0<IfThenElseFunctor>::Res
    01039             r3(expr3_());
    01040         return expr1_() ? r2 : r3;
    01041     }
    01042
    01043     template <class T>
    01044     typename ResultTraits1<IfThenElseFunctor, T>::Res
    01045     operator()(T const & v1) const
    01046     {
    01047         typename
    01048             ResultTraits1<IfThenElseFunctor, T>::Res
    01049             r2(expr2_(v1));
    01050         typename
    01051             ResultTraits1<IfThenElseFunctor, T>::Res
    01052             r3(expr3_(v1));
    01053         return expr1_(v1) ? r2 : r3;
    01054     }
    01055
    01056     template <class T1, class T2>
    01057     typename ResultTraits2<IfThenElseFunctor, T1, T2>::Res
    01058     operator()(T1 const & v1, T2 const & v2) const
    01059     {
    01060         typename
    01061             ResultTraits2<IfThenElseFunctor, T1, T2>::Res
    01062             r2(expr2_(v1, v2));
    01063         typename
    01064             ResultTraits2<IfThenElseFunctor, T1, T2>::Res
    01065             r3(expr3_(v1, v2));
    01066         return expr1_(v1, v2) ? r2 : r3;
    01067     }
    01068
    01069     template <class T1, class T2, class T3>
    01070     typename ResultTraits3<IfThenElseFunctor, T1, T2, T3>::Res
    01071     operator()(T1 const & v1, T2 const & v2, T3 const & v3) const
    01072     {
    01073         typename
    01074             ResultTraits3<IfThenElseFunctor, T1, T2, T3>::Res
    01075             r2(expr2_(v1, v2, v3));
    01076         typename
    01077             ResultTraits3<IfThenElseFunctor, T1, T2, T3>::Res
    01078             r3(expr3_(v1, v2, v3));
    01079         return expr1_(v1, v2, v3) ? r2 : r3;
    01080     }
    01081
    01082   private:
    01083
    01084     EXPR1 expr1_;
    01085     EXPR2 expr2_;
    01086     EXPR3 expr3_;
    01087
    01088     IfThenElseFunctor & operator=(IfThenElseFunctor const &); // not implemented
    01089 };
    01090
    01091 template <class EXPR1, class EXPR2, class EXPR3>
    01092 UnaryFunctor<IfThenElseFunctor<UnaryFunctor<EXPR1>,
    01093                                UnaryFunctor<EXPR2>,
    01094                                UnaryFunctor<EXPR3> > >
    01095 ifThenElse(UnaryFunctor<EXPR1> const & e1,
    01096            UnaryFunctor<EXPR2> const & e2,
    01097            UnaryFunctor<EXPR3> const & e3)
    01098 {
    01099     IfThenElseFunctor<UnaryFunctor<EXPR1>,
    01100                       UnaryFunctor<EXPR2>,
    01101                       UnaryFunctor<EXPR3> > p(e1, e2, e3);
    01102     return UnaryFunctor<IfThenElseFunctor<UnaryFunctor<EXPR1>,
    01103                                           UnaryFunctor<EXPR2>,
    01104                                           UnaryFunctor<EXPR3> > >(p);
    01105 }
    01106
    01107 /************************************************************/
    01108 /*                                                          */
    01109 /*                functors for unary functions              */
    01110 /*                                                          */
    01111 /************************************************************/
    01112
    01113 #define MAKE_FUNCTOR_UNARY_FUNCTION(function, namespc) \
    01114     using ::namespc::function; \
    01115     template <class EXPR> \
    01116     struct Functor_##function; \
    01117     \
    01118     template <class EXPR> \
    01119     struct ResultTraits0<Functor_##function<EXPR> > \
    01120     { \
    01121         typedef typename ResultTraits0<EXPR>::Res R1; \
    01122         typedef typename NumericTraits<R1>::RealPromote Res; \
    01123     }; \
    01124     \
    01125     template <class EXPR, class T1> \
    01126     struct ResultTraits1<Functor_##function<EXPR>, T1> \
    01127     { \
    01128         typedef typename ResultTraits1<EXPR, T1>::Res R1; \
    01129         typedef typename NumericTraits<R1>::RealPromote Res; \
    01130     }; \
    01131     \
    01132     template <class EXPR, class T1, class T2> \
    01133     struct ResultTraits2<Functor_##function<EXPR>, T1, T2> \
    01134     { \
    01135         typedef typename ResultTraits2<EXPR, T1, T2>::Res R1; \
    01136         typedef typename NumericTraits<R1>::RealPromote Res; \
    01137     }; \
    01138     \
    01139     template <class EXPR, class T1, class T2, class T3> \
    01140     struct ResultTraits3<Functor_##function<EXPR>, T1, T2, T3> \
    01141     { \
    01142         typedef typename ResultTraits3<EXPR, T1, T2, T3>::Res R1; \
    01143         typedef typename NumericTraits<R1>::RealPromote Res; \
    01144     }; \
    01145     \
    01146     template <class EXPR> \
    01147     struct Functor_##function \
    01148     { \
    01149         Functor_##function(EXPR const & e) \
    01150         : expr_(e) \
    01151         {} \
    01152          \
    01153         typename ResultTraits0<Functor_##function>::Res \
    01154         operator()() const \
    01155         { \
    01156             return function(expr_()); \
    01157         } \
    01158          \
    01159         template <class T> \
    01160         typename ResultTraits1<Functor_##function, T>::Res \
    01161         operator()(T const & v1) const \
    01162         { \
    01163             return function(expr_(v1)); \
    01164         } \
    01165          \
    01166         template <class T1, class T2> \
    01167         typename ResultTraits2<Functor_##function, T1, T2>::Res \
    01168         operator()(T1 const & v1, T2 const & v2) const \
    01169         { \
    01170             return function(expr_(v1, v2)); \
    01171         } \
    01172          \
    01173         template <class T1, class T2, class T3> \
    01174         typename ResultTraits3<Functor_##function, T1, T2, T3>::Res \
    01175         operator()(T1 const & v1, T2 const & v2, T3 const & v3) const \
    01176         { \
    01177             return function(expr_(v1, v2, v3)); \
    01178         } \
    01179          \
    01180       protected: \
    01181        \
    01182         EXPR expr_; \
    01183        \
    01184       private: \
    01185         Functor_##function & operator=(Functor_##function const &); \
    01186     }; \
    01187      \
    01188     template <class EXPR> \
    01189     inline UnaryFunctor<Functor_##function<UnaryFunctor<EXPR> > > \
    01190     function(UnaryFunctor<EXPR> const & e) \
    01191     { \
    01192         Functor_##function<UnaryFunctor<EXPR> > p(e); \
    01193         return UnaryFunctor<Functor_##function<UnaryFunctor<EXPR> > >(p); \
    01194     }
    01195
    01196 /************************************************************/
    01197
    01198 MAKE_FUNCTOR_UNARY_FUNCTION(sqrt, std)
    01199 MAKE_FUNCTOR_UNARY_FUNCTION(exp, std)
    01200 MAKE_FUNCTOR_UNARY_FUNCTION(log, std)
    01201 MAKE_FUNCTOR_UNARY_FUNCTION(log10, std)
    01202 MAKE_FUNCTOR_UNARY_FUNCTION(sin, std)
    01203 MAKE_FUNCTOR_UNARY_FUNCTION(asin, std)
    01204 MAKE_FUNCTOR_UNARY_FUNCTION(cos, std)
    01205 MAKE_FUNCTOR_UNARY_FUNCTION(acos, std)
    01206 MAKE_FUNCTOR_UNARY_FUNCTION(tan, std)
    01207 MAKE_FUNCTOR_UNARY_FUNCTION(atan, std)
    01208 MAKE_FUNCTOR_UNARY_FUNCTION(floor, std)
    01209 MAKE_FUNCTOR_UNARY_FUNCTION(ceil, std)
    01210 MAKE_FUNCTOR_UNARY_FUNCTION(abs, vigra)
    01211 //MAKE_FUNCTOR_UNARY_FUNCTION(norm, vigra)
    01212 //MAKE_FUNCTOR_UNARY_FUNCTION(squaredNorm, vigra)
    01213
    01214 #undef MAKE_FUNCTOR_UNARY_FUNCTION
    01215
    01216 /************************************************************/
    01217 /*                                                          */
    01218 /*                functors for unary operators              */
    01219 /*                                                          */
    01220 /************************************************************/
    01221
    01222 #define MAKE_FUNCTOR_UNARY_OPERATOR(name, op) \
    01223     template <class EXPR> \
    01224     struct Functor_##name; \
    01225     \
    01226     template <class EXPR> \
    01227     struct ResultTraits0<Functor_##name<EXPR> > \
    01228     { \
    01229         typedef typename ResultTraits0<EXPR>::Res Res; \
    01230     }; \
    01231     \
    01232     template <class EXPR, class T1> \
    01233     struct ResultTraits1<Functor_##name<EXPR>, T1> \
    01234     { \
    01235         typedef typename ResultTraits1<EXPR, T1>::Res Res; \
    01236     }; \
    01237     \
    01238     template <class EXPR, class T1, class T2> \
    01239     struct ResultTraits2<Functor_##name<EXPR>, T1, T2> \
    01240     { \
    01241         typedef typename ResultTraits2<EXPR, T1, T2>::Res Res; \
    01242     }; \
    01243     \
    01244     template <class EXPR, class T1, class T2, class T3> \
    01245     struct ResultTraits3<Functor_##name<EXPR>, T1, T2, T3> \
    01246     { \
    01247         typedef typename ResultTraits3<EXPR, T1, T2, T3>::Res Res; \
    01248     }; \
    01249     \
    01250     template <class EXPR> \
    01251     struct Functor_##name \
    01252     { \
    01253         Functor_##name(EXPR const & e) \
    01254         : expr_(e) \
    01255         {} \
    01256          \
    01257         typename ResultTraits0<Functor_##name>::Res \
    01258         operator()() const \
    01259         { \
    01260             return op expr_(); \
    01261         } \
    01262          \
    01263         template <class T> \
    01264         typename ResultTraits1<Functor_##name, T>::Res \
    01265         operator()(T const & v1) const \
    01266         { \
    01267             return op expr_(v1); \
    01268         } \
    01269          \
    01270         template <class T1, class T2> \
    01271         typename ResultTraits2<Functor_##name, T1, T2>::Res \
    01272         operator()(T1 const & v1, T2 const & v2) const \
    01273         { \
    01274             return op expr_(v1, v2); \
    01275         } \
    01276          \
    01277         template <class T1, class T2, class T3> \
    01278         typename ResultTraits3<Functor_##name, T1, T2, T3>::Res \
    01279         operator()(T1 const & v1, T2 const & v2, T3 const & v3) const \
    01280         { \
    01281             return op expr_(v1, v2, v3); \
    01282         } \
    01283       protected: \
    01284        \
    01285         EXPR expr_; \
    01286        \
    01287       private: \
    01288         Functor_##name & operator=(Functor_##name const &);\
    01289     }; \
    01290      \
    01291     template <class EXPR> \
    01292     inline UnaryFunctor<Functor_##name<UnaryFunctor<EXPR> > > \
    01293     operator op(UnaryFunctor<EXPR> const & e) \
    01294     { \
    01295         Functor_##name<UnaryFunctor<EXPR> > p(e); \
    01296         return UnaryFunctor<Functor_##name<UnaryFunctor<EXPR> > >(p); \
    01297     }
    01298
    01299
    01300 /************************************************************/
    01301
    01302 MAKE_FUNCTOR_UNARY_OPERATOR(minus, -)
    01303 MAKE_FUNCTOR_UNARY_OPERATOR(negate, !)
    01304 MAKE_FUNCTOR_UNARY_OPERATOR(bitNegate, ~)
    01305
    01306 #undef MAKE_FUNCTOR_UNARY_OPERATOR
    01307
    01308 /************************************************************/
    01309 /*                                                          */
    01310 /*               functors for binary functions              */
    01311 /*                                                          */
    01312 /************************************************************/
    01313
    01314 #define MAKE_FUNCTOR_BINARY_FUNCTION(function) \
    01315     using std::function; \
    01316     template <class EXPR1, class EXPR2> \
    01317     struct Functor_##function; \
    01318     \
    01319     template <class EXPR1, class EXPR2> \
    01320     struct ResultTraits0<Functor_##function<EXPR1, EXPR2> > \
    01321     { \
    01322         typedef typename ResultTraits0<EXPR1>::Res R1; \
    01323         typedef typename ResultTraits0<EXPR2>::Res R2; \
    01324         typedef typename PromoteTraits<R1, R2>::Promote R3; \
    01325         typedef typename NumericTraits<R3>::RealPromote Res; \
    01326     }; \
    01327     \
    01328     template <class EXPR1, class EXPR2, class T1> \
    01329     struct ResultTraits1<Functor_##function<EXPR1, EXPR2>, T1> \
    01330     { \
    01331         typedef typename ResultTraits1<EXPR1, T1>::Res R1; \
    01332         typedef typename ResultTraits1<EXPR2, T1>::Res R2; \
    01333         typedef typename PromoteTraits<R1, R2>::Promote R3; \
    01334         typedef typename NumericTraits<R3>::RealPromote Res; \
    01335     }; \
    01336     \
    01337     template <class EXPR1, class EXPR2, class T1, class T2> \
    01338     struct ResultTraits2<Functor_##function<EXPR1, EXPR2>, T1, T2> \
    01339     { \
    01340         typedef typename ResultTraits2<EXPR1, T1, T2>::Res R1; \
    01341         typedef typename ResultTraits2<EXPR2, T1, T2>::Res R2; \
    01342         typedef typename PromoteTraits<R1, R2>::Promote R3; \
    01343         typedef typename NumericTraits<R3>::RealPromote Res; \
    01344     }; \
    01345     \
    01346     template <class EXPR1, class EXPR2, class T1, class T2, class T3> \
    01347     struct ResultTraits3<Functor_##function<EXPR1, EXPR2>, T1, T2, T3> \
    01348     { \
    01349         typedef typename ResultTraits3<EXPR1, T1, T2, T3>::Res R1; \
    01350         typedef typename ResultTraits3<EXPR2, T1, T2, T3>::Res R2; \
    01351         typedef typename PromoteTraits<R1, R2>::Promote R3; \
    01352         typedef typename NumericTraits<R3>::RealPromote Res; \
    01353     }; \
    01354     \
    01355     template <class EXPR1, class EXPR2> \
    01356     struct Functor_##function \
    01357     { \
    01358         Functor_##function(EXPR1 const & e1, EXPR2 const & e2) \
    01359         : expr1_(e1), expr2_(e2) \
    01360         {} \
    01361          \
    01362         typename ResultTraits0<Functor_##function>::Res \
    01363         operator()() const \
    01364         { \
    01365             return function(expr1_(), expr2_()); \
    01366         } \
    01367          \
    01368         template <class T> \
    01369         typename ResultTraits1<Functor_##function, T>::Res \
    01370         operator()(T const & v1) const \
    01371         { \
    01372             return function(expr1_(v1), expr2_(v1)); \
    01373         } \
    01374          \
    01375         template <class T1, class T2> \
    01376         typename ResultTraits2<Functor_##function, T1, T2>::Res \
    01377         operator()(T1 const & v1, T2 const & v2) const \
    01378         { \
    01379             return function(expr1_(v1, v2), expr2_(v1, v2)); \
    01380         } \
    01381          \
    01382         template <class T1, class T2, class T3> \
    01383         typename ResultTraits3<Functor_##function, T1, T2, T3>::Res \
    01384         operator()(T1 const & v1, T2 const & v2, T3 const & v3) const \
    01385         { \
    01386             return function(expr1_(v1, v2, v3), expr2_(v1, v2, v3)); \
    01387         } \
    01388          \
    01389       private: \
    01390          \
    01391         EXPR1 expr1_; \
    01392         EXPR2 expr2_; \
    01393         \
    01394         Functor_##function & operator=(Functor_##function const &); \
    01395     }; \
    01396      \
    01397     template <class EXPR1, class EXPR2> \
    01398     inline UnaryFunctor<Functor_##function<UnaryFunctor<EXPR1>, UnaryFunctor<EXPR2> > > \
    01399     function(UnaryFunctor<EXPR1> const & e1, UnaryFunctor<EXPR2> const & e2) \
    01400     { \
    01401         Functor_##function<UnaryFunctor<EXPR1>, UnaryFunctor<EXPR2> > p(e1, e2); \
    01402         return UnaryFunctor<Functor_##function<UnaryFunctor<EXPR1>,  \
    01403                                         UnaryFunctor<EXPR2> > >(p); \
    01404     }
    01405
    01406 /************************************************************/
    01407
    01408 MAKE_FUNCTOR_BINARY_FUNCTION(pow)
    01409 MAKE_FUNCTOR_BINARY_FUNCTION(atan2)
    01410 MAKE_FUNCTOR_BINARY_FUNCTION(fmod)
    01411
    01412 #undef MAKE_FUNCTOR_BINARY_FUNCTION
    01413
    01414 /************************************************************/
    01415
    01416 #define MAKE_FUNCTOR_MINMAX(name, op) \
    01417     template <class EXPR1, class EXPR2> \
    01418     struct Functor_##name; \
    01419     \
    01420     template <class EXPR1, class EXPR2> \
    01421     struct ResultTraits0<Functor_##name<EXPR1, EXPR2> > \
    01422     { \
    01423         typedef typename ResultTraits0<EXPR1>::Res R1; \
    01424         typedef typename ResultTraits0<EXPR2>::Res R2; \
    01425         typedef typename PromoteTraits<R1, R2>::Promote Res; \
    01426     }; \
    01427     \
    01428     template <class EXPR1, class EXPR2, class T1> \
    01429     struct ResultTraits1<Functor_##name<EXPR1, EXPR2>, T1> \
    01430     { \
    01431         typedef typename ResultTraits1<EXPR1, T1>::Res R1; \
    01432         typedef typename ResultTraits1<EXPR2, T1>::Res R2; \
    01433         typedef typename PromoteTraits<R1, R2>::Promote Res; \
    01434     }; \
    01435     \
    01436     template <class EXPR1, class EXPR2, class T1, class T2> \
    01437     struct ResultTraits2<Functor_##name<EXPR1, EXPR2>, T1, T2> \
    01438     { \
    01439         typedef typename ResultTraits2<EXPR1, T1, T2>::Res R1; \
    01440         typedef typename ResultTraits2<EXPR2, T1, T2>::Res R2; \
    01441         typedef typename PromoteTraits<R1, R2>::Promote Res; \
    01442     }; \
    01443     \
    01444     template <class EXPR1, class EXPR2, class T1, class T2, class T3> \
    01445     struct ResultTraits3<Functor_##name<EXPR1, EXPR2>, T1, T2, T3> \
    01446     { \
    01447         typedef typename ResultTraits3<EXPR1, T1, T2, T3>::Res R1; \
    01448         typedef typename ResultTraits3<EXPR2, T1, T2, T3>::Res R2; \
    01449         typedef typename PromoteTraits<R1, R2>::Promote Res; \
    01450     }; \
    01451     \
    01452     template <class EXPR1, class EXPR2> \
    01453     struct Functor_##name \
    01454     { \
    01455         Functor_##name(EXPR1 const & e1, EXPR2 const & e2) \
    01456         : expr1_(e1), expr2_(e2) \
    01457         {} \
    01458          \
    01459         typename ResultTraits0<Functor_##name>::Res \
    01460         operator()() const \
    01461         { \
    01462             typename \
    01463             ResultTraits0<Functor_##name<EXPR1, EXPR2> >::R1 r1(expr1_()); \
    01464             typename \
    01465             ResultTraits0<Functor_##name<EXPR1, EXPR2> >::R2 r2(expr2_()); \
    01466             return (r1 op r2) ? r1 : r2; \
    01467         } \
    01468          \
    01469         template <class T> \
    01470         typename ResultTraits1<Functor_##name, T>::Res \
    01471         operator()(T const & v1) const \
    01472         { \
    01473             typename \
    01474             ResultTraits1<Functor_##name<EXPR1, EXPR2>, T>::R1 r1(expr1_(v1)); \
    01475             typename \
    01476             ResultTraits1<Functor_##name<EXPR1, EXPR2>, T>::R2 r2(expr2_(v1)); \
    01477             return (r1 op r2) ? r1 : r2; \
    01478         } \
    01479          \
    01480         template <class T1, class T2> \
    01481         typename ResultTraits2<Functor_##name, T1, T2>::Res \
    01482         operator()(T1 const & v1, T2 const & v2) const \
    01483         { \
    01484             typename \
    01485             ResultTraits2<Functor_##name<EXPR1, EXPR2>, T1, T2>::R1 r1(expr1_(v1, v2)); \
    01486             typename \
    01487             ResultTraits2<Functor_##name<EXPR1, EXPR2>, T1, T2>::R2 r2(expr2_(v1, v2)); \
    01488             return (r1 op r2) ? r1 : r2; \
    01489         } \
    01490          \
    01491         template <class T1, class T2, class T3> \
    01492         typename ResultTraits3<Functor_##name, T1, T2, T3>::Res \
    01493         operator()(T1 const & v1, T2 const & v2, T3 const & v3) const \
    01494         { \
    01495             typename \
    01496             ResultTraits3<Functor_##name<EXPR1, EXPR2>, T1, T2, T3>::R1 r1(expr1_(v1, v2, v3)); \
    01497             typename \
    01498             ResultTraits3<Functor_##name<EXPR1, EXPR2>, T1, T2, T3>::R2 r2(expr2_(v1, v2, v3)); \
    01499             return (r1 op r2) ? r1 : r2; \
    01500         } \
    01501          \
    01502       private: \
    01503          \
    01504         EXPR1 expr1_; \
    01505         EXPR2 expr2_; \
    01506         \
    01507         Functor_##name & operator=(Functor_##name const &); \
    01508     }; \
    01509      \
    01510     template <class EXPR1, class EXPR2> \
    01511     inline UnaryFunctor<Functor_##name<UnaryFunctor<EXPR1>, UnaryFunctor<EXPR2> > > \
    01512     name(UnaryFunctor<EXPR1> const & e1, UnaryFunctor<EXPR2> const & e2) \
    01513     { \
    01514         Functor_##name<UnaryFunctor<EXPR1>, UnaryFunctor<EXPR2> > p(e1, e2); \
    01515         return UnaryFunctor<Functor_##name<UnaryFunctor<EXPR1>,  \
    01516                                         UnaryFunctor<EXPR2> > >(p); \
    01517     }
    01518
    01519 MAKE_FUNCTOR_MINMAX(min, <)
    01520 MAKE_FUNCTOR_MINMAX(max, >)
    01521
    01522 #undef MAKE_FUNCTOR_MINMAX
    01523
    01524 /************************************************************/
    01525 /*                                                          */
    01526 /*               functors for binary operators              */
    01527 /*                                                          */
    01528 /************************************************************/
    01529
    01530 #define MAKE_FUNCTOR_BINARY_OPERATOR(name, op) \
    01531     template <class EXPR1, class EXPR2> \
    01532     struct Functor_##name; \
    01533     \
    01534     template <class EXPR1, class EXPR2> \
    01535     struct ResultTraits0<Functor_##name<EXPR1, EXPR2> > \
    01536     { \
    01537         typedef typename ResultTraits0<EXPR1>::Res R1; \
    01538         typedef typename ResultTraits0<EXPR2>::Res R2; \
    01539         typedef typename PromoteTraits<R1, R2>::Promote Res; \
    01540     }; \
    01541     \
    01542     template <class EXPR1, class EXPR2, class T1> \
    01543     struct ResultTraits1<Functor_##name<EXPR1, EXPR2>, T1> \
    01544     { \
    01545         typedef typename ResultTraits1<EXPR1, T1>::Res R1; \
    01546         typedef typename ResultTraits1<EXPR2, T1>::Res R2; \
    01547         typedef typename PromoteTraits<R1, R2>::Promote Res; \
    01548     }; \
    01549     \
    01550     template <class EXPR1, class EXPR2, class T1, class T2> \
    01551     struct ResultTraits2<Functor_##name<EXPR1, EXPR2>, T1, T2> \
    01552     { \
    01553         typedef typename ResultTraits2<EXPR1, T1, T2>::Res R1; \
    01554         typedef typename ResultTraits2<EXPR2, T1, T2>::Res R2; \
    01555         typedef typename PromoteTraits<R1, R2>::Promote Res; \
    01556     }; \
    01557     \
    01558     template <class EXPR1, class EXPR2, class T1, class T2, class T3> \
    01559     struct ResultTraits3<Functor_##name<EXPR1, EXPR2>, T1, T2, T3> \
    01560     { \
    01561         typedef typename ResultTraits3<EXPR1, T1, T2, T3>::Res R1; \
    01562         typedef typename ResultTraits3<EXPR2, T1, T2, T3>::Res R2; \
    01563         typedef typename PromoteTraits<R1, R2>::Promote Res; \
    01564     }; \
    01565     \
    01566     template <class EXPR1, class EXPR2> \
    01567     struct Functor_##name \
    01568     { \
    01569         Functor_##name(EXPR1 const & e1, EXPR2 const & e2) \
    01570         : expr1_(e1), expr2_(e2) \
    01571         {} \
    01572          \
    01573         typename ResultTraits0<Functor_##name>::Res \
    01574         operator()() const \
    01575         { \
    01576             return expr1_() op expr2_(); \
    01577         } \
    01578          \
    01579         template <class T> \
    01580         typename ResultTraits1<Functor_##name, T>::Res \
    01581         operator()(T const & v1) const \
    01582         { \
    01583             return expr1_(v1) op expr2_(v1); \
    01584         } \
    01585          \
    01586         template <class T1, class T2> \
    01587         typename ResultTraits2<Functor_##name, T1, T2>::Res \
    01588         operator()(T1 const & v1, T2 const & v2) const \
    01589         { \
    01590             return expr1_(v1, v2) op expr2_(v1, v2); \
    01591         } \
    01592          \
    01593         template <class T1, class T2, class T3> \
    01594         typename ResultTraits3<Functor_##name, T1, T2, T3>::Res \
    01595         operator()(T1 const & v1, T2 const & v2, T3 const & v3) const \
    01596         { \
    01597             return expr1_(v1, v2, v3) op expr2_(v1, v2, v3); \
    01598         } \
    01599          \
    01600       private: \
    01601          \
    01602         EXPR1 expr1_; \
    01603         EXPR2 expr2_; \
    01604         \
    01605         Functor_##name & operator=(Functor_##name const &); \
    01606     }; \
    01607      \
    01608     template <class EXPR1, class EXPR2> \
    01609     inline UnaryFunctor<Functor_##name<UnaryFunctor<EXPR1>, UnaryFunctor<EXPR2> > > \
    01610     operator op(UnaryFunctor<EXPR1> const & e1, UnaryFunctor<EXPR2> const & e2) \
    01611     { \
    01612         Functor_##name<UnaryFunctor<EXPR1>, UnaryFunctor<EXPR2> > p(e1, e2); \
    01613         return UnaryFunctor<Functor_##name<UnaryFunctor<EXPR1>,  \
    01614                                         UnaryFunctor<EXPR2> > >(p); \
    01615     }
    01616
    01617 /************************************************************/
    01618
    01619 MAKE_FUNCTOR_BINARY_OPERATOR(add, +)
    01620 MAKE_FUNCTOR_BINARY_OPERATOR(subtract, -)
    01621 MAKE_FUNCTOR_BINARY_OPERATOR(multiply, *)
    01622 MAKE_FUNCTOR_BINARY_OPERATOR(divide, /)
    01623 MAKE_FUNCTOR_BINARY_OPERATOR(modulo, %)
    01624 MAKE_FUNCTOR_BINARY_OPERATOR(bitAnd, &)
    01625 MAKE_FUNCTOR_BINARY_OPERATOR(bitOr, |)
    01626 MAKE_FUNCTOR_BINARY_OPERATOR(bitXor, ^)
    01627
    01628 #undef MAKE_FUNCTOR_BINARY_OPERATOR
    01629
    01630 /************************************************************/
    01631
    01632 #define MAKE_FUNCTOR_BINARY_OPERATOR_BOOL(name, op) \
    01633     template <class EXPR1, class EXPR2> \
    01634     struct Functor_##name; \
    01635     \
    01636     template <class EXPR1, class EXPR2> \
    01637     struct ResultTraits0<Functor_##name<EXPR1, EXPR2> > \
    01638     { \
    01639         typedef bool Res; \
    01640     }; \
    01641     \
    01642     template <class EXPR1, class EXPR2, class T1> \
    01643     struct ResultTraits1<Functor_##name<EXPR1, EXPR2>, T1> \
    01644     { \
    01645         typedef bool Res; \
    01646     }; \
    01647     \
    01648     template <class EXPR1, class EXPR2, class T1, class T2> \
    01649     struct ResultTraits2<Functor_##name<EXPR1, EXPR2>, T1, T2> \
    01650     { \
    01651         typedef bool Res; \
    01652     }; \
    01653     \
    01654     template <class EXPR1, class EXPR2, class T1, class T2, class T3> \
    01655     struct ResultTraits3<Functor_##name<EXPR1, EXPR2>, T1, T2, T3> \
    01656     { \
    01657         typedef bool Res; \
    01658     }; \
    01659     \
    01660     template <class EXPR1, class EXPR2> \
    01661     struct Functor_##name \
    01662     { \
    01663         Functor_##name(EXPR1 const & e1, EXPR2 const & e2) \
    01664         : expr1_(e1), expr2_(e2) \
    01665         {} \
    01666          \
    01667         bool operator()() const \
    01668         { \
    01669             return expr1_() op expr2_(); \
    01670         } \
    01671          \
    01672         template <class T> \
    01673         bool operator()(T const & v1) const \
    01674         { \
    01675             return expr1_(v1) op expr2_(v1); \
    01676         } \
    01677          \
    01678         template <class T1, class T2> \
    01679         bool operator()(T1 const & v1, T2 const & v2) const \
    01680         { \
    01681             return expr1_(v1, v2) op expr2_(v1, v2); \
    01682         } \
    01683          \
    01684         template <class T1, class T2, class T3> \
    01685         bool operator()(T1 const & v1, T2 const & v2, T3 const & v3) const \
    01686         { \
    01687             return expr1_(v1, v2, v3) op expr2_(v1, v2, v3); \
    01688         } \
    01689          \
    01690       private: \
    01691          \
    01692         EXPR1 expr1_; \
    01693         EXPR2 expr2_; \
    01694         \
    01695         Functor_##name & operator=(Functor_##name const &); \
    01696     }; \
    01697      \
    01698     template <class EXPR1, class EXPR2> \
    01699     inline UnaryFunctor<Functor_##name<UnaryFunctor<EXPR1>, UnaryFunctor<EXPR2> > > \
    01700     operator op(UnaryFunctor<EXPR1> const & e1, UnaryFunctor<EXPR2> const & e2) \
    01701     { \
    01702         Functor_##name<UnaryFunctor<EXPR1>, UnaryFunctor<EXPR2> > p(e1, e2); \
    01703         return UnaryFunctor<Functor_##name<UnaryFunctor<EXPR1>,  \
    01704                                         UnaryFunctor<EXPR2> > >(p); \
    01705     }
    01706
    01707 /************************************************************/
    01708
    01709 MAKE_FUNCTOR_BINARY_OPERATOR_BOOL(equals, ==)
    01710 MAKE_FUNCTOR_BINARY_OPERATOR_BOOL(differs, !=)
    01711 MAKE_FUNCTOR_BINARY_OPERATOR_BOOL(less, <)
    01712 MAKE_FUNCTOR_BINARY_OPERATOR_BOOL(lessEqual, <=)
    01713 MAKE_FUNCTOR_BINARY_OPERATOR_BOOL(greater, >)
    01714 MAKE_FUNCTOR_BINARY_OPERATOR_BOOL(greaterEqual, >=)
    01715 MAKE_FUNCTOR_BINARY_OPERATOR_BOOL(and, &&)
    01716 MAKE_FUNCTOR_BINARY_OPERATOR_BOOL(or, ||)
    01717
    01718 #undef MAKE_FUNCTOR_BINARY_OPERATOR_BOOL
    01719
    01720 /************************************************************/
    01721 /*                                                          */
    01722 /*                         unary apply                      */
    01723 /*                                                          */
    01724 /************************************************************/
    01725
    01726 template <class EXPR, class RES, class ARG>
    01727 struct UnaryFctPtrFunctor
    01728 {
    01729     UnaryFctPtrFunctor(EXPR const & e, RES (*fct)(ARG))
    01730     : expr_(e), f_(fct)
    01731     {}
    01732
    01733     RES operator()() const
    01734     {
    01735         return f_(expr_());
    01736     }
    01737
    01738     template <class T>
    01739     RES operator()(T const & v1) const
    01740     {
    01741         return f_(expr_(v1));
    01742     }
    01743
    01744     template <class T1, class T2>
    01745     RES operator()(T1 const & v1, T2 const & v2) const
    01746     {
    01747         return f_(expr_(v1, v2));
    01748     }
    01749
    01750     template <class T1, class T2, class T3>
    01751     RES operator()(T1 const & v1, T2 const & v2, T3 const & v3) const
    01752     {
    01753         return f_(expr_(v1, v2, v3));
    01754     }
    01755   protected:
    01756
    01757     EXPR expr_;
    01758     RES (*f_)(ARG);
    01759
    01760   private:
    01761     UnaryFctPtrFunctor & operator=(UnaryFctPtrFunctor const &); // not implemented
    01762 };
    01763
    01764 template <class EXPR, class RES, class ARG>
    01765 struct ResultTraits0<UnaryFctPtrFunctor<EXPR, RES, ARG> >
    01766 {
    01767     typedef RES Res;
    01768 };
    01769
    01770 template <class EXPR, class RES, class ARG, class T1>
    01771 struct ResultTraits1<UnaryFctPtrFunctor<EXPR, RES, ARG>, T1>
    01772 {
    01773     typedef RES Res;
    01774 };
    01775
    01776 template <class EXPR, class RES, class ARG, class T1, class T2>
    01777 struct ResultTraits2<UnaryFctPtrFunctor<EXPR, RES, ARG>, T1, T2>
    01778 {
    01779     typedef RES Res;
    01780 };
    01781
    01782 template <class EXPR, class RES, class ARG, class T1, class T2, class T3>
    01783 struct ResultTraits3<UnaryFctPtrFunctor<EXPR, RES, ARG>, T1, T2, T3>
    01784 {
    01785     typedef RES Res;
    01786 };
    01787
    01788 template <class EXPR, class RES, class ARG>
    01789 inline UnaryFunctor<UnaryFctPtrFunctor<UnaryFunctor<EXPR>, RES, ARG> >
    01790 applyFct(RES (*f)(ARG), UnaryFunctor<EXPR> const & e)
    01791 {
    01792     UnaryFctPtrFunctor<UnaryFunctor<EXPR>, RES, ARG> p(e, f);
    01793     return UnaryFunctor<UnaryFctPtrFunctor<UnaryFunctor<EXPR>, RES, ARG> >(p);
    01794 }
    01795
    01796 /************************************************************/
    01797 /*                                                          */
    01798 /*                        binary apply                      */
    01799 /*                                                          */
    01800 /************************************************************/
    01801
    01802 template <class EXPR1, class EXPR2, class RES, class ARG1, class ARG2>
    01803 struct BinaryFctPtrFunctor
    01804 {
    01805     BinaryFctPtrFunctor(EXPR1 const & e1, EXPR2 const & e2,
    01806                         RES (*f)(ARG1, ARG2))
    01807     : expr1_(e1), expr2_(e2), f_(f)
    01808     {}
    01809
    01810     RES operator()() const
    01811     {
    01812         return f_(expr1_(), expr2_());
    01813     }
    01814
    01815     template <class T>
    01816     RES operator()(T const & v1) const
    01817     {
    01818         return f_(expr1_(v1), expr2_(v1));
    01819     }
    01820
    01821     template <class T1, class T2>
    01822     RES operator()(T1 const & v1, T2 const & v2) const
    01823     {
    01824         return f_(expr1_(v1, v2), expr2_(v1, v2));
    01825     }
    01826
    01827     template <class T1, class T2, class T3>
    01828     RES operator()(T1 const & v1, T2 const & v2, T3 const & v3) const
    01829     {
    01830         return f_(expr1_(v1, v2, v3), expr2_(v1, v2, v3));
    01831     }
    01832
    01833   protected:
    01834
    01835     EXPR1 expr1_;
    01836     EXPR2 expr2_;
    01837     RES (*f_)(ARG1, ARG2);
    01838
    01839   private:
    01840     BinaryFctPtrFunctor & operator=(BinaryFctPtrFunctor const &); // not implemented
    01841 };
    01842
    01843 template <class EXPR1, class EXPR2, class RES, class ARG1, class ARG2>
    01844 struct ResultTraits0<BinaryFctPtrFunctor<EXPR1, EXPR2, RES, ARG1, ARG2> >
    01845 {
    01846     typedef RES Res;
    01847 };
    01848
    01849 template <class EXPR1, class EXPR2, class RES, class ARG1, class ARG2,
    01850           class T1>
    01851 struct ResultTraits1<BinaryFctPtrFunctor<EXPR1, EXPR2, RES, ARG1, ARG2>, T1>
    01852 {
    01853     typedef RES Res;
    01854 };
    01855
    01856 template <class EXPR1, class EXPR2, class RES, class ARG1, class ARG2,
    01857           class T1, class T2>
    01858 struct ResultTraits2<BinaryFctPtrFunctor<EXPR1, EXPR2, RES, ARG1, ARG2>, T1, T2>
    01859 {
    01860     typedef RES Res;
    01861 };
    01862
    01863 template <class EXPR1, class EXPR2, class RES, class ARG1, class ARG2,
    01864           class T1, class T2, class T3>
    01865 struct ResultTraits3<BinaryFctPtrFunctor<EXPR1, EXPR2, RES, ARG1, ARG2>, T1, T2, T3>
    01866 {
    01867     typedef RES Res;
    01868 };
    01869
    01870 template <class EXPR1, class EXPR2, class RES, class ARG1, class ARG2>
    01871 inline UnaryFunctor<BinaryFctPtrFunctor<UnaryFunctor<EXPR1>,
    01872                                  UnaryFunctor<EXPR2>,
    01873                                  RES, ARG1, ARG2> >
    01874 applyFct(RES (*f)(ARG1, ARG2), UnaryFunctor<EXPR1> const & e1,
    01875          UnaryFunctor<EXPR2> const & e2)
    01876 {
    01877     BinaryFctPtrFunctor<UnaryFunctor<EXPR1>,
    01878                         UnaryFunctor<EXPR2>,
    01879                         RES, ARG1, ARG2>  p(e1, e2, f);
    01880     return UnaryFunctor<BinaryFctPtrFunctor<UnaryFunctor<EXPR1>,
    01881                                             UnaryFunctor<EXPR2>,
    01882                                             RES, ARG1, ARG2> >(p);
    01883 }
    01884
    01885 /************************************************************/
    01886 /*                                                          */
    01887 /*                      comma operator                      */
    01888 /*                                                          */
    01889 /************************************************************/
    01890
    01891 template <class EXPR1, class EXPR2>
    01892 struct CommaFunctor
    01893 {
    01894     CommaFunctor(EXPR1 const & e1, EXPR2 const & e2)
    01895     : expr1_(e1), expr2_(e2)
    01896     {}
    01897
    01898     typename ResultTraits0<EXPR2>::Res
    01899     operator()() const
    01900     {
    01901         expr1_();
    01902         return expr2_();
    01903     }
    01904
    01905     template <class T>
    01906     typename ResultTraits1<EXPR2, T>::Res
    01907     operator()(T const & v1) const
    01908     {
    01909         expr1_(v1);
    01910         return expr2_(v1);
    01911     }
    01912
    01913     template <class T1, class T2>
    01914     typename ResultTraits2<EXPR2, T1, T2>::Res
    01915     operator()(T1 const & v1, T2 const & v2) const
    01916     {
    01917         expr1_(v1, v2);
    01918         return expr2_(v1, v2);
    01919     }
    01920
    01921     template <class T1, class T2, class T3>
    01922     typename ResultTraits3<EXPR2, T1, T2, T3>::Res
    01923     operator()(T1 const & v1, T2 const & v2, T3 const & v3) const
    01924     {
    01925         expr1_(v1, v2, v3);
    01926         return expr2_(v1, v2, v3);
    01927     }
    01928
    01929   protected:
    01930
    01931     EXPR1 expr1_;
    01932     EXPR2 expr2_;
    01933
    01934   private:
    01935     CommaFunctor & operator=(CommaFunctor const &); // not implemented
    01936 };
    01937
    01938 template <class Expr1, class Expr2>
    01939 struct ResultTraits0<CommaFunctor<Expr1, Expr2> >
    01940 {
    01941     typedef typename ResultTraits0<Expr2>::Res Res;
    01942 };
    01943
    01944 template <class Expr1, class Expr2, class T1>
    01945 struct ResultTraits1<CommaFunctor<Expr1, Expr2>, T1>
    01946 {
    01947     typedef typename ResultTraits1<Expr2, T1>::Res Res;
    01948 };
    01949
    01950 template <class Expr1, class Expr2, class T1, class T2>
    01951 struct ResultTraits2<CommaFunctor<Expr1, Expr2>, T1, T2>
    01952 {
    01953     typedef typename ResultTraits2<Expr2, T1, T2>::Res Res;
    01954 };
    01955
    01956 template <class Expr1, class Expr2, class T1, class T2, class T3>
    01957 struct ResultTraits3<CommaFunctor<Expr1, Expr2>, T1, T2, T3>
    01958 {
    01959     typedef typename ResultTraits3<Expr2, T1, T2, T3>::Res Res;
    01960 };
    01961
    01962 template <class EXPR1, class EXPR2>
    01963 inline UnaryFunctor<CommaFunctor<UnaryAnalyser<EXPR1>,
    01964                             UnaryFunctor<EXPR2> > >
    01965 operator,(UnaryAnalyser<EXPR1> const & e1,
    01966           UnaryFunctor<EXPR2> const & e2)
    01967 {
    01968     CommaFunctor<UnaryAnalyser<EXPR1>,
    01969                             UnaryFunctor<EXPR2> >  p(e1, e2);
    01970     return UnaryFunctor<CommaFunctor<UnaryAnalyser<EXPR1>,
    01971                             UnaryFunctor<EXPR2> > >(p);
    01972 }
    01973
    01974 /************************************************************/
    01975
    01976 template <class EXPR1, class EXPR2>
    01977 struct CommaAnalyser
    01978 {
    01979     CommaAnalyser(EXPR1 const & e1, EXPR2 const & e2)
    01980     : expr1_(e1), expr2_(e2)
    01981     {}
    01982
    01983     void operator()() const
    01984     {
    01985         expr1_();
    01986         expr2_();
    01987     }
    01988
    01989     template <class T>
    01990     void operator()(T const & v1) const
    01991     {
    01992         expr1_(v1);
    01993         expr2_(v1);
    01994     }
    01995
    01996     template <class T1, class T2>
    01997     void operator()(T1 const & v1, T2 const & v2) const
    01998     {
    01999         expr1_(v1, v2);
    02000         expr2_(v1, v2);
    02001     }
    02002
    02003     template <class T1, class T2, class T3>
    02004     void operator()(T1 const & v1, T2 const & v2, T3 const & v3) const
    02005     {
    02006         expr1_(v1, v2, v3);
    02007         expr2_(v1, v2, v3);
    02008     }
    02009
    02010   protected:
    02011
    02012     EXPR1 expr1_;
    02013     EXPR2 expr2_;
    02014
    02015   private:
    02016     CommaAnalyser & operator=(CommaAnalyser const &); // not implemented
    02017 };
    02018
    02019 template <class EXPR1, class EXPR2>
    02020 inline UnaryAnalyser<CommaAnalyser<UnaryAnalyser<EXPR1>,
    02021                             UnaryAnalyser<EXPR2> > >
    02022 operator,(UnaryAnalyser<EXPR1> const & e1,
    02023           UnaryAnalyser<EXPR2> const & e2)
    02024 {
    02025     CommaAnalyser<UnaryAnalyser<EXPR1>,
    02026                             UnaryAnalyser<EXPR2> >  p(e1, e2);
    02027     return UnaryAnalyser<CommaAnalyser<UnaryAnalyser<EXPR1>,
    02028                             UnaryAnalyser<EXPR2> > >(p);
    02029 }
    02030
    02031 } // namespace functor
    02032
    02033 #if defined(__GNUC__) &&  __GNUC__ < 3
    02034 using functor::Arg1;
    02035 using functor::Arg2;
    02036 using functor::Arg3;
    02037 using functor::Param;
    02038 #endif
    02039
    02040 template <class T>
    02041 class FunctorTraits<functor::UnaryFunctor<T> >
    02042 : public FunctorTraitsBase<functor::UnaryFunctor<T> >
    02043 {
    02044   public:
    02045     typedef VigraTrueType isInitializer;
    02046     typedef VigraTrueType isUnaryFunctor;
    02047     typedef VigraTrueType isBinaryFunctor;
    02048     typedef VigraTrueType isTernaryFunctor;
    02049 };
    02050
    02051 template <class T>
    02052 class FunctorTraits<functor::UnaryAnalyser<T> >
    02053 : public FunctorTraitsBase<functor::UnaryAnalyser<T> >
    02054 {
    02055   public:
    02056     typedef VigraTrueType isUnaryAnalyser;
    02057     typedef VigraTrueType isBinaryAnalyser;
    02058     typedef VigraTrueType isTernaryAnalyser;
    02059 };
    02060
    02061
    02062
    02063 } // namespace vigra
    02064
    02065 #endif /* NO_PARTIAL_TEMPLATE_SPECIALIZATION */
    02066
    02067 #endif // DOXYGEN
    02068
    02069 #endif /* VIGRA_FUNCTOREXPRESSION_HXX  */
    02070
    02071

© 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.6.0 (13 Aug 2008)