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