Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-02-14 13:33:27

0001 #ifndef PhysicsTools_Utilities_Fraction_h
0002 #define PhysicsTools_Utilities_Fraction_h
0003 
0004 #include "PhysicsTools/Utilities/interface/Numerical.h"
0005 #include "PhysicsTools/Utilities/interface/Operations.h"
0006 #include <numeric>
0007 
0008 namespace funct {
0009 
0010   template <int n, int m>
0011   struct FractionStruct {
0012     static_assert(m != 0);
0013     static const int numerator = n, denominator = m;
0014     double operator()() const { return double(n) / double(m); }
0015     operator double() const { return double(n) / double(m); }
0016     double operator()(double) const { return double(n) / double(m); }
0017     double operator()(double, double) const { return double(n) / double(m); }
0018   };
0019 
0020   template <int n, int m, unsigned gcd = std::gcd(n, m), int num = n / gcd, int den = m / gcd>
0021   struct PositiveFraction {
0022     typedef FractionStruct<num, den> type;
0023   };
0024 
0025   template <int n, int m, unsigned gcd, int num>
0026   struct PositiveFraction<n, m, gcd, num, 1> {
0027     typedef Numerical<num> type;
0028   };
0029 
0030   template <int n, int m, bool pn = (n >= 0), bool pm = (m >= 0)>
0031   struct Fraction {
0032     typedef typename PositiveFraction<n, m>::type type;
0033   };
0034 
0035   template <int n, int m>
0036   const typename Fraction<n, m>::type& fract() {
0037     static typename Fraction<n, m>::type c;
0038     return c;
0039   }
0040 
0041   template <int n, int m>
0042   struct Ratio<Numerical<n>, Numerical<m> > {
0043     typedef typename Fraction<n, m>::type type;
0044     inline static type combine(const Numerical<n>&, const Numerical<m>&) { return fract<n, m>(); }
0045   };
0046 
0047   template <int n, int m>
0048   struct Fraction<n, m, false, true> {
0049     typedef typename Minus<typename PositiveFraction<-n, m>::type>::type type;
0050   };
0051 
0052   template <int n, int m>
0053   struct Fraction<n, m, true, false> {
0054     typedef typename Minus<typename PositiveFraction<n, -m>::type>::type type;
0055   };
0056 
0057   template <int n, int m>
0058   struct Fraction<n, m, false, false> {
0059     typedef typename Minus<typename PositiveFraction<-n, -m>::type>::type type;
0060   };
0061 
0062   template <int a, int b, int c>
0063   struct Product<Numerical<a>, FractionStruct<b, c> > {
0064     typedef typename Fraction<a * b, c>::type type;
0065     inline static type combine(const Numerical<a>&, const FractionStruct<b, c>&) { return fract<a * b, c>(); }
0066   };
0067 
0068   template <int a, int b, int c>
0069   struct Product<FractionStruct<b, c>, Numerical<a> > {
0070     typedef typename Fraction<a * b, c>::type type;
0071     inline static type combine(const FractionStruct<b, c>&, const Numerical<a>&) { return fract<a * b, c>(); }
0072   };
0073 
0074   template <int a, int b, int c>
0075   struct Ratio<Numerical<a>, FractionStruct<b, c> > {
0076     typedef typename Fraction<a * c, b>::type type;
0077     inline static type combine(const Numerical<a>&, const FractionStruct<b, c>&) { return fract<a * c, b>(); }
0078   };
0079 
0080   template <int a, int b, int c>
0081   struct Sum<Numerical<a>, FractionStruct<b, c> > {
0082     typedef typename Fraction<a * c + b, b>::type type;
0083     inline static type combine(const Numerical<a>&, const FractionStruct<b, c>&) { return fract<a * c + b, b>(); }
0084   };
0085 
0086   template <int a, int b, int c>
0087   struct Difference<Numerical<a>, FractionStruct<b, c> > {
0088     typedef typename Fraction<a * c - b, b>::type type;
0089     inline static type combine(const Numerical<a>&, const FractionStruct<b, c>&) { return fract<a * c - b, b>(); }
0090   };
0091 
0092   template <int a, int b, int c>
0093   struct Sum<FractionStruct<b, c>, Numerical<a> > {
0094     typedef typename Fraction<a * c + b, b>::type type;
0095     inline static type combine(const FractionStruct<b, c>&, const Numerical<a>&) { return fract<a * c + b, b>(); }
0096   };
0097 
0098   template <int a, int b, int c>
0099   struct Ratio<FractionStruct<b, c>, Numerical<a> > {
0100     typedef typename Fraction<b, a * c>::type type;
0101     inline static type combine(const FractionStruct<b, c>&, const Numerical<a>&) { return fract<b, a * c>(); }
0102   };
0103 
0104   template <int a, int b, int c, int d>
0105   struct Sum<FractionStruct<a, b>, FractionStruct<c, d> > {
0106     typedef typename Fraction<a * d + c * b, b * d>::type type;
0107     inline static type combine(const FractionStruct<a, b>&, const FractionStruct<c, d>&) {
0108       return fract<a * d + c * b, b * d>();
0109     }
0110   };
0111 
0112   template <int a, int b, int c, int d>
0113   struct Difference<FractionStruct<a, b>, FractionStruct<c, d> > {
0114     typedef typename Fraction<a * d - c * b, b * d>::type type;
0115     inline static type combine(const FractionStruct<a, b>&, const FractionStruct<c, d>&) {
0116       return fract<a * d - c * b, b * d>();
0117     }
0118   };
0119 
0120   template <int a, int b, int c, int d>
0121   struct Product<FractionStruct<a, b>, FractionStruct<c, d> > {
0122     typedef typename Fraction<a * c, b * d>::type type;
0123     inline static type combine(const FractionStruct<a, b>&, const FractionStruct<c, d>&) {
0124       return fract<a * c, b * d>();
0125     }
0126   };
0127 
0128   template <int a, int b, int c, int d>
0129   struct Ratio<FractionStruct<a, b>, FractionStruct<c, d> > {
0130     typedef typename Fraction<a * d, b * c>::type type;
0131     inline static type combine(const FractionStruct<a, b>&, const FractionStruct<c, d>&) {
0132       return fract<a * d, b * c>();
0133     }
0134   };
0135 
0136 }  // namespace funct
0137 
0138 #endif