Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2023-10-25 09:53:58

0001 #ifndef NPSTAT_SIMPLEFUNCTORS_HH_
0002 #define NPSTAT_SIMPLEFUNCTORS_HH_
0003 
0004 /*!
0005 // \file SimpleFunctors.h
0006 //
0007 // \brief Interface definitions and concrete simple functors for
0008 //        a variety of functor-based calculations
0009 //
0010 // Author: I. Volobouev
0011 //
0012 // March 2009
0013 */
0014 
0015 namespace npstat {
0016   /** Base class for a functor that takes no arguments */
0017   template <typename Result>
0018   struct Functor0 {
0019     typedef Result result_type;
0020 
0021     inline virtual ~Functor0() {}
0022     virtual Result operator()() const = 0;
0023   };
0024 
0025   /** Base class for a functor that takes a single argument */
0026   template <typename Result, typename Arg1>
0027   struct Functor1 {
0028     typedef Result result_type;
0029     typedef Arg1 first_argument_type;
0030 
0031     inline virtual ~Functor1() {}
0032     virtual Result operator()(const Arg1&) const = 0;
0033   };
0034 
0035   /** Base class for a functor that takes two arguments */
0036   template <typename Result, typename Arg1, typename Arg2>
0037   struct Functor2 {
0038     typedef Result result_type;
0039     typedef Arg1 first_argument_type;
0040     typedef Arg2 second_argument_type;
0041 
0042     inline virtual ~Functor2() {}
0043     virtual Result operator()(const Arg1&, const Arg2&) const = 0;
0044   };
0045 
0046   /** Base class for a functor that takes three arguments */
0047   template <typename Result, typename Arg1, typename Arg2, typename Arg3>
0048   struct Functor3 {
0049     typedef Result result_type;
0050     typedef Arg1 first_argument_type;
0051     typedef Arg2 second_argument_type;
0052     typedef Arg3 third_argument_type;
0053 
0054     inline virtual ~Functor3() {}
0055     virtual Result operator()(const Arg1&, const Arg2&, const Arg3&) const = 0;
0056   };
0057 
0058   /** A simple functor which returns a copy of its argument */
0059   template <typename Result>
0060   struct Same : public Functor1<Result, Result> {
0061     inline Result operator()(const Result& a) const override { return a; }
0062   };
0063 
0064   /** A simple functor which returns a reference to its argument */
0065   template <typename Result>
0066   struct SameRef : public Functor1<const Result&, Result> {
0067     inline const Result& operator()(const Result& a) const { return a; }
0068   };
0069 
0070   /**
0071     // Simple functor which ignores is arguments and instead
0072     // builds the result using the default constructor of the result type
0073     */
0074   template <typename Result>
0075   struct DefaultConstructor0 : public Functor0<Result> {
0076     inline Result operator()() const { return Result(); }
0077   };
0078 
0079   /**
0080     // Simple functor which ignores is arguments and instead
0081     // builds the result using the default constructor of the result type
0082     */
0083   template <typename Result, typename Arg1>
0084   struct DefaultConstructor1 : public Functor1<Result, Arg1> {
0085     inline Result operator()(const Arg1&) const { return Result(); }
0086   };
0087 
0088   /**
0089     // Simple functor which ignores is arguments and instead
0090     // builds the result using the default constructor of the result type
0091     */
0092   template <typename Result, typename Arg1, typename Arg2>
0093   struct DefaultConstructor2 : public Functor2<Result, Arg1, Arg2> {
0094     inline Result operator()(const Arg1&, const Arg2&) const { return Result(); }
0095   };
0096 
0097   /**
0098     // Simple functor which ignores is arguments and instead
0099     // builds the result using the default constructor of the result type
0100     */
0101   template <typename Result, typename Arg1, typename Arg2, typename Arg3>
0102   struct DefaultConstructor3 : public Functor3<Result, Arg1, Arg2, Arg3> {
0103     inline Result operator()(const Arg1&, const Arg2&, const Arg3&) const { return Result(); }
0104   };
0105 
0106   /**
0107     // Sometimes it becomes necessary to perform an explicit cast for proper
0108     // overload resolution of a converting copy constructor
0109     */
0110   template <typename Result, typename Arg1, typename CastType>
0111   struct CastingCopyConstructor : public Functor1<Result, Arg1> {
0112     inline Result operator()(const Arg1& a) const { return Result(static_cast<CastType>(a)); }
0113   };
0114 
0115   /**
0116     // Adaptation for using functors without arguments with simple
0117     // cmath-style functions. Do not use this struct as a base class.
0118     */
0119   template <typename Result>
0120   struct FcnFunctor0 : public Functor0<Result> {
0121     inline explicit FcnFunctor0(Result (*fcn)()) : fcn_(fcn) {}
0122 
0123     inline Result operator()() const { return fcn_(); }
0124 
0125     FcnFunctor0() = delete;
0126 
0127   private:
0128     Result (*fcn_)();
0129   };
0130 
0131   /**
0132     // Adaptation for using single-argument functors with simple
0133     // cmath-style functions. Do not use this struct as a base class.
0134     */
0135   template <typename Result, typename Arg1>
0136   struct FcnFunctor1 : public Functor1<Result, Arg1> {
0137     inline explicit FcnFunctor1(Result (*fcn)(Arg1)) : fcn_(fcn) {}
0138 
0139     inline Result operator()(const Arg1& a) const { return fcn_(a); }
0140 
0141     FcnFunctor1() = delete;
0142 
0143   private:
0144     Result (*fcn_)(Arg1);
0145   };
0146 
0147   /**
0148     // Adaptation for using two-argument functors with simple
0149     // cmath-style functions. Do not use this struct as a base class.
0150     */
0151   template <typename Result, typename Arg1, typename Arg2>
0152   struct FcnFunctor2 : public Functor2<Result, Arg1, Arg2> {
0153     inline explicit FcnFunctor2(Result (*fcn)(Arg1, Arg2)) : fcn_(fcn) {}
0154 
0155     inline Result operator()(const Arg1& x, const Arg2& y) const { return fcn_(x, y); }
0156 
0157     FcnFunctor2() = delete;
0158 
0159   private:
0160     Result (*fcn_)(Arg1, Arg2);
0161   };
0162 
0163   /**
0164     // Adaptation for using three-argument functors with simple
0165     // cmath-style functions. Do not use this struct as a base class.
0166     */
0167   template <typename Result, typename Arg1, typename Arg2, typename Arg3>
0168   struct FcnFunctor3 : public Functor3<Result, Arg1, Arg2, Arg3> {
0169     inline explicit FcnFunctor3(Result (*fcn)(Arg1, Arg2, Arg3)) : fcn_(fcn) {}
0170 
0171     inline Result operator()(const Arg1& x, const Arg2& y, const Arg3& z) const { return fcn_(x, y, z); }
0172 
0173     FcnFunctor3() = delete;
0174 
0175   private:
0176     Result (*fcn_)(Arg1, Arg2, Arg3);
0177   };
0178 
0179   /**
0180     // Functor which extracts a given element from a random access linear
0181     // container without bounds checking
0182     */
0183   template <class Container, class Result = typename Container::value_type>
0184   struct Element1D : public Functor1<Result, Container> {
0185     inline explicit Element1D(const unsigned long index) : idx(index) {}
0186 
0187     inline Result operator()(const Container& c) const { return c[idx]; }
0188 
0189     Element1D() = delete;
0190 
0191   private:
0192     unsigned long idx;
0193   };
0194 
0195   /**
0196     // Functor which extracts a given element from a random access linear
0197     // container with bounds checking
0198     */
0199   template <class Container, class Result = typename Container::value_type>
0200   struct Element1DAt : public Functor1<Result, Container> {
0201     inline explicit Element1DAt(const unsigned long index) : idx(index) {}
0202 
0203     inline Result operator()(const Container& c) const { return c.at(idx); }
0204 
0205     Element1DAt() = delete;
0206 
0207   private:
0208     unsigned long idx;
0209   };
0210 
0211   /** 
0212     // Left assignment functor. Works just like normal binary
0213     // assignment operator in places where functor is needed.
0214     */
0215   template <typename T1, typename T2>
0216   struct assign_left {
0217     inline T1& operator()(T1& left, const T2& right) const { return left = right; }
0218   };
0219 
0220   /** 
0221     // Right assignment functor. Reverses the assignment direction
0222     // in comparison with the normal binary assignment operator.
0223     */
0224   template <typename T1, typename T2>
0225   struct assign_right {
0226     inline T2& operator()(const T1& left, T2& right) const { return right = left; }
0227   };
0228 
0229   /** In-place addition on the left side */
0230   template <typename T1, typename T2>
0231   struct pluseq_left {
0232     inline T1& operator()(T1& left, const T2& right) const { return left += right; }
0233   };
0234 
0235   /** In-place addition on the right side */
0236   template <typename T1, typename T2>
0237   struct pluseq_right {
0238     inline T2& operator()(const T1& left, T2& right) const { return right += left; }
0239   };
0240 
0241   /** 
0242     // In-place addition on the left side preceded by
0243     // multiplication of the right argument by a double
0244     */
0245   template <typename T1, typename T2>
0246   struct addmul_left {
0247     inline explicit addmul_left(const double weight) : w_(weight) {}
0248 
0249     inline T1& operator()(T1& left, const T2& right) const { return left += w_ * right; }
0250 
0251     addmul_left() = delete;
0252 
0253   private:
0254     double w_;
0255   };
0256 
0257   /** 
0258     // In-place addition on the right side preceded by
0259     // multiplication of the left argument by a double
0260     */
0261   template <typename T1, typename T2>
0262   struct addmul_right {
0263     inline explicit addmul_right(const double weight) : w_(weight) {}
0264 
0265     inline T1& operator()(T1& left, const T2& right) const { return right += w_ * left; }
0266 
0267     addmul_right() = delete;
0268 
0269   private:
0270     double w_;
0271   };
0272 
0273   /** In-place subtraction on the left side */
0274   template <typename T1, typename T2>
0275   struct minuseq_left {
0276     inline T1& operator()(T1& left, const T2& right) const { return left -= right; }
0277   };
0278 
0279   /** In-place subtraction on the right side */
0280   template <typename T1, typename T2>
0281   struct minuseq_right {
0282     inline T2& operator()(const T1& left, T2& right) const { return right -= left; }
0283   };
0284 
0285   /** In-place multiplication on the left side */
0286   template <typename T1, typename T2>
0287   struct multeq_left {
0288     inline T1& operator()(T1& left, const T2& right) const { return left *= right; }
0289   };
0290 
0291   /** In-place multiplication on the right side */
0292   template <typename T1, typename T2>
0293   struct multeq_right {
0294     inline T2& operator()(const T1& left, T2& right) const { return right *= left; }
0295   };
0296 
0297   /** In-place division on the left side withot checking for division by 0 */
0298   template <typename T1, typename T2>
0299   struct diveq_left {
0300     inline T1& operator()(T1& left, const T2& right) const { return left /= right; }
0301   };
0302 
0303   /** In-place division on the right side withot checking for division by 0 */
0304   template <typename T1, typename T2>
0305   struct diveq_right {
0306     inline T2& operator()(const T1& left, T2& right) const { return right /= left; }
0307   };
0308 
0309   /** In-place division on the left side. Allow 0/0 = const. */
0310   template <typename T1, typename T2>
0311   struct diveq_left_0by0isC {
0312     inline diveq_left_0by0isC() : C(T1()), leftZero(T1()), rightZero(T2()) {}
0313     inline explicit diveq_left_0by0isC(const T1& value) : C(value), leftZero(T1()), rightZero(T2()) {}
0314 
0315     inline T1& operator()(T1& left, const T2& right) const {
0316       if (right == rightZero)
0317         if (left == leftZero) {
0318           left = C;
0319           return left;
0320         }
0321       return left /= right;
0322     }
0323 
0324   private:
0325     T1 C;
0326     T1 leftZero;
0327     T2 rightZero;
0328   };
0329 
0330   /** In-place division on the right side. Allow 0/0 = const. */
0331   template <typename T1, typename T2>
0332   struct diveq_right_0by0isC {
0333     inline diveq_right_0by0isC() : C(T2()), leftZero(T1()), rightZero(T2()) {}
0334     inline explicit diveq_right_0by0isC(const T2& value) : C(value), leftZero(T1()), rightZero(T2()) {}
0335 
0336     inline T2& operator()(const T1& left, T2& right) const {
0337       if (left == leftZero)
0338         if (right == rightZero) {
0339           right = C;
0340           return right;
0341         }
0342       return right /= left;
0343     }
0344 
0345   private:
0346     T2 C;
0347     T1 leftZero;
0348     T2 rightZero;
0349   };
0350 
0351   /** Left assignment functor preceded by a static cast */
0352   template <typename T1, typename T2, typename T3 = T1>
0353   struct scast_assign_left {
0354     inline T1& operator()(T1& left, const T2& right) const { return left = static_cast<T3>(right); }
0355   };
0356 
0357   /** Right assignment functor preceded by a static cast */
0358   template <typename T1, typename T2, typename T3 = T2>
0359   struct scast_assign_right {
0360     inline T2& operator()(const T1& left, T2& right) const { return right = static_cast<T3>(left); }
0361   };
0362 
0363   /** In-place addition on the left side preceded by a static cast */
0364   template <typename T1, typename T2, typename T3 = T1>
0365   struct scast_pluseq_left {
0366     inline T1& operator()(T1& left, const T2& right) const { return left += static_cast<T3>(right); }
0367   };
0368 
0369   /** In-place addition on the right side preceded by a static cast */
0370   template <typename T1, typename T2, typename T3 = T2>
0371   struct scast_pluseq_right {
0372     inline T2& operator()(const T1& left, T2& right) const { return right += static_cast<T3>(left); }
0373   };
0374 
0375   /** In-place subtraction on the left side preceded by a static cast */
0376   template <typename T1, typename T2, typename T3 = T1>
0377   struct scast_minuseq_left {
0378     inline T1& operator()(T1& left, const T2& right) const { return left -= static_cast<T3>(right); }
0379   };
0380 
0381   /** In-place subtraction on the right side preceded by a static cast */
0382   template <typename T1, typename T2, typename T3 = T2>
0383   struct scast_minuseq_right {
0384     inline T2& operator()(const T1& left, T2& right) const { return right -= static_cast<T3>(left); }
0385   };
0386 }  // namespace npstat
0387 
0388 #endif  // NPSTAT_SIMPLEFUNCTORS_HH_