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