vigra - vigra/functorexpression.hxx Source File

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

© Ullrich Köthe (ullrich.koethe@iwr.uni-heidelberg.de) Heidelberg Collaboratory for Image Processing, University of Heidelberg, Germany | html generated using doxygen and Python vigra 1.9.0 (Tue Nov 6 2012)