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

© Ullrich Köthe (koethe@informatik.uni-hamburg.de) Cognitive Systems Group, University of Hamburg, Germany | html generated using doxygen and Python VIGRA 1.3.2 (27 Jan 2005)