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

vigra/functorexpression.hxx

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

© Ullrich Köthe (ullrich.koethe@iwr.uni-heidelberg.de)
Heidelberg Collaboratory for Image Processing, University of Heidelberg, Germany

html generated using doxygen and Python
VIGRA 1.6.0 (5 Nov 2009)