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

details vigra/functorexpression.hxx VIGRA

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

© Ullrich Köthe (koethe@informatik.uni-hamburg.de)
Cognitive Systems Group, University of Hamburg, Germany

html generated using doxygen and Python
VIGRA 1.3.3 (18 Aug 2005)