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