VIGRA - vigra/functorexpression.hxx Source File

[ 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.5.0, Dec 07 2006 )                                    */
    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 /*        koethe@informatik.uni-hamburg.de          or                  */
    00012 /*        vigra@kogs1.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
    00416 template <class Expr>
    00417 struct ResultTraits0<UnaryFunctor<Expr> >
    00418 {
    00419     typedef typename ResultTraits0<Expr>::Res Res;
    00420 };
    00421
    00422 template <class Expr, class T1>
    00423 struct ResultTraits1<UnaryFunctor<Expr>, T1>
    00424 {
    00425     typedef typename ResultTraits1<Expr, T1>::Res Res;
    00426 };
    00427
    00428 template <class Expr, class T1, class T2>
    00429 struct ResultTraits2<UnaryFunctor<Expr>, T1, T2>
    00430 {
    00431     typedef typename ResultTraits2<Expr, T1, T2>::Res Res;
    00432 };
    00433
    00434 template <class Expr, class T1, class T2, class T3>
    00435 struct ResultTraits3<UnaryFunctor<Expr>, T1, T2, T3>
    00436 {
    00437     typedef typename ResultTraits3<Expr, T1, T2, T3>::Res Res;
    00438 };
    00439
    00440 /************************************************************/
    00441 /*                                                          */
    00442 /*                 unary functors for arguments             */
    00443 /*                                                          */
    00444 /************************************************************/
    00445
    00446 struct ArgumentFunctor1;
    00447 struct ArgumentFunctor2;
    00448 struct ArgumentFunctor3;
    00449
    00450 template <>
    00451 struct UnaryFunctor<ArgumentFunctor1>
    00452 {
    00453     UnaryFunctor()
    00454     {}
    00455
    00456     template <class T1>
    00457     T1 const & operator()(T1 const & v1) const
    00458     {
    00459         return v1;
    00460     }
    00461
    00462     template <class T1, class T2>
    00463     T1 const & operator()(T1 const & v1, T2 const &) const
    00464     {
    00465         return v1;
    00466     }
    00467
    00468     template <class T1, class T2, class T3>
    00469     T1 const & operator()(T1 const & v1, T2 const &, T3 const &) const
    00470     {
    00471         return v1;
    00472     }
    00473 };
    00474
    00475 template <>
    00476 struct ResultTraits0<UnaryFunctor<ArgumentFunctor1> >
    00477 {
    00478     typedef ErrorType Res;
    00479 };
    00480
    00481 template <class T1>
    00482 struct ResultTraits1<UnaryFunctor<ArgumentFunctor1>, T1>
    00483 {
    00484     typedef T1 Res;
    00485 };
    00486
    00487 template <class T1, class T2>
    00488 struct ResultTraits2<UnaryFunctor<ArgumentFunctor1>, T1, T2>
    00489 {
    00490     typedef T1 Res;
    00491 };
    00492
    00493 template <class T1, class T2, class T3>
    00494 struct ResultTraits3<UnaryFunctor<ArgumentFunctor1>, T1, T2, T3>
    00495 {
    00496     typedef T1 Res;
    00497 };
    00498
    00499 /************************************************************/
    00500
    00501 inline
    00502 UnaryFunctor<ArgumentFunctor1>
    00503 Arg1()
    00504 {
    00505     return UnaryFunctor<ArgumentFunctor1>();
    00506 }
    00507
    00508 /************************************************************/
    00509
    00510 template <>
    00511 struct UnaryFunctor<ArgumentFunctor2>
    00512 {
    00513     UnaryFunctor()
    00514     {}
    00515
    00516     template <class T1, class T2>
    00517     T2 const & operator()(T1 const &, T2 const & v2) const
    00518     {
    00519         return v2;
    00520     }
    00521
    00522     template <class T1, class T2, class T3>
    00523     T2 const & operator()(T1 const &, T2 const & v2, T3 const &) const
    00524     {
    00525         return v2;
    00526     }
    00527 };
    00528
    00529 template <>
    00530 struct ResultTraits0<UnaryFunctor<ArgumentFunctor2> >
    00531 {
    00532     typedef ErrorType Res;
    00533 };
    00534
    00535 template <class T1>
    00536 struct ResultTraits1<UnaryFunctor<ArgumentFunctor2>, T1>
    00537 {
    00538     typedef ErrorType Res;
    00539 };
    00540
    00541 template <class T1, class T2>
    00542 struct ResultTraits2<UnaryFunctor<ArgumentFunctor2>, T1, T2>
    00543 {
    00544     typedef T2 Res;
    00545 };
    00546
    00547 template <class T1, class T2, class T3>
    00548 struct ResultTraits3<UnaryFunctor<ArgumentFunctor2>, T1, T2, T3>
    00549 {
    00550     typedef T2 Res;
    00551 };
    00552
    00553 /************************************************************/
    00554
    00555 inline
    00556 UnaryFunctor<ArgumentFunctor2>
    00557 Arg2()
    00558 {
    00559     return UnaryFunctor<ArgumentFunctor2>();
    00560 }
    00561
    00562 /************************************************************/
    00563
    00564 template <>
    00565 struct UnaryFunctor<ArgumentFunctor3>
    00566 {
    00567     UnaryFunctor()
    00568     {}
    00569
    00570     template <class T1, class T2, class T3>
    00571     T3 const & operator()(T1 const &, T2 const &, T3 const & v3) const
    00572     {
    00573         return v3;
    00574     }
    00575 };
    00576
    00577 template <>
    00578 struct ResultTraits0<UnaryFunctor<ArgumentFunctor3> >
    00579 {
    00580     typedef ErrorType Res;
    00581 };
    00582
    00583 template <class T1>
    00584 struct ResultTraits1<UnaryFunctor<ArgumentFunctor3>, T1>
    00585 {
    00586     typedef ErrorType Res;
    00587 };
    00588
    00589 template <class T1, class T2>
    00590 struct ResultTraits2<UnaryFunctor<ArgumentFunctor3>, T1, T2>
    00591 {
    00592     typedef ErrorType Res;
    00593 };
    00594
    00595 template <class T1, class T2, class T3>
    00596 struct ResultTraits3<UnaryFunctor<ArgumentFunctor3>, T1, T2, T3>
    00597 {
    00598     typedef T3 Res;
    00599 };
    00600
    00601 /************************************************************/
    00602
    00603 inline
    00604 UnaryFunctor<ArgumentFunctor3>
    00605 Arg3()
    00606 {
    00607     return UnaryFunctor<ArgumentFunctor3>();
    00608 }
    00609
    00610 /************************************************************/
    00611 /*                                                          */
    00612 /*                    constant parameters                   */
    00613 /*                                                          */
    00614 /************************************************************/
    00615
    00616 template <class T>
    00617 struct ParameterFunctor
    00618 {
    00619     ParameterFunctor(T v)
    00620     : value_(v)
    00621     {}
    00622
    00623     T const & operator()() const
    00624     {
    00625         return value_;
    00626     }
    00627
    00628     template <class U1>
    00629     T const & operator()(U1 const &) const
    00630     {
    00631         return value_;
    00632     }
    00633
    00634     template <class U1, class U2>
    00635     T const & operator()(U1 const &, U2 const &) const
    00636     {
    00637         return value_;
    00638     }
    00639
    00640     template <class U1, class U2, class U3>
    00641     T const & operator()(U1 const &, U2 const &, U3 const &) const
    00642     {
    00643         return value_;
    00644     }
    00645
    00646   protected:
    00647     T value_;
    00648 };
    00649
    00650 template <class T>
    00651 struct ResultTraits0<ParameterFunctor<T> >
    00652 {
    00653     typedef T Res;
    00654 };
    00655
    00656 template <class T, class T1>
    00657 struct ResultTraits1<ParameterFunctor<T>, T1>
    00658 {
    00659     typedef T Res;
    00660 };
    00661
    00662 template <class T, class T1, class T2>
    00663 struct ResultTraits2<ParameterFunctor<T>, T1, T2>
    00664 {
    00665     typedef T Res;
    00666 };
    00667
    00668 template <class T, class T1, class T2, class T3>
    00669 struct ResultTraits3<ParameterFunctor<T>, T1, T2, T3>
    00670 {
    00671     typedef T Res;
    00672 };
    00673
    00674 template <class T>
    00675 UnaryFunctor<ParameterFunctor<T> >
    00676 Param(T const & v)
    00677 {
    00678     ParameterFunctor<T> fv(v);
    00679     return UnaryFunctor<ParameterFunctor<T> >(fv);
    00680 }
    00681
    00682 /************************************************************/
    00683 /*                                                          */
    00684 /*                unary analyser base template              */
    00685 /*                                                          */
    00686 /************************************************************/
    00687
    00688
    00689 template <class EXPR>
    00690 class UnaryAnalyser
    00691 {
    00692   public:
    00693     UnaryAnalyser(EXPR const & e)
    00694     : expr_(e)
    00695     {}
    00696
    00697     void operator()() const
    00698     {
    00699         expr_();
    00700     }
    00701
    00702     template <class T1>
    00703     void operator()(T1 const & v) const
    00704     {
    00705         expr_(v);
    00706     }
    00707
    00708     template <class T1, class T2>
    00709     void operator()(T1 const & v1, T2 const & v2) const
    00710     {
    00711         expr_(v1, v2);
    00712     }
    00713
    00714     template <class T1, class T2, class T3>
    00715     void operator()(T1 const & v1, T2 const & v2, T3 const & v3) const
    00716     {
    00717         expr_(v1, v2, v3);
    00718     }
    00719   protected:
    00720
    00721     EXPR expr_;
    00722 };
    00723
    00724 /************************************************************/
    00725 /*                                                          */
    00726 /*                     variable assignment                  */
    00727 /*                                                          */
    00728 /************************************************************/
    00729
    00730 template <class T>
    00731 struct VarFunctor;
    00732
    00733 template <class T>
    00734 struct UnaryFunctor<VarFunctor<T> >;
    00735
    00736 /************************************************************/
    00737
    00738 #define MAKE_ASSIGNMENT_FUNCTOR(name, op) \
    00739     template <class V, class EXPR> \
    00740     struct AssignmentFunctor_##name \
    00741     { \
    00742         AssignmentFunctor_##name(UnaryFunctor<VarFunctor<V> > v,  \
    00743                                  UnaryFunctor<EXPR> const & e) \
    00744         : value_(v.value_), expr_(e) \
    00745         {} \
    00746          \
    00747         V & operator()() const \
    00748         { \
    00749             const_cast<V &>(value_) op expr_(); \
    00750             return const_cast<V &>(value_); \
    00751         } \
    00752          \
    00753         template <class T1>  \
    00754         V & operator()(T1 const & v1) const \
    00755         { \
    00756             const_cast<V &>(value_) op expr_(v1); \
    00757             return const_cast<V &>(value_); \
    00758         } \
    00759          \
    00760         template <class T1, class T2>  \
    00761         V & operator()(T1 const & v1, T2 const & v2) const \
    00762         { \
    00763             const_cast<V &>(value_) op expr_(v1, v2); \
    00764             return const_cast<V &>(value_); \
    00765         } \
    00766          \
    00767         template <class T1, class T2, class T3>  \
    00768         V & operator()(T1 const & v1, T2 const & v2, T3 const & v3) const \
    00769         { \
    00770             const_cast<V &>(value_) op expr_(v1, v2, v3); \
    00771             return const_cast<V &>(value_); \
    00772         } \
    00773          \
    00774       private: \
    00775         V & value_; \
    00776         UnaryFunctor<EXPR> expr_; \
    00777     };
    00778
    00779 /************************************************************/
    00780
    00781 MAKE_ASSIGNMENT_FUNCTOR(assign, =)
    00782 MAKE_ASSIGNMENT_FUNCTOR(add, +=)
    00783 MAKE_ASSIGNMENT_FUNCTOR(subtract, -=)
    00784 MAKE_ASSIGNMENT_FUNCTOR(multiply, *=)
    00785 MAKE_ASSIGNMENT_FUNCTOR(divide, /=)
    00786
    00787 #undef MAKE_ASSIGNMENT_FUNCTOR
    00788
    00789 /************************************************************/
    00790 /*                                                          */
    00791 /*                          variables                       */
    00792 /*                                                          */
    00793 /************************************************************/
    00794
    00795 template <class T>
    00796 struct UnaryFunctor<VarFunctor<T> >
    00797 {
    00798     typedef T Res;
    00799
    00800     UnaryFunctor(T & v)
    00801     : value_(v)
    00802     {}
    00803
    00804     template <class EXPR>
    00805     UnaryAnalyser< AssignmentFunctor_assign<T, UnaryFunctor<EXPR> > >
    00806     operator=(UnaryFunctor<EXPR> const & e)
    00807     {
    00808         AssignmentFunctor_assign<T, UnaryFunctor<EXPR> > va(*this, e);
    00809         return UnaryAnalyser< AssignmentFunctor_assign<T, UnaryFunctor<EXPR> > >(va);
    00810     }
    00811
    00812     template <class EXPR>
    00813     UnaryAnalyser< AssignmentFunctor_add<T, UnaryFunctor<EXPR> > >
    00814     operator+=(UnaryFunctor<EXPR> const & e)
    00815     {
    00816         AssignmentFunctor_add<T, UnaryFunctor<EXPR> > va(*this, e);
    00817         return UnaryAnalyser< AssignmentFunctor_add<T, UnaryFunctor<EXPR> > >(va);
    00818     }
    00819
    00820     template <class EXPR>
    00821     UnaryAnalyser< AssignmentFunctor_subtract<T, UnaryFunctor<EXPR> > >
    00822     operator-=(UnaryFunctor<EXPR> const & e)
    00823     {
    00824         AssignmentFunctor_subtract<T, UnaryFunctor<EXPR> > va(*this, e);
    00825         return UnaryAnalyser< AssignmentFunctor_subtract<T, UnaryFunctor<EXPR> > >(va);
    00826     }
    00827
    00828     template <class EXPR>
    00829     UnaryAnalyser< AssignmentFunctor_multiply<T, UnaryFunctor<EXPR> > >
    00830     operator*=(UnaryFunctor<EXPR> const & e)
    00831     {
    00832         AssignmentFunctor_multiply<T, UnaryFunctor<EXPR> > va(*this, e);
    00833         return UnaryAnalyser< AssignmentFunctor_multiply<T, UnaryFunctor<EXPR> > >(va);
    00834     }
    00835
    00836     template <class EXPR>
    00837     UnaryAnalyser< AssignmentFunctor_divide<T, UnaryFunctor<EXPR> > >
    00838     operator/=(UnaryFunctor<EXPR> const & e)
    00839     {
    00840         AssignmentFunctor_divide<T, UnaryFunctor<EXPR> > va(*this, e);
    00841         return UnaryAnalyser< AssignmentFunctor_divide<T, UnaryFunctor<EXPR> > >(va);
    00842     }
    00843
    00844     T const & operator()() const
    00845     {
    00846         return value_;
    00847     }
    00848
    00849     template <class U1>
    00850     T const & operator()(U1 const &) const
    00851     {
    00852         return value_;
    00853     }
    00854
    00855     template <class U1, class U2>
    00856     T const & operator()(U1 const &, U2 const &) const
    00857     {
    00858         return value_;
    00859     }
    00860
    00861     template <class U1, class U2, class U3>
    00862     T const & operator()(U1 const &, U2 const &, U3 const &) const
    00863     {
    00864         return value_;
    00865     }
    00866
    00867     T & value_;
    00868 };
    00869
    00870 template <class T>
    00871 struct ResultTraits0<UnaryFunctor<VarFunctor<T> > >
    00872 {
    00873     typedef T Res;
    00874 };
    00875
    00876 template <class T, class T1>
    00877 struct ResultTraits1<UnaryFunctor<VarFunctor<T> >, T1>
    00878 {
    00879     typedef T Res;
    00880 };
    00881
    00882 template <class T, class T1, class T2>
    00883 struct ResultTraits2<UnaryFunctor<VarFunctor<T> >, T1, T2>
    00884 {
    00885     typedef T Res;
    00886 };
    00887
    00888 template <class T, class T1, class T2, class T3>
    00889 struct ResultTraits3<UnaryFunctor<VarFunctor<T> >, T1, T2, T3>
    00890 {
    00891     typedef T Res;
    00892 };
    00893
    00894 template <class T>
    00895 UnaryFunctor<VarFunctor<T> >
    00896 Var(T & v)
    00897 {
    00898     return UnaryFunctor<VarFunctor<T> >(v);
    00899 }
    00900
    00901 /************************************************************/
    00902 /*                                                          */
    00903 /*                          if then                         */
    00904 /*                                                          */
    00905 /************************************************************/
    00906
    00907 template <class EXPR1, class EXPR2>
    00908 struct IfThenFunctor
    00909 {
    00910     typedef void Res;
    00911
    00912     IfThenFunctor(EXPR1 const & e1, EXPR2 const & e2)
    00913     : expr1_(e1), expr2_(e2)
    00914     {}
    00915
    00916     void operator()() const
    00917     {
    00918         if( expr1_() ) expr2_();
    00919     }
    00920
    00921     template <class T>
    00922     void operator()(T const & v1) const
    00923     {
    00924         if( expr1_(v1) ) expr2_(v1);
    00925     }
    00926
    00927     template <class T1, class T2>
    00928     void operator()(T1 const & v1, T2 const & v2) const
    00929     {
    00930         if( expr1_(v1, v2) ) expr2_(v1, v2);
    00931     }
    00932
    00933     template <class T1, class T2, class T3>
    00934     void operator()(T1 const & v1, T2 const & v2, T3 const & v3) const
    00935     {
    00936         if( expr1_(v1, v2, v3) ) expr2_(v1, v2, v3);
    00937     }
    00938
    00939   private:
    00940
    00941     EXPR1 expr1_;
    00942     EXPR2 expr2_;
    00943 };
    00944
    00945 template <class EXPR1, class EXPR2>
    00946 UnaryAnalyser<IfThenFunctor<UnaryFunctor<EXPR1>,
    00947                             UnaryAnalyser<EXPR2> > >
    00948 ifThen(UnaryFunctor<EXPR1> const & e1,
    00949        UnaryAnalyser<EXPR2> const & e2)
    00950 {
    00951     IfThenFunctor<UnaryFunctor<EXPR1>,
    00952                   UnaryAnalyser<EXPR2> > p(e1, e2);
    00953     return UnaryAnalyser<IfThenFunctor<UnaryFunctor<EXPR1>,
    00954                                        UnaryAnalyser<EXPR2> > >(p);
    00955 }
    00956
    00957 /************************************************************/
    00958 /*                                                          */
    00959 /*                         if then else                     */
    00960 /*                                                          */
    00961 /************************************************************/
    00962
    00963 template <class EXPR1, class EXPR2, class EXPR3>
    00964 struct IfThenElseFunctor;
    00965
    00966 template <class EXPR1, class EXPR2, class EXPR3>
    00967 struct ResultTraits0<IfThenElseFunctor<EXPR1, EXPR2, EXPR3> >
    00968 {
    00969     typedef typename ResultTraits0<EXPR2>::Res R2;
    00970     typedef typename ResultTraits0<EXPR3>::Res R3;
    00971     typedef typename PromoteTraits<R2, R3>::Promote Res;
    00972 };
    00973
    00974 template <class EXPR1, class EXPR2, class EXPR3, class T1>
    00975 struct ResultTraits1<IfThenElseFunctor<EXPR1, EXPR2, EXPR3>, T1>
    00976 {
    00977     typedef typename ResultTraits1<EXPR2, T1>::Res R2;
    00978     typedef typename ResultTraits1<EXPR3, T1>::Res R3;
    00979     typedef typename PromoteTraits<R2, R3>::Promote Res;
    00980 };
    00981
    00982 template <class EXPR1, class EXPR2, class EXPR3, class T1, class T2>
    00983 struct ResultTraits2<IfThenElseFunctor<EXPR1, EXPR2, EXPR3>, T1, T2>
    00984 {
    00985     typedef typename ResultTraits2<EXPR2, T1, T2>::Res R2;
    00986     typedef typename ResultTraits2<EXPR3, T1, T2>::Res R3;
    00987     typedef typename PromoteTraits<R2, R3>::Promote Res;
    00988 };
    00989
    00990 template <class EXPR1, class EXPR2, class EXPR3, class T1, class T2, class T3>
    00991 struct ResultTraits3<IfThenElseFunctor<EXPR1, EXPR2, EXPR3>, T1, T2, T3>
    00992 {
    00993     typedef typename ResultTraits3<EXPR2, T1, T2, T3>::Res R2;
    00994     typedef typename ResultTraits3<EXPR3, T1, T2, T3>::Res R3;
    00995     typedef typename PromoteTraits<R2, R3>::Promote Res;
    00996 };
    00997
    00998 template <class EXPR1, class EXPR2, class EXPR3>
    00999 struct IfThenElseFunctor
    01000 {
    01001     IfThenElseFunctor(EXPR1 const & e1, EXPR2 const & e2, EXPR3 const & e3)
    01002     : expr1_(e1), expr2_(e2), expr3_(e3)
    01003     {}
    01004
    01005     typename ResultTraits0<IfThenElseFunctor>::Res
    01006     operator()() const
    01007     {
    01008         typename
    01009             ResultTraits0<IfThenElseFunctor>::Res
    01010             r2(expr2_());
    01011         typename
    01012             ResultTraits0<IfThenElseFunctor>::Res
    01013             r3(expr3_());
    01014         return expr1_() ? r2 : r3;
    01015     }
    01016
    01017     template <class T>
    01018     typename ResultTraits1<IfThenElseFunctor, T>::Res
    01019     operator()(T const & v1) const
    01020     {
    01021         typename
    01022             ResultTraits1<IfThenElseFunctor, T>::Res
    01023             r2(expr2_(v1));
    01024         typename
    01025             ResultTraits1<IfThenElseFunctor, T>::Res
    01026             r3(expr3_(v1));
    01027         return expr1_(v1) ? r2 : r3;
    01028     }
    01029
    01030     template <class T1, class T2>
    01031     typename ResultTraits2<IfThenElseFunctor, T1, T2>::Res
    01032     operator()(T1 const & v1, T2 const & v2) const
    01033     {
    01034         typename
    01035             ResultTraits2<IfThenElseFunctor, T1, T2>::Res
    01036             r2(expr2_(v1, v2));
    01037         typename
    01038             ResultTraits2<IfThenElseFunctor, T1, T2>::Res
    01039             r3(expr3_(v1, v2));
    01040         return expr1_(v1, v2) ? r2 : r3;
    01041     }
    01042
    01043     template <class T1, class T2, class T3>
    01044     typename ResultTraits3<IfThenElseFunctor, T1, T2, T3>::Res
    01045     operator()(T1 const & v1, T2 const & v2, T3 const & v3) const
    01046     {
    01047         typename
    01048             ResultTraits3<IfThenElseFunctor, T1, T2, T3>::Res
    01049             r2(expr2_(v1, v2, v3));
    01050         typename
    01051             ResultTraits3<IfThenElseFunctor, T1, T2, T3>::Res
    01052             r3(expr3_(v1, v2, v3));
    01053         return expr1_(v1, v2, v3) ? r2 : r3;
    01054     }
    01055
    01056   private:
    01057
    01058     EXPR1 expr1_;
    01059     EXPR2 expr2_;
    01060     EXPR3 expr3_;
    01061 };
    01062
    01063 template <class EXPR1, class EXPR2, class EXPR3>
    01064 UnaryFunctor<IfThenElseFunctor<UnaryFunctor<EXPR1>,
    01065                                UnaryFunctor<EXPR2>,
    01066                                UnaryFunctor<EXPR3> > >
    01067 ifThenElse(UnaryFunctor<EXPR1> const & e1,
    01068            UnaryFunctor<EXPR2> const & e2,
    01069            UnaryFunctor<EXPR3> const & e3)
    01070 {
    01071     IfThenElseFunctor<UnaryFunctor<EXPR1>,
    01072                       UnaryFunctor<EXPR2>,
    01073                       UnaryFunctor<EXPR3> > p(e1, e2, e3);
    01074     return UnaryFunctor<IfThenElseFunctor<UnaryFunctor<EXPR1>,
    01075                                           UnaryFunctor<EXPR2>,
    01076                                           UnaryFunctor<EXPR3> > >(p);
    01077 }
    01078
    01079 /************************************************************/
    01080 /*                                                          */
    01081 /*                functors for unary functions              */
    01082 /*                                                          */
    01083 /************************************************************/
    01084
    01085 #define MAKE_FUNCTOR_UNARY_FUNCTION(function, namespc) \
    01086     using ::namespc::function; \
    01087     template <class EXPR> \
    01088     struct Functor_##function; \
    01089     \
    01090     template <class EXPR> \
    01091     struct ResultTraits0<Functor_##function<EXPR> > \
    01092     { \
    01093         typedef typename ResultTraits0<EXPR>::Res R1; \
    01094         typedef typename NumericTraits<R1>::RealPromote Res; \
    01095     }; \
    01096     \
    01097     template <class EXPR, class T1> \
    01098     struct ResultTraits1<Functor_##function<EXPR>, T1> \
    01099     { \
    01100         typedef typename ResultTraits1<EXPR, T1>::Res R1; \
    01101         typedef typename NumericTraits<R1>::RealPromote Res; \
    01102     }; \
    01103     \
    01104     template <class EXPR, class T1, class T2> \
    01105     struct ResultTraits2<Functor_##function<EXPR>, T1, T2> \
    01106     { \
    01107         typedef typename ResultTraits2<EXPR, T1, T2>::Res R1; \
    01108         typedef typename NumericTraits<R1>::RealPromote Res; \
    01109     }; \
    01110     \
    01111     template <class EXPR, class T1, class T2, class T3> \
    01112     struct ResultTraits3<Functor_##function<EXPR>, T1, T2, T3> \
    01113     { \
    01114         typedef typename ResultTraits3<EXPR, T1, T2, T3>::Res R1; \
    01115         typedef typename NumericTraits<R1>::RealPromote Res; \
    01116     }; \
    01117     \
    01118     template <class EXPR> \
    01119     struct Functor_##function \
    01120     { \
    01121         Functor_##function(EXPR const & e) \
    01122         : expr_(e) \
    01123         {} \
    01124          \
    01125         typename ResultTraits0<Functor_##function>::Res \
    01126         operator()() const \
    01127         { \
    01128             return function(expr_()); \
    01129         } \
    01130          \
    01131         template <class T> \
    01132         typename ResultTraits1<Functor_##function, T>::Res \
    01133         operator()(T const & v1) const \
    01134         { \
    01135             return function(expr_(v1)); \
    01136         } \
    01137          \
    01138         template <class T1, class T2> \
    01139         typename ResultTraits2<Functor_##function, T1, T2>::Res \
    01140         operator()(T1 const & v1, T2 const & v2) const \
    01141         { \
    01142             return function(expr_(v1, v2)); \
    01143         } \
    01144          \
    01145         template <class T1, class T2, class T3> \
    01146         typename ResultTraits3<Functor_##function, T1, T2, T3>::Res \
    01147         operator()(T1 const & v1, T2 const & v2, T3 const & v3) const \
    01148         { \
    01149             return function(expr_(v1, v2, v3)); \
    01150         } \
    01151          \
    01152       protected: \
    01153        \
    01154         EXPR expr_; \
    01155     }; \
    01156      \
    01157     template <class EXPR> \
    01158     UnaryFunctor<Functor_##function<UnaryFunctor<EXPR> > > \
    01159     function(UnaryFunctor<EXPR> const & e) \
    01160     { \
    01161         Functor_##function<UnaryFunctor<EXPR> > p(e); \
    01162         return UnaryFunctor<Functor_##function<UnaryFunctor<EXPR> > >(p); \
    01163     }
    01164
    01165 /************************************************************/
    01166
    01167 MAKE_FUNCTOR_UNARY_FUNCTION(sqrt, std)
    01168 MAKE_FUNCTOR_UNARY_FUNCTION(exp, std)
    01169 MAKE_FUNCTOR_UNARY_FUNCTION(log, std)
    01170 MAKE_FUNCTOR_UNARY_FUNCTION(log10, std)
    01171 MAKE_FUNCTOR_UNARY_FUNCTION(sin, std)
    01172 MAKE_FUNCTOR_UNARY_FUNCTION(asin, std)
    01173 MAKE_FUNCTOR_UNARY_FUNCTION(cos, std)
    01174 MAKE_FUNCTOR_UNARY_FUNCTION(acos, std)
    01175 MAKE_FUNCTOR_UNARY_FUNCTION(tan, std)
    01176 MAKE_FUNCTOR_UNARY_FUNCTION(atan, std)
    01177 MAKE_FUNCTOR_UNARY_FUNCTION(floor, std)
    01178 MAKE_FUNCTOR_UNARY_FUNCTION(ceil, std)
    01179 MAKE_FUNCTOR_UNARY_FUNCTION(abs, vigra)
    01180 //MAKE_FUNCTOR_UNARY_FUNCTION(norm, vigra)
    01181 //MAKE_FUNCTOR_UNARY_FUNCTION(squaredNorm, vigra)
    01182
    01183 #undef MAKE_FUNCTOR_UNARY_FUNCTION
    01184
    01185 /************************************************************/
    01186 /*                                                          */
    01187 /*                functors for unary operators              */
    01188 /*                                                          */
    01189 /************************************************************/
    01190
    01191 #define MAKE_FUNCTOR_UNARY_OPERATOR(name, op) \
    01192     template <class EXPR> \
    01193     struct Functor_##name; \
    01194     \
    01195     template <class EXPR> \
    01196     struct ResultTraits0<Functor_##name<EXPR> > \
    01197     { \
    01198         typedef typename ResultTraits0<EXPR>::Res Res; \
    01199     }; \
    01200     \
    01201     template <class EXPR, class T1> \
    01202     struct ResultTraits1<Functor_##name<EXPR>, T1> \
    01203     { \
    01204         typedef typename ResultTraits1<EXPR, T1>::Res Res; \
    01205     }; \
    01206     \
    01207     template <class EXPR, class T1, class T2> \
    01208     struct ResultTraits2<Functor_##name<EXPR>, T1, T2> \
    01209     { \
    01210         typedef typename ResultTraits2<EXPR, T1, T2>::Res Res; \
    01211     }; \
    01212     \
    01213     template <class EXPR, class T1, class T2, class T3> \
    01214     struct ResultTraits3<Functor_##name<EXPR>, T1, T2, T3> \
    01215     { \
    01216         typedef typename ResultTraits3<EXPR, T1, T2, T3>::Res Res; \
    01217     }; \
    01218     \
    01219     template <class EXPR> \
    01220     struct Functor_##name \
    01221     { \
    01222         Functor_##name(EXPR const & e) \
    01223         : expr_(e) \
    01224         {} \
    01225          \
    01226         typename ResultTraits0<Functor_##name>::Res \
    01227         operator()() const \
    01228         { \
    01229             return op expr_(); \
    01230         } \
    01231          \
    01232         template <class T> \
    01233         typename ResultTraits1<Functor_##name, T>::Res \
    01234         operator()(T const & v1) const \
    01235         { \
    01236             return op expr_(v1); \
    01237         } \
    01238          \
    01239         template <class T1, class T2> \
    01240         typename ResultTraits2<Functor_##name, T1, T2>::Res \
    01241         operator()(T1 const & v1, T2 const & v2) const \
    01242         { \
    01243             return op expr_(v1, v2); \
    01244         } \
    01245          \
    01246         template <class T1, class T2, class T3> \
    01247         typename ResultTraits3<Functor_##name, T1, T2, T3>::Res \
    01248         operator()(T1 const & v1, T2 const & v2, T3 const & v3) const \
    01249         { \
    01250             return op expr_(v1, v2, v3); \
    01251         } \
    01252       protected: \
    01253        \
    01254         EXPR expr_; \
    01255     }; \
    01256      \
    01257     template <class EXPR> \
    01258     UnaryFunctor<Functor_##name<UnaryFunctor<EXPR> > > \
    01259     operator op(UnaryFunctor<EXPR> const & e) \
    01260     { \
    01261         Functor_##name<UnaryFunctor<EXPR> > p(e); \
    01262         return UnaryFunctor<Functor_##name<UnaryFunctor<EXPR> > >(p); \
    01263     }
    01264
    01265
    01266 /************************************************************/
    01267
    01268 MAKE_FUNCTOR_UNARY_OPERATOR(minus, -)
    01269 MAKE_FUNCTOR_UNARY_OPERATOR(negate, !)
    01270 MAKE_FUNCTOR_UNARY_OPERATOR(bitNegate, ~)
    01271
    01272 #undef MAKE_FUNCTOR_UNARY_OPERATOR
    01273
    01274 /************************************************************/
    01275 /*                                                          */
    01276 /*               functors for binary functions              */
    01277 /*                                                          */
    01278 /************************************************************/
    01279
    01280 #define MAKE_FUNCTOR_BINARY_FUNCTION(function) \
    01281     using std::function; \
    01282     template <class EXPR1, class EXPR2> \
    01283     struct Functor_##function; \
    01284     \
    01285     template <class EXPR1, class EXPR2> \
    01286     struct ResultTraits0<Functor_##function<EXPR1, EXPR2> > \
    01287     { \
    01288         typedef typename ResultTraits0<EXPR1>::Res R1; \
    01289         typedef typename ResultTraits0<EXPR2>::Res R2; \
    01290         typedef typename PromoteTraits<R1, R2>::Promote R3; \
    01291         typedef typename NumericTraits<R3>::RealPromote Res; \
    01292     }; \
    01293     \
    01294     template <class EXPR1, class EXPR2, class T1> \
    01295     struct ResultTraits1<Functor_##function<EXPR1, EXPR2>, T1> \
    01296     { \
    01297         typedef typename ResultTraits1<EXPR1, T1>::Res R1; \
    01298         typedef typename ResultTraits1<EXPR2, T1>::Res R2; \
    01299         typedef typename PromoteTraits<R1, R2>::Promote R3; \
    01300         typedef typename NumericTraits<R3>::RealPromote Res; \
    01301     }; \
    01302     \
    01303     template <class EXPR1, class EXPR2, class T1, class T2> \
    01304     struct ResultTraits2<Functor_##function<EXPR1, EXPR2>, T1, T2> \
    01305     { \
    01306         typedef typename ResultTraits2<EXPR1, T1, T2>::Res R1; \
    01307         typedef typename ResultTraits2<EXPR2, T1, T2>::Res R2; \
    01308         typedef typename PromoteTraits<R1, R2>::Promote R3; \
    01309         typedef typename NumericTraits<R3>::RealPromote Res; \
    01310     }; \
    01311     \
    01312     template <class EXPR1, class EXPR2, class T1, class T2, class T3> \
    01313     struct ResultTraits3<Functor_##function<EXPR1, EXPR2>, T1, T2, T3> \
    01314     { \
    01315         typedef typename ResultTraits3<EXPR1, T1, T2, T3>::Res R1; \
    01316         typedef typename ResultTraits3<EXPR2, T1, T2, T3>::Res R2; \
    01317         typedef typename PromoteTraits<R1, R2>::Promote R3; \
    01318         typedef typename NumericTraits<R3>::RealPromote Res; \
    01319     }; \
    01320     \
    01321     template <class EXPR1, class EXPR2> \
    01322     struct Functor_##function \
    01323     { \
    01324         Functor_##function(EXPR1 const & e1, EXPR2 const & e2) \
    01325         : expr1_(e1), expr2_(e2) \
    01326         {} \
    01327          \
    01328         typename ResultTraits0<Functor_##function>::Res \
    01329         operator()() const \
    01330         { \
    01331             return function(expr1_(), expr2_()); \
    01332         } \
    01333          \
    01334         template <class T> \
    01335         typename ResultTraits1<Functor_##function, T>::Res \
    01336         operator()(T const & v1) const \
    01337         { \
    01338             return function(expr1_(v1), expr2_(v1)); \
    01339         } \
    01340          \
    01341         template <class T1, class T2> \
    01342         typename ResultTraits2<Functor_##function, T1, T2>::Res \
    01343         operator()(T1 const & v1, T2 const & v2) const \
    01344         { \
    01345             return function(expr1_(v1, v2), expr2_(v1, v2)); \
    01346         } \
    01347          \
    01348         template <class T1, class T2, class T3> \
    01349         typename ResultTraits3<Functor_##function, T1, T2, T3>::Res \
    01350         operator()(T1 const & v1, T2 const & v2, T3 const & v3) const \
    01351         { \
    01352             return function(expr1_(v1, v2, v3), expr2_(v1, v2, v3)); \
    01353         } \
    01354          \
    01355       private: \
    01356          \
    01357         EXPR1 expr1_; \
    01358         EXPR2 expr2_; \
    01359     }; \
    01360      \
    01361     template <class EXPR1, class EXPR2> \
    01362     UnaryFunctor<Functor_##function<UnaryFunctor<EXPR1>, UnaryFunctor<EXPR2> > > \
    01363     function(UnaryFunctor<EXPR1> const & e1, UnaryFunctor<EXPR2> const & e2) \
    01364     { \
    01365         Functor_##function<UnaryFunctor<EXPR1>, UnaryFunctor<EXPR2> > p(e1, e2); \
    01366         return UnaryFunctor<Functor_##function<UnaryFunctor<EXPR1>,  \
    01367                                         UnaryFunctor<EXPR2> > >(p); \
    01368     }
    01369
    01370 /************************************************************/
    01371
    01372 MAKE_FUNCTOR_BINARY_FUNCTION(pow)
    01373 MAKE_FUNCTOR_BINARY_FUNCTION(atan2)
    01374 MAKE_FUNCTOR_BINARY_FUNCTION(fmod)
    01375
    01376 #undef MAKE_FUNCTOR_BINARY_FUNCTION
    01377
    01378 /************************************************************/
    01379
    01380 #define MAKE_FUNCTOR_MINMAX(name, op) \
    01381     template <class EXPR1, class EXPR2> \
    01382     struct Functor_##name; \
    01383     \
    01384     template <class EXPR1, class EXPR2> \
    01385     struct ResultTraits0<Functor_##name<EXPR1, EXPR2> > \
    01386     { \
    01387         typedef typename ResultTraits0<EXPR1>::Res R1; \
    01388         typedef typename ResultTraits0<EXPR2>::Res R2; \
    01389         typedef typename PromoteTraits<R1, R2>::Promote Res; \
    01390     }; \
    01391     \
    01392     template <class EXPR1, class EXPR2, class T1> \
    01393     struct ResultTraits1<Functor_##name<EXPR1, EXPR2>, T1> \
    01394     { \
    01395         typedef typename ResultTraits1<EXPR1, T1>::Res R1; \
    01396         typedef typename ResultTraits1<EXPR2, T1>::Res R2; \
    01397         typedef typename PromoteTraits<R1, R2>::Promote Res; \
    01398     }; \
    01399     \
    01400     template <class EXPR1, class EXPR2, class T1, class T2> \
    01401     struct ResultTraits2<Functor_##name<EXPR1, EXPR2>, T1, T2> \
    01402     { \
    01403         typedef typename ResultTraits2<EXPR1, T1, T2>::Res R1; \
    01404         typedef typename ResultTraits2<EXPR2, T1, T2>::Res R2; \
    01405         typedef typename PromoteTraits<R1, R2>::Promote Res; \
    01406     }; \
    01407     \
    01408     template <class EXPR1, class EXPR2, class T1, class T2, class T3> \
    01409     struct ResultTraits3<Functor_##name<EXPR1, EXPR2>, T1, T2, T3> \
    01410     { \
    01411         typedef typename ResultTraits3<EXPR1, T1, T2, T3>::Res R1; \
    01412         typedef typename ResultTraits3<EXPR2, T1, T2, T3>::Res R2; \
    01413         typedef typename PromoteTraits<R1, R2>::Promote Res; \
    01414     }; \
    01415     \
    01416     template <class EXPR1, class EXPR2> \
    01417     struct Functor_##name \
    01418     { \
    01419         Functor_##name(EXPR1 const & e1, EXPR2 const & e2) \
    01420         : expr1_(e1), expr2_(e2) \
    01421         {} \
    01422          \
    01423         typename ResultTraits0<Functor_##name>::Res \
    01424         operator()() const \
    01425         { \
    01426             typename \
    01427             ResultTraits0<Functor_##name<EXPR1, EXPR2> >::R1 r1(expr1_()); \
    01428             typename \
    01429             ResultTraits0<Functor_##name<EXPR1, EXPR2> >::R2 r2(expr2_()); \
    01430             return (r1 op r2) ? r1 : r2; \
    01431         } \
    01432          \
    01433         template <class T> \
    01434         typename ResultTraits1<Functor_##name, T>::Res \
    01435         operator()(T const & v1) const \
    01436         { \
    01437             typename \
    01438             ResultTraits1<Functor_##name<EXPR1, EXPR2>, T>::R1 r1(expr1_(v1)); \
    01439             typename \
    01440             ResultTraits1<Functor_##name<EXPR1, EXPR2>, T>::R2 r2(expr2_(v1)); \
    01441             return (r1 op r2) ? r1 : r2; \
    01442         } \
    01443          \
    01444         template <class T1, class T2> \
    01445         typename ResultTraits2<Functor_##name, T1, T2>::Res \
    01446         operator()(T1 const & v1, T2 const & v2) const \
    01447         { \
    01448             typename \
    01449             ResultTraits2<Functor_##name<EXPR1, EXPR2>, T1, T2>::R1 r1(expr1_(v1, v2)); \
    01450             typename \
    01451             ResultTraits2<Functor_##name<EXPR1, EXPR2>, T1, T2>::R2 r2(expr2_(v1, v2)); \
    01452             return (r1 op r2) ? r1 : r2; \
    01453         } \
    01454          \
    01455         template <class T1, class T2, class T3> \
    01456         typename ResultTraits3<Functor_##name, T1, T2, T3>::Res \
    01457         operator()(T1 const & v1, T2 const & v2, T3 const & v3) const \
    01458         { \
    01459             typename \
    01460             ResultTraits3<Functor_##name<EXPR1, EXPR2>, T1, T2, T3>::R1 r1(expr1_(v1, v2, v3)); \
    01461             typename \
    01462             ResultTraits3<Functor_##name<EXPR1, EXPR2>, T1, T2, T3>::R2 r2(expr2_(v1, v2, v3)); \
    01463             return (r1 op r2) ? r1 : r2; \
    01464         } \
    01465          \
    01466       private: \
    01467          \
    01468         EXPR1 expr1_; \
    01469         EXPR2 expr2_; \
    01470     }; \
    01471      \
    01472     template <class EXPR1, class EXPR2> \
    01473     UnaryFunctor<Functor_##name<UnaryFunctor<EXPR1>, UnaryFunctor<EXPR2> > > \
    01474     name(UnaryFunctor<EXPR1> const & e1, UnaryFunctor<EXPR2> const & e2) \
    01475     { \
    01476         Functor_##name<UnaryFunctor<EXPR1>, UnaryFunctor<EXPR2> > p(e1, e2); \
    01477         return UnaryFunctor<Functor_##name<UnaryFunctor<EXPR1>,  \
    01478                                         UnaryFunctor<EXPR2> > >(p); \
    01479     }
    01480
    01481 MAKE_FUNCTOR_MINMAX(min, <)
    01482 MAKE_FUNCTOR_MINMAX(max, >)
    01483
    01484 #undef MAKE_FUNCTOR_MINMAX
    01485
    01486 /************************************************************/
    01487 /*                                                          */
    01488 /*               functors for binary operators              */
    01489 /*                                                          */
    01490 /************************************************************/
    01491
    01492 #define MAKE_FUNCTOR_BINARY_OPERATOR(name, op) \
    01493     template <class EXPR1, class EXPR2> \
    01494     struct Functor_##name; \
    01495     \
    01496     template <class EXPR1, class EXPR2> \
    01497     struct ResultTraits0<Functor_##name<EXPR1, EXPR2> > \
    01498     { \
    01499         typedef typename ResultTraits0<EXPR1>::Res R1; \
    01500         typedef typename ResultTraits0<EXPR2>::Res R2; \
    01501         typedef typename PromoteTraits<R1, R2>::Promote Res; \
    01502     }; \
    01503     \
    01504     template <class EXPR1, class EXPR2, class T1> \
    01505     struct ResultTraits1<Functor_##name<EXPR1, EXPR2>, T1> \
    01506     { \
    01507         typedef typename ResultTraits1<EXPR1, T1>::Res R1; \
    01508         typedef typename ResultTraits1<EXPR2, T1>::Res R2; \
    01509         typedef typename PromoteTraits<R1, R2>::Promote Res; \
    01510     }; \
    01511     \
    01512     template <class EXPR1, class EXPR2, class T1, class T2> \
    01513     struct ResultTraits2<Functor_##name<EXPR1, EXPR2>, T1, T2> \
    01514     { \
    01515         typedef typename ResultTraits2<EXPR1, T1, T2>::Res R1; \
    01516         typedef typename ResultTraits2<EXPR2, T1, T2>::Res R2; \
    01517         typedef typename PromoteTraits<R1, R2>::Promote Res; \
    01518     }; \
    01519     \
    01520     template <class EXPR1, class EXPR2, class T1, class T2, class T3> \
    01521     struct ResultTraits3<Functor_##name<EXPR1, EXPR2>, T1, T2, T3> \
    01522     { \
    01523         typedef typename ResultTraits3<EXPR1, T1, T2, T3>::Res R1; \
    01524         typedef typename ResultTraits3<EXPR2, T1, T2, T3>::Res R2; \
    01525         typedef typename PromoteTraits<R1, R2>::Promote Res; \
    01526     }; \
    01527     \
    01528     template <class EXPR1, class EXPR2> \
    01529     struct Functor_##name \
    01530     { \
    01531         Functor_##name(EXPR1 const & e1, EXPR2 const & e2) \
    01532         : expr1_(e1), expr2_(e2) \
    01533         {} \
    01534          \
    01535         typename ResultTraits0<Functor_##name>::Res \
    01536         operator()() const \
    01537         { \
    01538             return expr1_() op expr2_(); \
    01539         } \
    01540          \
    01541         template <class T> \
    01542         typename ResultTraits1<Functor_##name, T>::Res \
    01543         operator()(T const & v1) const \
    01544         { \
    01545             return expr1_(v1) op expr2_(v1); \
    01546         } \
    01547          \
    01548         template <class T1, class T2> \
    01549         typename ResultTraits2<Functor_##name, T1, T2>::Res \
    01550         operator()(T1 const & v1, T2 const & v2) const \
    01551         { \
    01552             return expr1_(v1, v2) op expr2_(v1, v2); \
    01553         } \
    01554          \
    01555         template <class T1, class T2, class T3> \
    01556         typename ResultTraits3<Functor_##name, T1, T2, T3>::Res \
    01557         operator()(T1 const & v1, T2 const & v2, T3 const & v3) const \
    01558         { \
    01559             return expr1_(v1, v2, v3) op expr2_(v1, v2, v3); \
    01560         } \
    01561          \
    01562       private: \
    01563          \
    01564         EXPR1 expr1_; \
    01565         EXPR2 expr2_; \
    01566     }; \
    01567      \
    01568     template <class EXPR1, class EXPR2> \
    01569     UnaryFunctor<Functor_##name<UnaryFunctor<EXPR1>, UnaryFunctor<EXPR2> > > \
    01570     operator op(UnaryFunctor<EXPR1> const & e1, UnaryFunctor<EXPR2> const & e2) \
    01571     { \
    01572         Functor_##name<UnaryFunctor<EXPR1>, UnaryFunctor<EXPR2> > p(e1, e2); \
    01573         return UnaryFunctor<Functor_##name<UnaryFunctor<EXPR1>,  \
    01574                                         UnaryFunctor<EXPR2> > >(p); \
    01575     }
    01576
    01577 /************************************************************/
    01578
    01579 MAKE_FUNCTOR_BINARY_OPERATOR(add, +)
    01580 MAKE_FUNCTOR_BINARY_OPERATOR(subtract, -)
    01581 MAKE_FUNCTOR_BINARY_OPERATOR(multiply, *)
    01582 MAKE_FUNCTOR_BINARY_OPERATOR(divide, /)
    01583 MAKE_FUNCTOR_BINARY_OPERATOR(modulo, %)
    01584 MAKE_FUNCTOR_BINARY_OPERATOR(bitAnd, &)
    01585 MAKE_FUNCTOR_BINARY_OPERATOR(bitOr, |)
    01586 MAKE_FUNCTOR_BINARY_OPERATOR(bitXor, ^)
    01587
    01588 #undef MAKE_FUNCTOR_BINARY_OPERATOR
    01589
    01590 /************************************************************/
    01591
    01592 #define MAKE_FUNCTOR_BINARY_OPERATOR_BOOL(name, op) \
    01593     template <class EXPR1, class EXPR2> \
    01594     struct Functor_##name; \
    01595     \
    01596     template <class EXPR1, class EXPR2> \
    01597     struct ResultTraits0<Functor_##name<EXPR1, EXPR2> > \
    01598     { \
    01599         typedef bool Res; \
    01600     }; \
    01601     \
    01602     template <class EXPR1, class EXPR2, class T1> \
    01603     struct ResultTraits1<Functor_##name<EXPR1, EXPR2>, T1> \
    01604     { \
    01605         typedef bool Res; \
    01606     }; \
    01607     \
    01608     template <class EXPR1, class EXPR2, class T1, class T2> \
    01609     struct ResultTraits2<Functor_##name<EXPR1, EXPR2>, T1, T2> \
    01610     { \
    01611         typedef bool Res; \
    01612     }; \
    01613     \
    01614     template <class EXPR1, class EXPR2, class T1, class T2, class T3> \
    01615     struct ResultTraits3<Functor_##name<EXPR1, EXPR2>, T1, T2, T3> \
    01616     { \
    01617         typedef bool Res; \
    01618     }; \
    01619     \
    01620     template <class EXPR1, class EXPR2> \
    01621     struct Functor_##name \
    01622     { \
    01623         Functor_##name(EXPR1 const & e1, EXPR2 const & e2) \
    01624         : expr1_(e1), expr2_(e2) \
    01625         {} \
    01626          \
    01627         bool operator()() const \
    01628         { \
    01629             return expr1_() op expr2_(); \
    01630         } \
    01631          \
    01632         template <class T> \
    01633         bool operator()(T const & v1) const \
    01634         { \
    01635             return expr1_(v1) op expr2_(v1); \
    01636         } \
    01637          \
    01638         template <class T1, class T2> \
    01639         bool operator()(T1 const & v1, T2 const & v2) const \
    01640         { \
    01641             return expr1_(v1, v2) op expr2_(v1, v2); \
    01642         } \
    01643          \
    01644         template <class T1, class T2, class T3> \
    01645         bool operator()(T1 const & v1, T2 const & v2, T3 const & v3) const \
    01646         { \
    01647             return expr1_(v1, v2, v3) op expr2_(v1, v2, v3); \
    01648         } \
    01649          \
    01650       private: \
    01651          \
    01652         EXPR1 expr1_; \
    01653         EXPR2 expr2_; \
    01654     }; \
    01655      \
    01656     template <class EXPR1, class EXPR2> \
    01657     UnaryFunctor<Functor_##name<UnaryFunctor<EXPR1>, UnaryFunctor<EXPR2> > > \
    01658     operator op(UnaryFunctor<EXPR1> const & e1, UnaryFunctor<EXPR2> const & e2) \
    01659     { \
    01660         Functor_##name<UnaryFunctor<EXPR1>, UnaryFunctor<EXPR2> > p(e1, e2); \
    01661         return UnaryFunctor<Functor_##name<UnaryFunctor<EXPR1>,  \
    01662                                         UnaryFunctor<EXPR2> > >(p); \
    01663     }
    01664
    01665 /************************************************************/
    01666
    01667 MAKE_FUNCTOR_BINARY_OPERATOR_BOOL(equals, ==)
    01668 MAKE_FUNCTOR_BINARY_OPERATOR_BOOL(differs, !=)
    01669 MAKE_FUNCTOR_BINARY_OPERATOR_BOOL(less, <)
    01670 MAKE_FUNCTOR_BINARY_OPERATOR_BOOL(lessEqual, <=)
    01671 MAKE_FUNCTOR_BINARY_OPERATOR_BOOL(greater, >)
    01672 MAKE_FUNCTOR_BINARY_OPERATOR_BOOL(greaterEqual, >=)
    01673 MAKE_FUNCTOR_BINARY_OPERATOR_BOOL(and, &&)
    01674 MAKE_FUNCTOR_BINARY_OPERATOR_BOOL(or, ||)
    01675
    01676 #undef MAKE_FUNCTOR_BINARY_OPERATOR_BOOL
    01677
    01678 /************************************************************/
    01679 /*                                                          */
    01680 /*                         unary apply                      */
    01681 /*                                                          */
    01682 /************************************************************/
    01683
    01684 template <class EXPR, class RES, class ARG>
    01685 struct UnaryFctPtrFunctor
    01686 {
    01687     UnaryFctPtrFunctor(EXPR const & e, RES (*fct)(ARG))
    01688     : expr_(e), f_(fct)
    01689     {}
    01690
    01691     RES operator()() const
    01692     {
    01693         return f_(expr_());
    01694     }
    01695
    01696     template <class T>
    01697     RES operator()(T const & v1) const
    01698     {
    01699         return f_(expr_(v1));
    01700     }
    01701
    01702     template <class T1, class T2>
    01703     RES operator()(T1 const & v1, T2 const & v2) const
    01704     {
    01705         return f_(expr_(v1, v2));
    01706     }
    01707
    01708     template <class T1, class T2, class T3>
    01709     RES operator()(T1 const & v1, T2 const & v2, T3 const & v3) const
    01710     {
    01711         return f_(expr_(v1, v2, v3));
    01712     }
    01713   protected:
    01714
    01715     EXPR expr_;
    01716     RES (*f_)(ARG);
    01717 };
    01718
    01719 template <class EXPR, class RES, class ARG>
    01720 struct ResultTraits0<UnaryFctPtrFunctor<EXPR, RES, ARG> >
    01721 {
    01722     typedef RES Res;
    01723 };
    01724
    01725 template <class EXPR, class RES, class ARG, class T1>
    01726 struct ResultTraits1<UnaryFctPtrFunctor<EXPR, RES, ARG>, T1>
    01727 {
    01728     typedef RES Res;
    01729 };
    01730
    01731 template <class EXPR, class RES, class ARG, class T1, class T2>
    01732 struct ResultTraits2<UnaryFctPtrFunctor<EXPR, RES, ARG>, T1, T2>
    01733 {
    01734     typedef RES Res;
    01735 };
    01736
    01737 template <class EXPR, class RES, class ARG, class T1, class T2, class T3>
    01738 struct ResultTraits3<UnaryFctPtrFunctor<EXPR, RES, ARG>, T1, T2, T3>
    01739 {
    01740     typedef RES Res;
    01741 };
    01742
    01743 template <class EXPR, class RES, class ARG>
    01744 UnaryFunctor<UnaryFctPtrFunctor<UnaryFunctor<EXPR>, RES, ARG> >
    01745 applyFct(RES (*f)(ARG), UnaryFunctor<EXPR> const & e)
    01746 {
    01747     UnaryFctPtrFunctor<UnaryFunctor<EXPR>, RES, ARG> p(e, f);
    01748     return UnaryFunctor<UnaryFctPtrFunctor<UnaryFunctor<EXPR>, RES, ARG> >(p);
    01749 }
    01750
    01751 /************************************************************/
    01752 /*                                                          */
    01753 /*                        binary apply                      */
    01754 /*                                                          */
    01755 /************************************************************/
    01756
    01757 template <class EXPR1, class EXPR2, class RES, class ARG1, class ARG2>
    01758 struct BinaryFctPtrFunctor
    01759 {
    01760     BinaryFctPtrFunctor(EXPR1 const & e1, EXPR2 const & e2,
    01761                         RES (*f)(ARG1, ARG2))
    01762     : expr1_(e1), expr2_(e2), f_(f)
    01763     {}
    01764
    01765     RES operator()() const
    01766     {
    01767         return f_(expr1_(), expr2_());
    01768     }
    01769
    01770     template <class T>
    01771     RES operator()(T const & v1) const
    01772     {
    01773         return f_(expr1_(v1), expr2_(v1));
    01774     }
    01775
    01776     template <class T1, class T2>
    01777     RES operator()(T1 const & v1, T2 const & v2) const
    01778     {
    01779         return f_(expr1_(v1, v2), expr2_(v1, v2));
    01780     }
    01781
    01782     template <class T1, class T2, class T3>
    01783     RES operator()(T1 const & v1, T2 const & v2, T3 const & v3) const
    01784     {
    01785         return f_(expr1_(v1, v2, v3), expr2_(v1, v2, v3));
    01786     }
    01787   protected:
    01788
    01789     EXPR1 expr1_;
    01790     EXPR2 expr2_;
    01791     RES (*f_)(ARG1, ARG2);
    01792 };
    01793
    01794 template <class EXPR1, class EXPR2, class RES, class ARG1, class ARG2>
    01795 struct ResultTraits0<BinaryFctPtrFunctor<EXPR1, EXPR2, RES, ARG1, ARG2> >
    01796 {
    01797     typedef RES Res;
    01798 };
    01799
    01800 template <class EXPR1, class EXPR2, class RES, class ARG1, class ARG2,
    01801           class T1>
    01802 struct ResultTraits1<BinaryFctPtrFunctor<EXPR1, EXPR2, RES, ARG1, ARG2>, T1>
    01803 {
    01804     typedef RES Res;
    01805 };
    01806
    01807 template <class EXPR1, class EXPR2, class RES, class ARG1, class ARG2,
    01808           class T1, class T2>
    01809 struct ResultTraits2<BinaryFctPtrFunctor<EXPR1, EXPR2, RES, ARG1, ARG2>, T1, T2>
    01810 {
    01811     typedef RES Res;
    01812 };
    01813
    01814 template <class EXPR1, class EXPR2, class RES, class ARG1, class ARG2,
    01815           class T1, class T2, class T3>
    01816 struct ResultTraits3<BinaryFctPtrFunctor<EXPR1, EXPR2, RES, ARG1, ARG2>, T1, T2, T3>
    01817 {
    01818     typedef RES Res;
    01819 };
    01820
    01821 template <class EXPR1, class EXPR2, class RES, class ARG1, class ARG2>
    01822 UnaryFunctor<BinaryFctPtrFunctor<UnaryFunctor<EXPR1>,
    01823                                  UnaryFunctor<EXPR2>,
    01824                                  RES, ARG1, ARG2> >
    01825 applyFct(RES (*f)(ARG1, ARG2), UnaryFunctor<EXPR1> const & e1,
    01826          UnaryFunctor<EXPR2> const & e2)
    01827 {
    01828     BinaryFctPtrFunctor<UnaryFunctor<EXPR1>,
    01829                         UnaryFunctor<EXPR2>,
    01830                         RES, ARG1, ARG2>  p(e1, e2, f);
    01831     return UnaryFunctor<BinaryFctPtrFunctor<UnaryFunctor<EXPR1>,
    01832                                             UnaryFunctor<EXPR2>,
    01833                                             RES, ARG1, ARG2> >(p);
    01834 }
    01835
    01836 /************************************************************/
    01837 /*                                                          */
    01838 /*                      comma operator                      */
    01839 /*                                                          */
    01840 /************************************************************/
    01841
    01842 template <class EXPR1, class EXPR2>
    01843 struct CommaFunctor
    01844 {
    01845     CommaFunctor(EXPR1 const & e1, EXPR2 const & e2)
    01846     : expr1_(e1), expr2_(e2)
    01847     {}
    01848
    01849     typename ResultTraits0<EXPR2>::Res
    01850     operator()() const
    01851     {
    01852         expr1_();
    01853         return expr2_();
    01854     }
    01855
    01856     template <class T>
    01857     typename ResultTraits1<EXPR2, T>::Res
    01858     operator()(T const & v1) const
    01859     {
    01860         expr1_(v1);
    01861         return expr2_(v1);
    01862     }
    01863
    01864     template <class T1, class T2>
    01865     typename ResultTraits2<EXPR2, T1, T2>::Res
    01866     operator()(T1 const & v1, T2 const & v2) const
    01867     {
    01868         expr1_(v1, v2);
    01869         return expr2_(v1, v2);
    01870     }
    01871
    01872     template <class T1, class T2, class T3>
    01873     typename ResultTraits3<EXPR2, T1, T2, T3>::Res
    01874     operator()(T1 const & v1, T2 const & v2, T3 const & v3) const
    01875     {
    01876         expr1_(v1, v2, v3);
    01877         return expr2_(v1, v2, v3);
    01878     }
    01879
    01880   protected:
    01881
    01882     EXPR1 expr1_;
    01883     EXPR2 expr2_;
    01884 };
    01885
    01886 template <class Expr1, class Expr2>
    01887 struct ResultTraits0<CommaFunctor<Expr1, Expr2> >
    01888 {
    01889     typedef typename ResultTraits0<Expr2>::Res Res;
    01890 };
    01891
    01892 template <class Expr1, class Expr2, class T1>
    01893 struct ResultTraits1<CommaFunctor<Expr1, Expr2>, T1>
    01894 {
    01895     typedef typename ResultTraits1<Expr2, T1>::Res Res;
    01896 };
    01897
    01898 template <class Expr1, class Expr2, class T1, class T2>
    01899 struct ResultTraits2<CommaFunctor<Expr1, Expr2>, T1, T2>
    01900 {
    01901     typedef typename ResultTraits2<Expr2, T1, T2>::Res Res;
    01902 };
    01903
    01904 template <class Expr1, class Expr2, class T1, class T2, class T3>
    01905 struct ResultTraits3<CommaFunctor<Expr1, Expr2>, T1, T2, T3>
    01906 {
    01907     typedef typename ResultTraits3<Expr2, T1, T2, T3>::Res Res;
    01908 };
    01909
    01910 template <class EXPR1, class EXPR2>
    01911 UnaryFunctor<CommaFunctor<UnaryAnalyser<EXPR1>,
    01912                             UnaryFunctor<EXPR2> > >
    01913 operator,(UnaryAnalyser<EXPR1> const & e1,
    01914           UnaryFunctor<EXPR2> const & e2)
    01915 {
    01916     CommaFunctor<UnaryAnalyser<EXPR1>,
    01917                             UnaryFunctor<EXPR2> >  p(e1, e2);
    01918     return UnaryFunctor<CommaFunctor<UnaryAnalyser<EXPR1>,
    01919                             UnaryFunctor<EXPR2> > >(p);
    01920 }
    01921
    01922 /************************************************************/
    01923
    01924 template <class EXPR1, class EXPR2>
    01925 struct CommaAnalyser
    01926 {
    01927     CommaAnalyser(EXPR1 const & e1, EXPR2 const & e2)
    01928     : expr1_(e1), expr2_(e2)
    01929     {}
    01930
    01931     void operator()() const
    01932     {
    01933         expr1_();
    01934         expr2_();
    01935     }
    01936
    01937     template <class T>
    01938     void operator()(T const & v1) const
    01939     {
    01940         expr1_(v1);
    01941         expr2_(v1);
    01942     }
    01943
    01944     template <class T1, class T2>
    01945     void operator()(T1 const & v1, T2 const & v2) const
    01946     {
    01947         expr1_(v1, v2);
    01948         expr2_(v1, v2);
    01949     }
    01950
    01951     template <class T1, class T2, class T3>
    01952     void operator()(T1 const & v1, T2 const & v2, T3 const & v3) const
    01953     {
    01954         expr1_(v1, v2, v3);
    01955         expr2_(v1, v2, v3);
    01956     }
    01957
    01958   protected:
    01959
    01960     EXPR1 expr1_;
    01961     EXPR2 expr2_;
    01962 };
    01963
    01964 template <class EXPR1, class EXPR2>
    01965 UnaryAnalyser<CommaAnalyser<UnaryAnalyser<EXPR1>,
    01966                             UnaryAnalyser<EXPR2> > >
    01967 operator,(UnaryAnalyser<EXPR1> const & e1,
    01968           UnaryAnalyser<EXPR2> const & e2)
    01969 {
    01970     CommaAnalyser<UnaryAnalyser<EXPR1>,
    01971                             UnaryAnalyser<EXPR2> >  p(e1, e2);
    01972     return UnaryAnalyser<CommaAnalyser<UnaryAnalyser<EXPR1>,
    01973                             UnaryAnalyser<EXPR2> > >(p);
    01974 }
    01975
    01976 } // namespace functor
    01977
    01978 #if defined(__GNUC__) &&  __GNUC__ < 3
    01979 using functor::Arg1;
    01980 using functor::Arg2;
    01981 using functor::Arg3;
    01982 using functor::Param;
    01983 #endif
    01984
    01985 template <class T>
    01986 class FunctorTraits<functor::UnaryFunctor<T> >
    01987 : public FunctorTraitsBase<functor::UnaryFunctor<T> >
    01988 {
    01989   public:
    01990     typedef VigraTrueType isInitializer;
    01991     typedef VigraTrueType isUnaryFunctor;
    01992     typedef VigraTrueType isBinaryFunctor;
    01993     typedef VigraTrueType isTernaryFunctor;
    01994 };
    01995
    01996 template <class T>
    01997 class FunctorTraits<functor::UnaryAnalyser<T> >
    01998 : public FunctorTraitsBase<functor::UnaryAnalyser<T> >
    01999 {
    02000   public:
    02001     typedef VigraTrueType isUnaryAnalyser;
    02002     typedef VigraTrueType isBinaryAnalyser;
    02003     typedef VigraTrueType isTernaryAnalyser;
    02004 };
    02005
    02006
    02007
    02008 } // namespace vigra
    02009
    02010 #endif /* NO_PARTIAL_TEMPLATE_SPECIALIZATION */
    02011
    02012 #endif // DOXYGEN
    02013
    02014 #endif /* VIGRA_FUNCTOREXPRESSION_HXX  */
    02015
    02016

© Ullrich Köthe (koethe@informatik.uni-hamburg.de) Cognitive Systems Group, University of Hamburg, Germany | html generated using doxygen and Python VIGRA 1.5.0 (7 Dec 2006)