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

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

html generated using doxygen and Python
VIGRA 1.4.0 (21 Dec 2005)