File indexing completed on 2024-04-06 12:24:18
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 }
0137
0138 #endif