[ VIGRA Homepage | Function Index | Class Index | Namespaces | File List | Main Page ]
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> <<a href="functorexpression_8hxx-source.html">vigra/functorexpression.hxx</a>><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 programm 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 maintainance 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 suported). 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 seperated 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="http://hci.iwr.uni-heidelberg.de/vigra/doc/vigra/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 template <> 00474 struct ResultTraits0<UnaryFunctor<ArgumentFunctor1> > 00475 { 00476 typedef ErrorType Res; 00477 }; 00478 00479 template <class T1> 00480 struct ResultTraits1<UnaryFunctor<ArgumentFunctor1>, T1> 00481 { 00482 typedef T1 Res; 00483 }; 00484 00485 template <class T1, class T2> 00486 struct ResultTraits2<UnaryFunctor<ArgumentFunctor1>, T1, T2> 00487 { 00488 typedef T1 Res; 00489 }; 00490 00491 template <class T1, class T2, class T3> 00492 struct ResultTraits3<UnaryFunctor<ArgumentFunctor1>, T1, T2, T3> 00493 { 00494 typedef T1 Res; 00495 }; 00496 00497 /************************************************************/ 00498 00499 inline 00500 UnaryFunctor<ArgumentFunctor1> 00501 Arg1() 00502 { 00503 return UnaryFunctor<ArgumentFunctor1>(); 00504 } 00505 00506 /************************************************************/ 00507 00508 template <> 00509 struct UnaryFunctor<ArgumentFunctor2> 00510 { 00511 UnaryFunctor() 00512 {} 00513 00514 template <class T1, class T2> 00515 T2 const & operator()(T1 const &, T2 const & v2) const 00516 { 00517 return v2; 00518 } 00519 00520 template <class T1, class T2, class T3> 00521 T2 const & operator()(T1 const &, T2 const & v2, T3 const &) const 00522 { 00523 return v2; 00524 } 00525 00526 private: 00527 UnaryFunctor & operator=(UnaryFunctor const &); // not implemented 00528 }; 00529 00530 template <> 00531 struct ResultTraits0<UnaryFunctor<ArgumentFunctor2> > 00532 { 00533 typedef ErrorType Res; 00534 }; 00535 00536 template <class T1> 00537 struct ResultTraits1<UnaryFunctor<ArgumentFunctor2>, T1> 00538 { 00539 typedef ErrorType Res; 00540 }; 00541 00542 template <class T1, class T2> 00543 struct ResultTraits2<UnaryFunctor<ArgumentFunctor2>, T1, T2> 00544 { 00545 typedef T2 Res; 00546 }; 00547 00548 template <class T1, class T2, class T3> 00549 struct ResultTraits3<UnaryFunctor<ArgumentFunctor2>, T1, T2, T3> 00550 { 00551 typedef T2 Res; 00552 }; 00553 00554 /************************************************************/ 00555 00556 inline 00557 UnaryFunctor<ArgumentFunctor2> 00558 Arg2() 00559 { 00560 return UnaryFunctor<ArgumentFunctor2>(); 00561 } 00562 00563 /************************************************************/ 00564 00565 template <> 00566 struct UnaryFunctor<ArgumentFunctor3> 00567 { 00568 UnaryFunctor() 00569 {} 00570 00571 template <class T1, class T2, class T3> 00572 T3 const & operator()(T1 const &, T2 const &, T3 const & v3) const 00573 { 00574 return v3; 00575 } 00576 00577 private: 00578 UnaryFunctor & operator=(UnaryFunctor const &); // not implemented 00579 }; 00580 00581 template <> 00582 struct ResultTraits0<UnaryFunctor<ArgumentFunctor3> > 00583 { 00584 typedef ErrorType Res; 00585 }; 00586 00587 template <class T1> 00588 struct ResultTraits1<UnaryFunctor<ArgumentFunctor3>, T1> 00589 { 00590 typedef ErrorType Res; 00591 }; 00592 00593 template <class T1, class T2> 00594 struct ResultTraits2<UnaryFunctor<ArgumentFunctor3>, T1, T2> 00595 { 00596 typedef ErrorType Res; 00597 }; 00598 00599 template <class T1, class T2, class T3> 00600 struct ResultTraits3<UnaryFunctor<ArgumentFunctor3>, T1, T2, T3> 00601 { 00602 typedef T3 Res; 00603 }; 00604 00605 /************************************************************/ 00606 00607 inline 00608 UnaryFunctor<ArgumentFunctor3> 00609 Arg3() 00610 { 00611 return UnaryFunctor<ArgumentFunctor3>(); 00612 } 00613 00614 /************************************************************/ 00615 /* */ 00616 /* constant parameters */ 00617 /* */ 00618 /************************************************************/ 00619 00620 template <class T> 00621 struct ParameterFunctor 00622 { 00623 ParameterFunctor(T v) 00624 : value_(v) 00625 {} 00626 00627 T const & operator()() const 00628 { 00629 return value_; 00630 } 00631 00632 template <class U1> 00633 T const & operator()(U1 const &) const 00634 { 00635 return value_; 00636 } 00637 00638 template <class U1, class U2> 00639 T const & operator()(U1 const &, U2 const &) const 00640 { 00641 return value_; 00642 } 00643 00644 template <class U1, class U2, class U3> 00645 T const & operator()(U1 const &, U2 const &, U3 const &) const 00646 { 00647 return value_; 00648 } 00649 00650 protected: 00651 T value_; 00652 00653 private: 00654 ParameterFunctor & operator=(ParameterFunctor const &); // not implemented 00655 }; 00656 00657 template <class T> 00658 struct ResultTraits0<ParameterFunctor<T> > 00659 { 00660 typedef T Res; 00661 }; 00662 00663 template <class T, class T1> 00664 struct ResultTraits1<ParameterFunctor<T>, T1> 00665 { 00666 typedef T Res; 00667 }; 00668 00669 template <class T, class T1, class T2> 00670 struct ResultTraits2<ParameterFunctor<T>, T1, T2> 00671 { 00672 typedef T Res; 00673 }; 00674 00675 template <class T, class T1, class T2, class T3> 00676 struct ResultTraits3<ParameterFunctor<T>, T1, T2, T3> 00677 { 00678 typedef T Res; 00679 }; 00680 00681 template <class T> 00682 inline UnaryFunctor<ParameterFunctor<T> > 00683 Param(T const & v) 00684 { 00685 ParameterFunctor<T> fv(v); 00686 return UnaryFunctor<ParameterFunctor<T> >(fv); 00687 } 00688 00689 /************************************************************/ 00690 /* */ 00691 /* unary analyser base template */ 00692 /* */ 00693 /************************************************************/ 00694 00695 00696 template <class EXPR> 00697 class UnaryAnalyser 00698 { 00699 public: 00700 UnaryAnalyser(EXPR const & e) 00701 : expr_(e) 00702 {} 00703 00704 void operator()() const 00705 { 00706 expr_(); 00707 } 00708 00709 template <class T1> 00710 void operator()(T1 const & v) const 00711 { 00712 expr_(v); 00713 } 00714 00715 template <class T1, class T2> 00716 void operator()(T1 const & v1, T2 const & v2) const 00717 { 00718 expr_(v1, v2); 00719 } 00720 00721 template <class T1, class T2, class T3> 00722 void operator()(T1 const & v1, T2 const & v2, T3 const & v3) const 00723 { 00724 expr_(v1, v2, v3); 00725 } 00726 protected: 00727 00728 EXPR expr_; 00729 00730 private: 00731 UnaryAnalyser & operator=(UnaryAnalyser const &); // not implemented 00732 }; 00733 00734 /************************************************************/ 00735 /* */ 00736 /* variable assignment */ 00737 /* */ 00738 /************************************************************/ 00739 00740 template <class T> 00741 struct VarFunctor; 00742 00743 template <class T> 00744 struct UnaryFunctor<VarFunctor<T> >; 00745 00746 /************************************************************/ 00747 00748 #define MAKE_ASSIGNMENT_FUNCTOR(name, op) \ 00749 template <class V, class EXPR> \ 00750 struct AssignmentFunctor_##name \ 00751 { \ 00752 AssignmentFunctor_##name(UnaryFunctor<VarFunctor<V> > v, \ 00753 UnaryFunctor<EXPR> const & e) \ 00754 : value_(v.value_), expr_(e) \ 00755 {} \ 00756 \ 00757 V & operator()() const \ 00758 { \ 00759 const_cast<V &>(value_) op expr_(); \ 00760 return const_cast<V &>(value_); \ 00761 } \ 00762 \ 00763 template <class T1> \ 00764 V & operator()(T1 const & v1) const \ 00765 { \ 00766 const_cast<V &>(value_) op expr_(v1); \ 00767 return const_cast<V &>(value_); \ 00768 } \ 00769 \ 00770 template <class T1, class T2> \ 00771 V & operator()(T1 const & v1, T2 const & v2) const \ 00772 { \ 00773 const_cast<V &>(value_) op expr_(v1, v2); \ 00774 return const_cast<V &>(value_); \ 00775 } \ 00776 \ 00777 template <class T1, class T2, class T3> \ 00778 V & operator()(T1 const & v1, T2 const & v2, T3 const & v3) const \ 00779 { \ 00780 const_cast<V &>(value_) op expr_(v1, v2, v3); \ 00781 return const_cast<V &>(value_); \ 00782 } \ 00783 \ 00784 private: \ 00785 V & value_; \ 00786 UnaryFunctor<EXPR> expr_; \ 00787 \ 00788 AssignmentFunctor_##name & operator=(AssignmentFunctor_##name const &);\ 00789 }; 00790 00791 /************************************************************/ 00792 00793 MAKE_ASSIGNMENT_FUNCTOR(assign, =) 00794 MAKE_ASSIGNMENT_FUNCTOR(add, +=) 00795 MAKE_ASSIGNMENT_FUNCTOR(subtract, -=) 00796 MAKE_ASSIGNMENT_FUNCTOR(multiply, *=) 00797 MAKE_ASSIGNMENT_FUNCTOR(divide, /=) 00798 00799 #undef MAKE_ASSIGNMENT_FUNCTOR 00800 00801 /************************************************************/ 00802 /* */ 00803 /* variables */ 00804 /* */ 00805 /************************************************************/ 00806 00807 template <class T> 00808 struct UnaryFunctor<VarFunctor<T> > 00809 { 00810 typedef T Res; 00811 00812 UnaryFunctor(T & v) 00813 : value_(v) 00814 {} 00815 00816 template <class EXPR> 00817 UnaryAnalyser< AssignmentFunctor_assign<T, UnaryFunctor<EXPR> > > 00818 operator=(UnaryFunctor<EXPR> const & e) 00819 { 00820 AssignmentFunctor_assign<T, UnaryFunctor<EXPR> > va(*this, e); 00821 return UnaryAnalyser< AssignmentFunctor_assign<T, UnaryFunctor<EXPR> > >(va); 00822 } 00823 00824 template <class EXPR> 00825 UnaryAnalyser< AssignmentFunctor_add<T, UnaryFunctor<EXPR> > > 00826 operator+=(UnaryFunctor<EXPR> const & e) 00827 { 00828 AssignmentFunctor_add<T, UnaryFunctor<EXPR> > va(*this, e); 00829 return UnaryAnalyser< AssignmentFunctor_add<T, UnaryFunctor<EXPR> > >(va); 00830 } 00831 00832 template <class EXPR> 00833 UnaryAnalyser< AssignmentFunctor_subtract<T, UnaryFunctor<EXPR> > > 00834 operator-=(UnaryFunctor<EXPR> const & e) 00835 { 00836 AssignmentFunctor_subtract<T, UnaryFunctor<EXPR> > va(*this, e); 00837 return UnaryAnalyser< AssignmentFunctor_subtract<T, UnaryFunctor<EXPR> > >(va); 00838 } 00839 00840 template <class EXPR> 00841 UnaryAnalyser< AssignmentFunctor_multiply<T, UnaryFunctor<EXPR> > > 00842 operator*=(UnaryFunctor<EXPR> const & e) 00843 { 00844 AssignmentFunctor_multiply<T, UnaryFunctor<EXPR> > va(*this, e); 00845 return UnaryAnalyser< AssignmentFunctor_multiply<T, UnaryFunctor<EXPR> > >(va); 00846 } 00847 00848 template <class EXPR> 00849 UnaryAnalyser< AssignmentFunctor_divide<T, UnaryFunctor<EXPR> > > 00850 operator/=(UnaryFunctor<EXPR> const & e) 00851 { 00852 AssignmentFunctor_divide<T, UnaryFunctor<EXPR> > va(*this, e); 00853 return UnaryAnalyser< AssignmentFunctor_divide<T, UnaryFunctor<EXPR> > >(va); 00854 } 00855 00856 T const & operator()() const 00857 { 00858 return value_; 00859 } 00860 00861 template <class U1> 00862 T const & operator()(U1 const &) const 00863 { 00864 return value_; 00865 } 00866 00867 template <class U1, class U2> 00868 T const & operator()(U1 const &, U2 const &) const 00869 { 00870 return value_; 00871 } 00872 00873 template <class U1, class U2, class U3> 00874 T const & operator()(U1 const &, U2 const &, U3 const &) const 00875 { 00876 return value_; 00877 } 00878 00879 T & value_; 00880 00881 private: 00882 UnaryFunctor & operator=(UnaryFunctor const &); // not implemented 00883 }; 00884 00885 template <class T> 00886 struct ResultTraits0<UnaryFunctor<VarFunctor<T> > > 00887 { 00888 typedef T Res; 00889 }; 00890 00891 template <class T, class T1> 00892 struct ResultTraits1<UnaryFunctor<VarFunctor<T> >, T1> 00893 { 00894 typedef T Res; 00895 }; 00896 00897 template <class T, class T1, class T2> 00898 struct ResultTraits2<UnaryFunctor<VarFunctor<T> >, T1, T2> 00899 { 00900 typedef T Res; 00901 }; 00902 00903 template <class T, class T1, class T2, class T3> 00904 struct ResultTraits3<UnaryFunctor<VarFunctor<T> >, T1, T2, T3> 00905 { 00906 typedef T Res; 00907 }; 00908 00909 template <class T> 00910 inline UnaryFunctor<VarFunctor<T> > 00911 Var(T & v) 00912 { 00913 return UnaryFunctor<VarFunctor<T> >(v); 00914 } 00915 00916 /************************************************************/ 00917 /* */ 00918 /* if then */ 00919 /* */ 00920 /************************************************************/ 00921 00922 template <class EXPR1, class EXPR2> 00923 struct IfThenFunctor 00924 { 00925 typedef void Res; 00926 00927 IfThenFunctor(EXPR1 const & e1, EXPR2 const & e2) 00928 : expr1_(e1), expr2_(e2) 00929 {} 00930 00931 void operator()() const 00932 { 00933 if( expr1_() ) expr2_(); 00934 } 00935 00936 template <class T> 00937 void operator()(T const & v1) const 00938 { 00939 if( expr1_(v1) ) expr2_(v1); 00940 } 00941 00942 template <class T1, class T2> 00943 void operator()(T1 const & v1, T2 const & v2) const 00944 { 00945 if( expr1_(v1, v2) ) expr2_(v1, v2); 00946 } 00947 00948 template <class T1, class T2, class T3> 00949 void operator()(T1 const & v1, T2 const & v2, T3 const & v3) const 00950 { 00951 if( expr1_(v1, v2, v3) ) expr2_(v1, v2, v3); 00952 } 00953 00954 private: 00955 00956 EXPR1 expr1_; 00957 EXPR2 expr2_; 00958 00959 private: 00960 IfThenFunctor & operator=(IfThenFunctor const &); // not implemented 00961 }; 00962 00963 template <class EXPR1, class EXPR2> 00964 UnaryAnalyser<IfThenFunctor<UnaryFunctor<EXPR1>, 00965 UnaryAnalyser<EXPR2> > > 00966 ifThen(UnaryFunctor<EXPR1> const & e1, 00967 UnaryAnalyser<EXPR2> const & e2) 00968 { 00969 IfThenFunctor<UnaryFunctor<EXPR1>, 00970 UnaryAnalyser<EXPR2> > p(e1, e2); 00971 return UnaryAnalyser<IfThenFunctor<UnaryFunctor<EXPR1>, 00972 UnaryAnalyser<EXPR2> > >(p); 00973 } 00974 00975 /************************************************************/ 00976 /* */ 00977 /* if then else */ 00978 /* */ 00979 /************************************************************/ 00980 00981 template <class EXPR1, class EXPR2, class EXPR3> 00982 struct IfThenElseFunctor; 00983 00984 template <class EXPR1, class EXPR2, class EXPR3> 00985 struct ResultTraits0<IfThenElseFunctor<EXPR1, EXPR2, EXPR3> > 00986 { 00987 typedef typename ResultTraits0<EXPR2>::Res R2; 00988 typedef typename ResultTraits0<EXPR3>::Res R3; 00989 typedef typename PromoteTraits<R2, R3>::Promote Res; 00990 }; 00991 00992 template <class EXPR1, class EXPR2, class EXPR3, class T1> 00993 struct ResultTraits1<IfThenElseFunctor<EXPR1, EXPR2, EXPR3>, T1> 00994 { 00995 typedef typename ResultTraits1<EXPR2, T1>::Res R2; 00996 typedef typename ResultTraits1<EXPR3, T1>::Res R3; 00997 typedef typename PromoteTraits<R2, R3>::Promote Res; 00998 }; 00999 01000 template <class EXPR1, class EXPR2, class EXPR3, class T1, class T2> 01001 struct ResultTraits2<IfThenElseFunctor<EXPR1, EXPR2, EXPR3>, T1, T2> 01002 { 01003 typedef typename ResultTraits2<EXPR2, T1, T2>::Res R2; 01004 typedef typename ResultTraits2<EXPR3, T1, T2>::Res R3; 01005 typedef typename PromoteTraits<R2, R3>::Promote Res; 01006 }; 01007 01008 template <class EXPR1, class EXPR2, class EXPR3, class T1, class T2, class T3> 01009 struct ResultTraits3<IfThenElseFunctor<EXPR1, EXPR2, EXPR3>, T1, T2, T3> 01010 { 01011 typedef typename ResultTraits3<EXPR2, T1, T2, T3>::Res R2; 01012 typedef typename ResultTraits3<EXPR3, T1, T2, T3>::Res R3; 01013 typedef typename PromoteTraits<R2, R3>::Promote Res; 01014 }; 01015 01016 template <class EXPR1, class EXPR2, class EXPR3> 01017 struct IfThenElseFunctor 01018 { 01019 IfThenElseFunctor(EXPR1 const & e1, EXPR2 const & e2, EXPR3 const & e3) 01020 : expr1_(e1), expr2_(e2), expr3_(e3) 01021 {} 01022 01023 typename ResultTraits0<IfThenElseFunctor>::Res 01024 operator()() const 01025 { 01026 if(expr1_()) 01027 { 01028 return typename ResultTraits0<IfThenElseFunctor>::Res(expr2_()); 01029 } 01030 else 01031 { 01032 return typename ResultTraits0<IfThenElseFunctor>::Res(expr3_()); 01033 } 01034 } 01035 01036 template <class T> 01037 typename ResultTraits1<IfThenElseFunctor, T>::Res 01038 operator()(T const & v1) const 01039 { 01040 if(expr1_(v1)) 01041 { 01042 return typename ResultTraits1<IfThenElseFunctor, T>::Res(expr2_(v1)); 01043 } 01044 else 01045 { 01046 return typename ResultTraits1<IfThenElseFunctor, T>::Res(expr3_(v1)); 01047 } 01048 } 01049 01050 template <class T1, class T2> 01051 typename ResultTraits2<IfThenElseFunctor, T1, T2>::Res 01052 operator()(T1 const & v1, T2 const & v2) const 01053 { 01054 if(expr1_(v1, v2)) 01055 { 01056 return typename ResultTraits2<IfThenElseFunctor, T1, T2>::Res(expr2_(v1, v2)); 01057 } 01058 else 01059 { 01060 return typename ResultTraits2<IfThenElseFunctor, T1, T2>::Res(expr3_(v1, v2)); 01061 } 01062 } 01063 01064 template <class T1, class T2, class T3> 01065 typename ResultTraits3<IfThenElseFunctor, T1, T2, T3>::Res 01066 operator()(T1 const & v1, T2 const & v2, T3 const & v3) const 01067 { 01068 if(expr1_(v1, v2, v3)) 01069 { 01070 return typename ResultTraits3<IfThenElseFunctor, T1, T2, T3>::Res(expr2_(v1, v2, v3)); 01071 } 01072 else 01073 { 01074 return typename ResultTraits3<IfThenElseFunctor, T1, T2, T3>::Res(expr3_(v1, v2, v3)); 01075 } 01076 } 01077 01078 private: 01079 01080 EXPR1 expr1_; 01081 EXPR2 expr2_; 01082 EXPR3 expr3_; 01083 01084 IfThenElseFunctor & operator=(IfThenElseFunctor const &); // not implemented 01085 }; 01086 01087 template <class EXPR1, class EXPR2, class EXPR3> 01088 UnaryFunctor<IfThenElseFunctor<UnaryFunctor<EXPR1>, 01089 UnaryFunctor<EXPR2>, 01090 UnaryFunctor<EXPR3> > > 01091 ifThenElse(UnaryFunctor<EXPR1> const & e1, 01092 UnaryFunctor<EXPR2> const & e2, 01093 UnaryFunctor<EXPR3> const & e3) 01094 { 01095 IfThenElseFunctor<UnaryFunctor<EXPR1>, 01096 UnaryFunctor<EXPR2>, 01097 UnaryFunctor<EXPR3> > p(e1, e2, e3); 01098 return UnaryFunctor<IfThenElseFunctor<UnaryFunctor<EXPR1>, 01099 UnaryFunctor<EXPR2>, 01100 UnaryFunctor<EXPR3> > >(p); 01101 } 01102 01103 /************************************************************/ 01104 /* */ 01105 /* functors for unary functions */ 01106 /* */ 01107 /************************************************************/ 01108 01109 #define MAKE_FUNCTOR_UNARY_FUNCTION(function, namespc, traitsClass, traitsValue) \ 01110 using ::namespc::function; \ 01111 template <class EXPR> \ 01112 struct Functor_##function; \ 01113 \ 01114 template <class EXPR> \ 01115 struct ResultTraits0<Functor_##function<EXPR> > \ 01116 { \ 01117 typedef typename ResultTraits0<EXPR>::Res R1; \ 01118 typedef typename traitsClass<R1>::traitsValue Res; \ 01119 }; \ 01120 \ 01121 template <class EXPR, class T1> \ 01122 struct ResultTraits1<Functor_##function<EXPR>, T1> \ 01123 { \ 01124 typedef typename ResultTraits1<EXPR, T1>::Res R1; \ 01125 typedef typename traitsClass<R1>::traitsValue Res; \ 01126 }; \ 01127 \ 01128 template <class EXPR, class T1, class T2> \ 01129 struct ResultTraits2<Functor_##function<EXPR>, T1, T2> \ 01130 { \ 01131 typedef typename ResultTraits2<EXPR, T1, T2>::Res R1; \ 01132 typedef typename traitsClass<R1>::traitsValue Res; \ 01133 }; \ 01134 \ 01135 template <class EXPR, class T1, class T2, class T3> \ 01136 struct ResultTraits3<Functor_##function<EXPR>, T1, T2, T3> \ 01137 { \ 01138 typedef typename ResultTraits3<EXPR, T1, T2, T3>::Res R1; \ 01139 typedef typename traitsClass<R1>::traitsValue Res; \ 01140 }; \ 01141 \ 01142 template <class EXPR> \ 01143 struct Functor_##function \ 01144 { \ 01145 Functor_##function(EXPR const & e) \ 01146 : expr_(e) \ 01147 {} \ 01148 \ 01149 typename ResultTraits0<Functor_##function>::Res \ 01150 operator()() const \ 01151 { \ 01152 return function(expr_()); \ 01153 } \ 01154 \ 01155 template <class T> \ 01156 typename ResultTraits1<Functor_##function, T>::Res \ 01157 operator()(T const & v1) const \ 01158 { \ 01159 return function(expr_(v1)); \ 01160 } \ 01161 \ 01162 template <class T1, class T2> \ 01163 typename ResultTraits2<Functor_##function, T1, T2>::Res \ 01164 operator()(T1 const & v1, T2 const & v2) const \ 01165 { \ 01166 return function(expr_(v1, v2)); \ 01167 } \ 01168 \ 01169 template <class T1, class T2, class T3> \ 01170 typename ResultTraits3<Functor_##function, T1, T2, T3>::Res \ 01171 operator()(T1 const & v1, T2 const & v2, T3 const & v3) const \ 01172 { \ 01173 return function(expr_(v1, v2, v3)); \ 01174 } \ 01175 \ 01176 protected: \ 01177 \ 01178 EXPR expr_; \ 01179 \ 01180 private: \ 01181 Functor_##function & operator=(Functor_##function const &); \ 01182 }; \ 01183 \ 01184 template <class EXPR> \ 01185 inline UnaryFunctor<Functor_##function<UnaryFunctor<EXPR> > > \ 01186 function(UnaryFunctor<EXPR> const & e) \ 01187 { \ 01188 Functor_##function<UnaryFunctor<EXPR> > p(e); \ 01189 return UnaryFunctor<Functor_##function<UnaryFunctor<EXPR> > >(p); \ 01190 } 01191 01192 /************************************************************/ 01193 01194 MAKE_FUNCTOR_UNARY_FUNCTION(sq, vigra, NumericTraits, RealPromote) 01195 MAKE_FUNCTOR_UNARY_FUNCTION(sqrt, std, NumericTraits, RealPromote) 01196 MAKE_FUNCTOR_UNARY_FUNCTION(exp, std, NumericTraits, RealPromote) 01197 MAKE_FUNCTOR_UNARY_FUNCTION(log, std, NumericTraits, RealPromote) 01198 MAKE_FUNCTOR_UNARY_FUNCTION(log10, std, NumericTraits, RealPromote) 01199 MAKE_FUNCTOR_UNARY_FUNCTION(sin, std, NumericTraits, RealPromote) 01200 MAKE_FUNCTOR_UNARY_FUNCTION(asin, std, NumericTraits, RealPromote) 01201 MAKE_FUNCTOR_UNARY_FUNCTION(cos, std, NumericTraits, RealPromote) 01202 MAKE_FUNCTOR_UNARY_FUNCTION(acos, std, NumericTraits, RealPromote) 01203 MAKE_FUNCTOR_UNARY_FUNCTION(tan, std, NumericTraits, RealPromote) 01204 MAKE_FUNCTOR_UNARY_FUNCTION(atan, std, NumericTraits, RealPromote) 01205 MAKE_FUNCTOR_UNARY_FUNCTION(floor, std, NumericTraits, RealPromote) 01206 MAKE_FUNCTOR_UNARY_FUNCTION(ceil, std, NumericTraits, RealPromote) 01207 MAKE_FUNCTOR_UNARY_FUNCTION(abs, vigra, NumericTraits, RealPromote) 01208 MAKE_FUNCTOR_UNARY_FUNCTION(norm, vigra, NormTraits, NormType) 01209 MAKE_FUNCTOR_UNARY_FUNCTION(squaredNorm, vigra, NormTraits, SquaredNormType) 01210 01211 #undef MAKE_FUNCTOR_UNARY_FUNCTION 01212 01213 /************************************************************/ 01214 /* */ 01215 /* functors for unary operators */ 01216 /* */ 01217 /************************************************************/ 01218 01219 #define MAKE_FUNCTOR_UNARY_OPERATOR(name, op) \ 01220 template <class EXPR> \ 01221 struct Functor_##name; \ 01222 \ 01223 template <class EXPR> \ 01224 struct ResultTraits0<Functor_##name<EXPR> > \ 01225 { \ 01226 typedef typename ResultTraits0<EXPR>::Res Res; \ 01227 }; \ 01228 \ 01229 template <class EXPR, class T1> \ 01230 struct ResultTraits1<Functor_##name<EXPR>, T1> \ 01231 { \ 01232 typedef typename ResultTraits1<EXPR, T1>::Res Res; \ 01233 }; \ 01234 \ 01235 template <class EXPR, class T1, class T2> \ 01236 struct ResultTraits2<Functor_##name<EXPR>, T1, T2> \ 01237 { \ 01238 typedef typename ResultTraits2<EXPR, T1, T2>::Res Res; \ 01239 }; \ 01240 \ 01241 template <class EXPR, class T1, class T2, class T3> \ 01242 struct ResultTraits3<Functor_##name<EXPR>, T1, T2, T3> \ 01243 { \ 01244 typedef typename ResultTraits3<EXPR, T1, T2, T3>::Res Res; \ 01245 }; \ 01246 \ 01247 template <class EXPR> \ 01248 struct Functor_##name \ 01249 { \ 01250 Functor_##name(EXPR const & e) \ 01251 : expr_(e) \ 01252 {} \ 01253 \ 01254 typename ResultTraits0<Functor_##name>::Res \ 01255 operator()() const \ 01256 { \ 01257 return op expr_(); \ 01258 } \ 01259 \ 01260 template <class T> \ 01261 typename ResultTraits1<Functor_##name, T>::Res \ 01262 operator()(T const & v1) const \ 01263 { \ 01264 return op expr_(v1); \ 01265 } \ 01266 \ 01267 template <class T1, class T2> \ 01268 typename ResultTraits2<Functor_##name, T1, T2>::Res \ 01269 operator()(T1 const & v1, T2 const & v2) const \ 01270 { \ 01271 return op expr_(v1, v2); \ 01272 } \ 01273 \ 01274 template <class T1, class T2, class T3> \ 01275 typename ResultTraits3<Functor_##name, T1, T2, T3>::Res \ 01276 operator()(T1 const & v1, T2 const & v2, T3 const & v3) const \ 01277 { \ 01278 return op expr_(v1, v2, v3); \ 01279 } \ 01280 protected: \ 01281 \ 01282 EXPR expr_; \ 01283 \ 01284 private: \ 01285 Functor_##name & operator=(Functor_##name const &);\ 01286 }; \ 01287 \ 01288 template <class EXPR> \ 01289 inline UnaryFunctor<Functor_##name<UnaryFunctor<EXPR> > > \ 01290 operator op(UnaryFunctor<EXPR> const & e) \ 01291 { \ 01292 Functor_##name<UnaryFunctor<EXPR> > p(e); \ 01293 return UnaryFunctor<Functor_##name<UnaryFunctor<EXPR> > >(p); \ 01294 } 01295 01296 01297 /************************************************************/ 01298 01299 MAKE_FUNCTOR_UNARY_OPERATOR(minus, -) 01300 MAKE_FUNCTOR_UNARY_OPERATOR(negate, !) 01301 MAKE_FUNCTOR_UNARY_OPERATOR(bitNegate, ~) 01302 01303 #undef MAKE_FUNCTOR_UNARY_OPERATOR 01304 01305 /************************************************************/ 01306 /* */ 01307 /* functors for binary functions */ 01308 /* */ 01309 /************************************************************/ 01310 01311 #define MAKE_FUNCTOR_BINARY_FUNCTION(function) \ 01312 using std::function; \ 01313 template <class EXPR1, class EXPR2> \ 01314 struct Functor_##function; \ 01315 \ 01316 template <class EXPR1, class EXPR2> \ 01317 struct ResultTraits0<Functor_##function<EXPR1, EXPR2> > \ 01318 { \ 01319 typedef typename ResultTraits0<EXPR1>::Res R1; \ 01320 typedef typename ResultTraits0<EXPR2>::Res R2; \ 01321 typedef typename PromoteTraits<R1, R2>::Promote R3; \ 01322 typedef typename NumericTraits<R3>::RealPromote Res; \ 01323 }; \ 01324 \ 01325 template <class EXPR1, class EXPR2, class T1> \ 01326 struct ResultTraits1<Functor_##function<EXPR1, EXPR2>, T1> \ 01327 { \ 01328 typedef typename ResultTraits1<EXPR1, T1>::Res R1; \ 01329 typedef typename ResultTraits1<EXPR2, T1>::Res R2; \ 01330 typedef typename PromoteTraits<R1, R2>::Promote R3; \ 01331 typedef typename NumericTraits<R3>::RealPromote Res; \ 01332 }; \ 01333 \ 01334 template <class EXPR1, class EXPR2, class T1, class T2> \ 01335 struct ResultTraits2<Functor_##function<EXPR1, EXPR2>, T1, T2> \ 01336 { \ 01337 typedef typename ResultTraits2<EXPR1, T1, T2>::Res R1; \ 01338 typedef typename ResultTraits2<EXPR2, T1, T2>::Res R2; \ 01339 typedef typename PromoteTraits<R1, R2>::Promote R3; \ 01340 typedef typename NumericTraits<R3>::RealPromote Res; \ 01341 }; \ 01342 \ 01343 template <class EXPR1, class EXPR2, class T1, class T2, class T3> \ 01344 struct ResultTraits3<Functor_##function<EXPR1, EXPR2>, T1, T2, T3> \ 01345 { \ 01346 typedef typename ResultTraits3<EXPR1, T1, T2, T3>::Res R1; \ 01347 typedef typename ResultTraits3<EXPR2, T1, T2, T3>::Res R2; \ 01348 typedef typename PromoteTraits<R1, R2>::Promote R3; \ 01349 typedef typename NumericTraits<R3>::RealPromote Res; \ 01350 }; \ 01351 \ 01352 template <class EXPR1, class EXPR2> \ 01353 struct Functor_##function \ 01354 { \ 01355 Functor_##function(EXPR1 const & e1, EXPR2 const & e2) \ 01356 : expr1_(e1), expr2_(e2) \ 01357 {} \ 01358 \ 01359 typename ResultTraits0<Functor_##function>::Res \ 01360 operator()() const \ 01361 { \ 01362 return function(expr1_(), expr2_()); \ 01363 } \ 01364 \ 01365 template <class T> \ 01366 typename ResultTraits1<Functor_##function, T>::Res \ 01367 operator()(T const & v1) const \ 01368 { \ 01369 return function(expr1_(v1), expr2_(v1)); \ 01370 } \ 01371 \ 01372 template <class T1, class T2> \ 01373 typename ResultTraits2<Functor_##function, T1, T2>::Res \ 01374 operator()(T1 const & v1, T2 const & v2) const \ 01375 { \ 01376 return function(expr1_(v1, v2), expr2_(v1, v2)); \ 01377 } \ 01378 \ 01379 template <class T1, class T2, class T3> \ 01380 typename ResultTraits3<Functor_##function, T1, T2, T3>::Res \ 01381 operator()(T1 const & v1, T2 const & v2, T3 const & v3) const \ 01382 { \ 01383 return function(expr1_(v1, v2, v3), expr2_(v1, v2, v3)); \ 01384 } \ 01385 \ 01386 private: \ 01387 \ 01388 EXPR1 expr1_; \ 01389 EXPR2 expr2_; \ 01390 \ 01391 Functor_##function & operator=(Functor_##function const &); \ 01392 }; \ 01393 \ 01394 template <class EXPR1, class EXPR2> \ 01395 inline UnaryFunctor<Functor_##function<UnaryFunctor<EXPR1>, UnaryFunctor<EXPR2> > > \ 01396 function(UnaryFunctor<EXPR1> const & e1, UnaryFunctor<EXPR2> const & e2) \ 01397 { \ 01398 Functor_##function<UnaryFunctor<EXPR1>, UnaryFunctor<EXPR2> > p(e1, e2); \ 01399 return UnaryFunctor<Functor_##function<UnaryFunctor<EXPR1>, \ 01400 UnaryFunctor<EXPR2> > >(p); \ 01401 } 01402 01403 /************************************************************/ 01404 01405 MAKE_FUNCTOR_BINARY_FUNCTION(pow) 01406 MAKE_FUNCTOR_BINARY_FUNCTION(atan2) 01407 MAKE_FUNCTOR_BINARY_FUNCTION(fmod) 01408 01409 #undef MAKE_FUNCTOR_BINARY_FUNCTION 01410 01411 /************************************************************/ 01412 01413 #define MAKE_FUNCTOR_MINMAX(name, op) \ 01414 template <class EXPR1, class EXPR2> \ 01415 struct Functor_##name; \ 01416 \ 01417 template <class EXPR1, class EXPR2> \ 01418 struct ResultTraits0<Functor_##name<EXPR1, EXPR2> > \ 01419 { \ 01420 typedef typename ResultTraits0<EXPR1>::Res R1; \ 01421 typedef typename ResultTraits0<EXPR2>::Res R2; \ 01422 typedef typename PromoteTraits<R1, R2>::Promote Res; \ 01423 }; \ 01424 \ 01425 template <class EXPR1, class EXPR2, class T1> \ 01426 struct ResultTraits1<Functor_##name<EXPR1, EXPR2>, T1> \ 01427 { \ 01428 typedef typename ResultTraits1<EXPR1, T1>::Res R1; \ 01429 typedef typename ResultTraits1<EXPR2, T1>::Res R2; \ 01430 typedef typename PromoteTraits<R1, R2>::Promote Res; \ 01431 }; \ 01432 \ 01433 template <class EXPR1, class EXPR2, class T1, class T2> \ 01434 struct ResultTraits2<Functor_##name<EXPR1, EXPR2>, T1, T2> \ 01435 { \ 01436 typedef typename ResultTraits2<EXPR1, T1, T2>::Res R1; \ 01437 typedef typename ResultTraits2<EXPR2, T1, T2>::Res R2; \ 01438 typedef typename PromoteTraits<R1, R2>::Promote Res; \ 01439 }; \ 01440 \ 01441 template <class EXPR1, class EXPR2, class T1, class T2, class T3> \ 01442 struct ResultTraits3<Functor_##name<EXPR1, EXPR2>, T1, T2, T3> \ 01443 { \ 01444 typedef typename ResultTraits3<EXPR1, T1, T2, T3>::Res R1; \ 01445 typedef typename ResultTraits3<EXPR2, T1, T2, T3>::Res R2; \ 01446 typedef typename PromoteTraits<R1, R2>::Promote Res; \ 01447 }; \ 01448 \ 01449 template <class EXPR1, class EXPR2> \ 01450 struct Functor_##name \ 01451 { \ 01452 Functor_##name(EXPR1 const & e1, EXPR2 const & e2) \ 01453 : expr1_(e1), expr2_(e2) \ 01454 {} \ 01455 \ 01456 typename ResultTraits0<Functor_##name>::Res \ 01457 operator()() const \ 01458 { \ 01459 typename \ 01460 ResultTraits0<Functor_##name<EXPR1, EXPR2> >::R1 r1(expr1_()); \ 01461 typename \ 01462 ResultTraits0<Functor_##name<EXPR1, EXPR2> >::R2 r2(expr2_()); \ 01463 return (r1 op r2) ? r1 : r2; \ 01464 } \ 01465 \ 01466 template <class T> \ 01467 typename ResultTraits1<Functor_##name, T>::Res \ 01468 operator()(T const & v1) const \ 01469 { \ 01470 typename \ 01471 ResultTraits1<Functor_##name<EXPR1, EXPR2>, T>::R1 r1(expr1_(v1)); \ 01472 typename \ 01473 ResultTraits1<Functor_##name<EXPR1, EXPR2>, T>::R2 r2(expr2_(v1)); \ 01474 return (r1 op r2) ? r1 : r2; \ 01475 } \ 01476 \ 01477 template <class T1, class T2> \ 01478 typename ResultTraits2<Functor_##name, T1, T2>::Res \ 01479 operator()(T1 const & v1, T2 const & v2) const \ 01480 { \ 01481 typename \ 01482 ResultTraits2<Functor_##name<EXPR1, EXPR2>, T1, T2>::R1 r1(expr1_(v1, v2)); \ 01483 typename \ 01484 ResultTraits2<Functor_##name<EXPR1, EXPR2>, T1, T2>::R2 r2(expr2_(v1, v2)); \ 01485 return (r1 op r2) ? r1 : r2; \ 01486 } \ 01487 \ 01488 template <class T1, class T2, class T3> \ 01489 typename ResultTraits3<Functor_##name, T1, T2, T3>::Res \ 01490 operator()(T1 const & v1, T2 const & v2, T3 const & v3) const \ 01491 { \ 01492 typename \ 01493 ResultTraits3<Functor_##name<EXPR1, EXPR2>, T1, T2, T3>::R1 r1(expr1_(v1, v2, v3)); \ 01494 typename \ 01495 ResultTraits3<Functor_##name<EXPR1, EXPR2>, T1, T2, T3>::R2 r2(expr2_(v1, v2, v3)); \ 01496 return (r1 op r2) ? r1 : r2; \ 01497 } \ 01498 \ 01499 private: \ 01500 \ 01501 EXPR1 expr1_; \ 01502 EXPR2 expr2_; \ 01503 \ 01504 Functor_##name & operator=(Functor_##name const &); \ 01505 }; \ 01506 \ 01507 template <class EXPR1, class EXPR2> \ 01508 inline UnaryFunctor<Functor_##name<UnaryFunctor<EXPR1>, UnaryFunctor<EXPR2> > > \ 01509 name(UnaryFunctor<EXPR1> const & e1, UnaryFunctor<EXPR2> const & e2) \ 01510 { \ 01511 Functor_##name<UnaryFunctor<EXPR1>, UnaryFunctor<EXPR2> > p(e1, e2); \ 01512 return UnaryFunctor<Functor_##name<UnaryFunctor<EXPR1>, \ 01513 UnaryFunctor<EXPR2> > >(p); \ 01514 } 01515 01516 MAKE_FUNCTOR_MINMAX(min, <) 01517 MAKE_FUNCTOR_MINMAX(max, >) 01518 01519 #undef MAKE_FUNCTOR_MINMAX 01520 01521 /************************************************************/ 01522 /* */ 01523 /* functors for binary operators */ 01524 /* */ 01525 /************************************************************/ 01526 01527 #define MAKE_FUNCTOR_BINARY_OPERATOR(name, op) \ 01528 template <class EXPR1, class EXPR2> \ 01529 struct Functor_##name; \ 01530 \ 01531 template <class EXPR1, class EXPR2> \ 01532 struct ResultTraits0<Functor_##name<EXPR1, EXPR2> > \ 01533 { \ 01534 typedef typename ResultTraits0<EXPR1>::Res R1; \ 01535 typedef typename ResultTraits0<EXPR2>::Res R2; \ 01536 typedef typename PromoteTraits<R1, R2>::Promote Res; \ 01537 }; \ 01538 \ 01539 template <class EXPR1, class EXPR2, class T1> \ 01540 struct ResultTraits1<Functor_##name<EXPR1, EXPR2>, T1> \ 01541 { \ 01542 typedef typename ResultTraits1<EXPR1, T1>::Res R1; \ 01543 typedef typename ResultTraits1<EXPR2, T1>::Res R2; \ 01544 typedef typename PromoteTraits<R1, R2>::Promote Res; \ 01545 }; \ 01546 \ 01547 template <class EXPR1, class EXPR2, class T1, class T2> \ 01548 struct ResultTraits2<Functor_##name<EXPR1, EXPR2>, T1, T2> \ 01549 { \ 01550 typedef typename ResultTraits2<EXPR1, T1, T2>::Res R1; \ 01551 typedef typename ResultTraits2<EXPR2, T1, T2>::Res R2; \ 01552 typedef typename PromoteTraits<R1, R2>::Promote Res; \ 01553 }; \ 01554 \ 01555 template <class EXPR1, class EXPR2, class T1, class T2, class T3> \ 01556 struct ResultTraits3<Functor_##name<EXPR1, EXPR2>, T1, T2, T3> \ 01557 { \ 01558 typedef typename ResultTraits3<EXPR1, T1, T2, T3>::Res R1; \ 01559 typedef typename ResultTraits3<EXPR2, T1, T2, T3>::Res R2; \ 01560 typedef typename PromoteTraits<R1, R2>::Promote Res; \ 01561 }; \ 01562 \ 01563 template <class EXPR1, class EXPR2> \ 01564 struct Functor_##name \ 01565 { \ 01566 Functor_##name(EXPR1 const & e1, EXPR2 const & e2) \ 01567 : expr1_(e1), expr2_(e2) \ 01568 {} \ 01569 \ 01570 typename ResultTraits0<Functor_##name>::Res \ 01571 operator()() const \ 01572 { \ 01573 return expr1_() op expr2_(); \ 01574 } \ 01575 \ 01576 template <class T> \ 01577 typename ResultTraits1<Functor_##name, T>::Res \ 01578 operator()(T const & v1) const \ 01579 { \ 01580 return expr1_(v1) op expr2_(v1); \ 01581 } \ 01582 \ 01583 template <class T1, class T2> \ 01584 typename ResultTraits2<Functor_##name, T1, T2>::Res \ 01585 operator()(T1 const & v1, T2 const & v2) const \ 01586 { \ 01587 return expr1_(v1, v2) op expr2_(v1, v2); \ 01588 } \ 01589 \ 01590 template <class T1, class T2, class T3> \ 01591 typename ResultTraits3<Functor_##name, T1, T2, T3>::Res \ 01592 operator()(T1 const & v1, T2 const & v2, T3 const & v3) const \ 01593 { \ 01594 return expr1_(v1, v2, v3) op expr2_(v1, v2, v3); \ 01595 } \ 01596 \ 01597 private: \ 01598 \ 01599 EXPR1 expr1_; \ 01600 EXPR2 expr2_; \ 01601 \ 01602 Functor_##name & operator=(Functor_##name const &); \ 01603 }; \ 01604 \ 01605 template <class EXPR1, class EXPR2> \ 01606 inline UnaryFunctor<Functor_##name<UnaryFunctor<EXPR1>, UnaryFunctor<EXPR2> > > \ 01607 operator op(UnaryFunctor<EXPR1> const & e1, UnaryFunctor<EXPR2> const & e2) \ 01608 { \ 01609 Functor_##name<UnaryFunctor<EXPR1>, UnaryFunctor<EXPR2> > p(e1, e2); \ 01610 return UnaryFunctor<Functor_##name<UnaryFunctor<EXPR1>, \ 01611 UnaryFunctor<EXPR2> > >(p); \ 01612 } 01613 01614 /************************************************************/ 01615 01616 MAKE_FUNCTOR_BINARY_OPERATOR(add, +) 01617 MAKE_FUNCTOR_BINARY_OPERATOR(subtract, -) 01618 MAKE_FUNCTOR_BINARY_OPERATOR(multiply, *) 01619 MAKE_FUNCTOR_BINARY_OPERATOR(divide, /) 01620 MAKE_FUNCTOR_BINARY_OPERATOR(modulo, %) 01621 MAKE_FUNCTOR_BINARY_OPERATOR(bitAnd, &) 01622 MAKE_FUNCTOR_BINARY_OPERATOR(bitOr, |) 01623 MAKE_FUNCTOR_BINARY_OPERATOR(bitXor, ^) 01624 01625 #undef MAKE_FUNCTOR_BINARY_OPERATOR 01626 01627 /************************************************************/ 01628 01629 #define MAKE_FUNCTOR_BINARY_OPERATOR_BOOL(name, op) \ 01630 template <class EXPR1, class EXPR2> \ 01631 struct Functor_##name; \ 01632 \ 01633 template <class EXPR1, class EXPR2> \ 01634 struct ResultTraits0<Functor_##name<EXPR1, EXPR2> > \ 01635 { \ 01636 typedef bool Res; \ 01637 }; \ 01638 \ 01639 template <class EXPR1, class EXPR2, class T1> \ 01640 struct ResultTraits1<Functor_##name<EXPR1, EXPR2>, T1> \ 01641 { \ 01642 typedef bool Res; \ 01643 }; \ 01644 \ 01645 template <class EXPR1, class EXPR2, class T1, class T2> \ 01646 struct ResultTraits2<Functor_##name<EXPR1, EXPR2>, T1, T2> \ 01647 { \ 01648 typedef bool Res; \ 01649 }; \ 01650 \ 01651 template <class EXPR1, class EXPR2, class T1, class T2, class T3> \ 01652 struct ResultTraits3<Functor_##name<EXPR1, EXPR2>, T1, T2, T3> \ 01653 { \ 01654 typedef bool Res; \ 01655 }; \ 01656 \ 01657 template <class EXPR1, class EXPR2> \ 01658 struct Functor_##name \ 01659 { \ 01660 Functor_##name(EXPR1 const & e1, EXPR2 const & e2) \ 01661 : expr1_(e1), expr2_(e2) \ 01662 {} \ 01663 \ 01664 bool operator()() const \ 01665 { \ 01666 return expr1_() op expr2_(); \ 01667 } \ 01668 \ 01669 template <class T> \ 01670 bool operator()(T const & v1) const \ 01671 { \ 01672 return expr1_(v1) op expr2_(v1); \ 01673 } \ 01674 \ 01675 template <class T1, class T2> \ 01676 bool operator()(T1 const & v1, T2 const & v2) const \ 01677 { \ 01678 return expr1_(v1, v2) op expr2_(v1, v2); \ 01679 } \ 01680 \ 01681 template <class T1, class T2, class T3> \ 01682 bool operator()(T1 const & v1, T2 const & v2, T3 const & v3) const \ 01683 { \ 01684 return expr1_(v1, v2, v3) op expr2_(v1, v2, v3); \ 01685 } \ 01686 \ 01687 private: \ 01688 \ 01689 EXPR1 expr1_; \ 01690 EXPR2 expr2_; \ 01691 \ 01692 Functor_##name & operator=(Functor_##name const &); \ 01693 }; \ 01694 \ 01695 template <class EXPR1, class EXPR2> \ 01696 inline UnaryFunctor<Functor_##name<UnaryFunctor<EXPR1>, UnaryFunctor<EXPR2> > > \ 01697 operator op(UnaryFunctor<EXPR1> const & e1, UnaryFunctor<EXPR2> const & e2) \ 01698 { \ 01699 Functor_##name<UnaryFunctor<EXPR1>, UnaryFunctor<EXPR2> > p(e1, e2); \ 01700 return UnaryFunctor<Functor_##name<UnaryFunctor<EXPR1>, \ 01701 UnaryFunctor<EXPR2> > >(p); \ 01702 } 01703 01704 /************************************************************/ 01705 01706 MAKE_FUNCTOR_BINARY_OPERATOR_BOOL(equals, ==) 01707 MAKE_FUNCTOR_BINARY_OPERATOR_BOOL(differs, !=) 01708 MAKE_FUNCTOR_BINARY_OPERATOR_BOOL(less, <) 01709 MAKE_FUNCTOR_BINARY_OPERATOR_BOOL(lessEqual, <=) 01710 MAKE_FUNCTOR_BINARY_OPERATOR_BOOL(greater, >) 01711 MAKE_FUNCTOR_BINARY_OPERATOR_BOOL(greaterEqual, >=) 01712 MAKE_FUNCTOR_BINARY_OPERATOR_BOOL(and, &&) 01713 MAKE_FUNCTOR_BINARY_OPERATOR_BOOL(or, ||) 01714 01715 #undef MAKE_FUNCTOR_BINARY_OPERATOR_BOOL 01716 01717 /************************************************************/ 01718 /* */ 01719 /* unary apply */ 01720 /* */ 01721 /************************************************************/ 01722 01723 template <class EXPR, class RES, class ARG> 01724 struct UnaryFctPtrFunctor 01725 { 01726 UnaryFctPtrFunctor(EXPR const & e, RES (*fct)(ARG)) 01727 : expr_(e), f_(fct) 01728 {} 01729 01730 RES operator()() const 01731 { 01732 return f_(expr_()); 01733 } 01734 01735 template <class T> 01736 RES operator()(T const & v1) const 01737 { 01738 return f_(expr_(v1)); 01739 } 01740 01741 template <class T1, class T2> 01742 RES operator()(T1 const & v1, T2 const & v2) const 01743 { 01744 return f_(expr_(v1, v2)); 01745 } 01746 01747 template <class T1, class T2, class T3> 01748 RES operator()(T1 const & v1, T2 const & v2, T3 const & v3) const 01749 { 01750 return f_(expr_(v1, v2, v3)); 01751 } 01752 protected: 01753 01754 EXPR expr_; 01755 RES (*f_)(ARG); 01756 01757 private: 01758 UnaryFctPtrFunctor & operator=(UnaryFctPtrFunctor const &); // not implemented 01759 }; 01760 01761 template <class EXPR, class RES, class ARG> 01762 struct ResultTraits0<UnaryFctPtrFunctor<EXPR, RES, ARG> > 01763 { 01764 typedef RES Res; 01765 }; 01766 01767 template <class EXPR, class RES, class ARG, class T1> 01768 struct ResultTraits1<UnaryFctPtrFunctor<EXPR, RES, ARG>, T1> 01769 { 01770 typedef RES Res; 01771 }; 01772 01773 template <class EXPR, class RES, class ARG, class T1, class T2> 01774 struct ResultTraits2<UnaryFctPtrFunctor<EXPR, RES, ARG>, T1, T2> 01775 { 01776 typedef RES Res; 01777 }; 01778 01779 template <class EXPR, class RES, class ARG, class T1, class T2, class T3> 01780 struct ResultTraits3<UnaryFctPtrFunctor<EXPR, RES, ARG>, T1, T2, T3> 01781 { 01782 typedef RES Res; 01783 }; 01784 01785 template <class EXPR, class RES, class ARG> 01786 inline UnaryFunctor<UnaryFctPtrFunctor<UnaryFunctor<EXPR>, RES, ARG> > 01787 applyFct(RES (*f)(ARG), UnaryFunctor<EXPR> const & e) 01788 { 01789 UnaryFctPtrFunctor<UnaryFunctor<EXPR>, RES, ARG> p(e, f); 01790 return UnaryFunctor<UnaryFctPtrFunctor<UnaryFunctor<EXPR>, RES, ARG> >(p); 01791 } 01792 01793 /************************************************************/ 01794 /* */ 01795 /* binary apply */ 01796 /* */ 01797 /************************************************************/ 01798 01799 template <class EXPR1, class EXPR2, class RES, class ARG1, class ARG2> 01800 struct BinaryFctPtrFunctor 01801 { 01802 BinaryFctPtrFunctor(EXPR1 const & e1, EXPR2 const & e2, 01803 RES (*f)(ARG1, ARG2)) 01804 : expr1_(e1), expr2_(e2), f_(f) 01805 {} 01806 01807 RES operator()() const 01808 { 01809 return f_(expr1_(), expr2_()); 01810 } 01811 01812 template <class T> 01813 RES operator()(T const & v1) const 01814 { 01815 return f_(expr1_(v1), expr2_(v1)); 01816 } 01817 01818 template <class T1, class T2> 01819 RES operator()(T1 const & v1, T2 const & v2) const 01820 { 01821 return f_(expr1_(v1, v2), expr2_(v1, v2)); 01822 } 01823 01824 template <class T1, class T2, class T3> 01825 RES operator()(T1 const & v1, T2 const & v2, T3 const & v3) const 01826 { 01827 return f_(expr1_(v1, v2, v3), expr2_(v1, v2, v3)); 01828 } 01829 01830 protected: 01831 01832 EXPR1 expr1_; 01833 EXPR2 expr2_; 01834 RES (*f_)(ARG1, ARG2); 01835 01836 private: 01837 BinaryFctPtrFunctor & operator=(BinaryFctPtrFunctor const &); // not implemented 01838 }; 01839 01840 template <class EXPR1, class EXPR2, class RES, class ARG1, class ARG2> 01841 struct ResultTraits0<BinaryFctPtrFunctor<EXPR1, EXPR2, RES, ARG1, ARG2> > 01842 { 01843 typedef RES Res; 01844 }; 01845 01846 template <class EXPR1, class EXPR2, class RES, class ARG1, class ARG2, 01847 class T1> 01848 struct ResultTraits1<BinaryFctPtrFunctor<EXPR1, EXPR2, RES, ARG1, ARG2>, T1> 01849 { 01850 typedef RES Res; 01851 }; 01852 01853 template <class EXPR1, class EXPR2, class RES, class ARG1, class ARG2, 01854 class T1, class T2> 01855 struct ResultTraits2<BinaryFctPtrFunctor<EXPR1, EXPR2, RES, ARG1, ARG2>, T1, T2> 01856 { 01857 typedef RES Res; 01858 }; 01859 01860 template <class EXPR1, class EXPR2, class RES, class ARG1, class ARG2, 01861 class T1, class T2, class T3> 01862 struct ResultTraits3<BinaryFctPtrFunctor<EXPR1, EXPR2, RES, ARG1, ARG2>, T1, T2, T3> 01863 { 01864 typedef RES Res; 01865 }; 01866 01867 template <class EXPR1, class EXPR2, class RES, class ARG1, class ARG2> 01868 inline UnaryFunctor<BinaryFctPtrFunctor<UnaryFunctor<EXPR1>, 01869 UnaryFunctor<EXPR2>, 01870 RES, ARG1, ARG2> > 01871 applyFct(RES (*f)(ARG1, ARG2), UnaryFunctor<EXPR1> const & e1, 01872 UnaryFunctor<EXPR2> const & e2) 01873 { 01874 BinaryFctPtrFunctor<UnaryFunctor<EXPR1>, 01875 UnaryFunctor<EXPR2>, 01876 RES, ARG1, ARG2> p(e1, e2, f); 01877 return UnaryFunctor<BinaryFctPtrFunctor<UnaryFunctor<EXPR1>, 01878 UnaryFunctor<EXPR2>, 01879 RES, ARG1, ARG2> >(p); 01880 } 01881 01882 /************************************************************/ 01883 /* */ 01884 /* comma operator */ 01885 /* */ 01886 /************************************************************/ 01887 01888 template <class EXPR1, class EXPR2> 01889 struct CommaFunctor 01890 { 01891 CommaFunctor(EXPR1 const & e1, EXPR2 const & e2) 01892 : expr1_(e1), expr2_(e2) 01893 {} 01894 01895 typename ResultTraits0<EXPR2>::Res 01896 operator()() const 01897 { 01898 expr1_(); 01899 return expr2_(); 01900 } 01901 01902 template <class T> 01903 typename ResultTraits1<EXPR2, T>::Res 01904 operator()(T const & v1) const 01905 { 01906 expr1_(v1); 01907 return expr2_(v1); 01908 } 01909 01910 template <class T1, class T2> 01911 typename ResultTraits2<EXPR2, T1, T2>::Res 01912 operator()(T1 const & v1, T2 const & v2) const 01913 { 01914 expr1_(v1, v2); 01915 return expr2_(v1, v2); 01916 } 01917 01918 template <class T1, class T2, class T3> 01919 typename ResultTraits3<EXPR2, T1, T2, T3>::Res 01920 operator()(T1 const & v1, T2 const & v2, T3 const & v3) const 01921 { 01922 expr1_(v1, v2, v3); 01923 return expr2_(v1, v2, v3); 01924 } 01925 01926 protected: 01927 01928 EXPR1 expr1_; 01929 EXPR2 expr2_; 01930 01931 private: 01932 CommaFunctor & operator=(CommaFunctor const &); // not implemented 01933 }; 01934 01935 template <class Expr1, class Expr2> 01936 struct ResultTraits0<CommaFunctor<Expr1, Expr2> > 01937 { 01938 typedef typename ResultTraits0<Expr2>::Res Res; 01939 }; 01940 01941 template <class Expr1, class Expr2, class T1> 01942 struct ResultTraits1<CommaFunctor<Expr1, Expr2>, T1> 01943 { 01944 typedef typename ResultTraits1<Expr2, T1>::Res Res; 01945 }; 01946 01947 template <class Expr1, class Expr2, class T1, class T2> 01948 struct ResultTraits2<CommaFunctor<Expr1, Expr2>, T1, T2> 01949 { 01950 typedef typename ResultTraits2<Expr2, T1, T2>::Res Res; 01951 }; 01952 01953 template <class Expr1, class Expr2, class T1, class T2, class T3> 01954 struct ResultTraits3<CommaFunctor<Expr1, Expr2>, T1, T2, T3> 01955 { 01956 typedef typename ResultTraits3<Expr2, T1, T2, T3>::Res Res; 01957 }; 01958 01959 template <class EXPR1, class EXPR2> 01960 inline UnaryFunctor<CommaFunctor<UnaryAnalyser<EXPR1>, 01961 UnaryFunctor<EXPR2> > > 01962 operator,(UnaryAnalyser<EXPR1> const & e1, 01963 UnaryFunctor<EXPR2> const & e2) 01964 { 01965 CommaFunctor<UnaryAnalyser<EXPR1>, 01966 UnaryFunctor<EXPR2> > p(e1, e2); 01967 return UnaryFunctor<CommaFunctor<UnaryAnalyser<EXPR1>, 01968 UnaryFunctor<EXPR2> > >(p); 01969 } 01970 01971 /************************************************************/ 01972 01973 template <class EXPR1, class EXPR2> 01974 struct CommaAnalyser 01975 { 01976 CommaAnalyser(EXPR1 const & e1, EXPR2 const & e2) 01977 : expr1_(e1), expr2_(e2) 01978 {} 01979 01980 void operator()() const 01981 { 01982 expr1_(); 01983 expr2_(); 01984 } 01985 01986 template <class T> 01987 void operator()(T const & v1) const 01988 { 01989 expr1_(v1); 01990 expr2_(v1); 01991 } 01992 01993 template <class T1, class T2> 01994 void operator()(T1 const & v1, T2 const & v2) const 01995 { 01996 expr1_(v1, v2); 01997 expr2_(v1, v2); 01998 } 01999 02000 template <class T1, class T2, class T3> 02001 void operator()(T1 const & v1, T2 const & v2, T3 const & v3) const 02002 { 02003 expr1_(v1, v2, v3); 02004 expr2_(v1, v2, v3); 02005 } 02006 02007 protected: 02008 02009 EXPR1 expr1_; 02010 EXPR2 expr2_; 02011 02012 private: 02013 CommaAnalyser & operator=(CommaAnalyser const &); // not implemented 02014 }; 02015 02016 template <class EXPR1, class EXPR2> 02017 inline UnaryAnalyser<CommaAnalyser<UnaryAnalyser<EXPR1>, 02018 UnaryAnalyser<EXPR2> > > 02019 operator,(UnaryAnalyser<EXPR1> const & e1, 02020 UnaryAnalyser<EXPR2> const & e2) 02021 { 02022 CommaAnalyser<UnaryAnalyser<EXPR1>, 02023 UnaryAnalyser<EXPR2> > p(e1, e2); 02024 return UnaryAnalyser<CommaAnalyser<UnaryAnalyser<EXPR1>, 02025 UnaryAnalyser<EXPR2> > >(p); 02026 } 02027 02028 } // namespace functor 02029 02030 #if defined(__GNUC__) && __GNUC__ < 3 02031 using functor::Arg1; 02032 using functor::Arg2; 02033 using functor::Arg3; 02034 using functor::Param; 02035 #endif 02036 02037 template <class T> 02038 class FunctorTraits<functor::UnaryFunctor<T> > 02039 : public FunctorTraitsBase<functor::UnaryFunctor<T> > 02040 { 02041 public: 02042 typedef VigraTrueType isInitializer; 02043 typedef VigraTrueType isUnaryFunctor; 02044 typedef VigraTrueType isBinaryFunctor; 02045 typedef VigraTrueType isTernaryFunctor; 02046 }; 02047 02048 template <class T> 02049 class FunctorTraits<functor::UnaryAnalyser<T> > 02050 : public FunctorTraitsBase<functor::UnaryAnalyser<T> > 02051 { 02052 public: 02053 typedef VigraTrueType isUnaryAnalyser; 02054 typedef VigraTrueType isBinaryAnalyser; 02055 typedef VigraTrueType isTernaryAnalyser; 02056 }; 02057 02058 02059 02060 } // namespace vigra 02061 02062 #endif /* NO_PARTIAL_TEMPLATE_SPECIALIZATION */ 02063 02064 #endif // DOXYGEN 02065 02066 #endif /* VIGRA_FUNCTOREXPRESSION_HXX */ 02067 02068
© Ullrich Köthe (ullrich.koethe@iwr.uni-heidelberg.de) |
html generated using doxygen and Python
|