[ 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> 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) |
html generated using doxygen and Python
|