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

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

html generated using doxygen and Python
VIGRA 1.2.0 (7 Aug 2003)