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

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