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