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

© 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 (13 Aug 2008)