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

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

© 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.7.0 (Thu Aug 25 2011)