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

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

html generated using doxygen and Python
VIGRA 1.5.0 (7 Dec 2006)