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

vigra/functorexpression.hxx |

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

© Ullrich Köthe (ullrich.koethe@iwr.uni-heidelberg.de) Heidelberg Collaboratory for Image Processing, University of Heidelberg, Germany | html generated using doxygen and Python vigra 1.7.1 (3 Dec 2010)