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