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

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

html generated using doxygen and Python
vigra 1.8.0 (20 Sep 2011)