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

vigra/functorexpression.hxx VIGRA

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

© 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.9.0 (Tue Nov 6 2012)