00001 #ifndef PhysicsTools_Utilities_Fraction_h 00002 #define PhysicsTools_Utilities_Fraction_h 00003 00004 #include "PhysicsTools/Utilities/interface/Numerical.h" 00005 #include "PhysicsTools/Utilities/interface/Operations.h" 00006 #include <boost/math/common_factor.hpp> 00007 #include <boost/static_assert.hpp> 00008 00009 namespace funct { 00010 00011 template<int n, int m> 00012 struct FractionStruct { 00013 BOOST_STATIC_ASSERT(m != 0); 00014 static const int numerator = n, denominator = m; 00015 double operator()() const { return double(n) / double (m); } 00016 operator double() const { return double(n) / double (m); } 00017 double operator()(double) const { return double(n) / double (m); } 00018 double operator()(double, double) const { return double(n) / double (m); } 00019 }; 00020 00021 template<int n, int m, unsigned gcd = boost::math::static_gcd<n, m>::value, 00022 int num = n / gcd, int den = m / gcd> 00023 struct PositiveFraction { 00024 typedef FractionStruct<num, den> type; 00025 }; 00026 00027 template<int n, int m, unsigned gcd, int num> 00028 struct PositiveFraction<n, m , gcd, num, 1> { 00029 typedef Numerical<num> type; 00030 }; 00031 00032 template<int n, int m, bool pn = (n >= 0), bool pm = (m >= 0)> 00033 struct Fraction { 00034 typedef typename PositiveFraction<n, m>::type type; 00035 }; 00036 00037 template<int n, int m> 00038 const typename Fraction<n, m>::type& fract() { 00039 static typename Fraction<n, m>::type c; 00040 return c; 00041 } 00042 00043 template<int n, int m> 00044 struct Ratio<Numerical<n>, Numerical<m> > { 00045 typedef typename Fraction<n, m>::type type; 00046 inline static type combine(const Numerical<n>&, const Numerical<m>&) { 00047 return fract<n, m>(); 00048 } 00049 }; 00050 00051 template<int n, int m> 00052 struct Fraction<n, m, false, true> { 00053 typedef typename Minus<typename PositiveFraction<-n, m>::type>::type type; 00054 }; 00055 00056 template<int n, int m> 00057 struct Fraction<n, m, true, false> { 00058 typedef typename Minus<typename PositiveFraction<n, -m>::type>::type type; 00059 }; 00060 00061 template<int n, int m> 00062 struct Fraction<n, m, false, false> { 00063 typedef typename Minus<typename PositiveFraction<-n, -m>::type>::type type; 00064 }; 00065 00066 template<int a, int b, int c> 00067 struct Product<Numerical<a>, FractionStruct<b, c> > { 00068 typedef typename Fraction<a * b, c>::type type; 00069 inline static type combine(const Numerical<a>&, const FractionStruct<b, c>&) { 00070 return fract<a * b, c>(); 00071 } 00072 }; 00073 00074 template<int a, int b, int c> 00075 struct Product<FractionStruct<b, c>, Numerical<a> > { 00076 typedef typename Fraction<a * b, c>::type type; 00077 inline static type combine(const FractionStruct<b, c>&, const Numerical<a>&) { 00078 return fract<a * b, c>(); 00079 } 00080 }; 00081 00082 template<int a, int b, int c> 00083 struct Ratio<Numerical<a>, FractionStruct<b, c> > { 00084 typedef typename Fraction<a * c, b>::type type; 00085 inline static type combine(const Numerical<a>&, const FractionStruct<b, c>&) { 00086 return fract<a * c, b>(); 00087 } 00088 }; 00089 00090 template<int a, int b, int c> 00091 struct Sum<Numerical<a>, FractionStruct<b, c> > { 00092 typedef typename Fraction<a * c + b, b>::type type; 00093 inline static type combine(const Numerical<a>&, const FractionStruct<b, c>&) { 00094 return fract<a * c + b, b>(); 00095 } 00096 }; 00097 00098 template<int a, int b, int c> 00099 struct Difference<Numerical<a>, FractionStruct<b, c> > { 00100 typedef typename Fraction<a * c - b, b>::type type; 00101 inline static type combine(const Numerical<a>&, const FractionStruct<b, c>&) { 00102 return fract<a * c - b, b>(); 00103 } 00104 }; 00105 00106 template<int a, int b, int c> 00107 struct Sum<FractionStruct<b, c>, Numerical<a> > { 00108 typedef typename Fraction<a * c + b, b>::type type; 00109 inline static type combine(const FractionStruct<b, c>&, const Numerical<a>&) { 00110 return fract<a * c + b, b>(); 00111 } 00112 }; 00113 00114 template<int a, int b, int c> 00115 struct Ratio<FractionStruct<b, c>, Numerical<a> > { 00116 typedef typename Fraction<b, a * c>::type type; 00117 inline static type combine(const FractionStruct<b, c>&, const Numerical<a>&) { 00118 return fract<b, a * c>(); 00119 } 00120 }; 00121 00122 template<int a, int b, int c, int d> 00123 struct Sum<FractionStruct<a, b>, FractionStruct<c, d> > { 00124 typedef typename Fraction<a * d + c * b, b * d>::type type; 00125 inline static type combine(const FractionStruct<a, b>&, const FractionStruct<c, d>&) { 00126 return fract<a * d + c * b, b * d>(); 00127 } 00128 }; 00129 00130 template<int a, int b, int c, int d> 00131 struct Difference<FractionStruct<a, b>, FractionStruct<c, d> > { 00132 typedef typename Fraction<a * d - c * b, b * d>::type type; 00133 inline static type combine(const FractionStruct<a, b>&, const FractionStruct<c, d>&) { 00134 return fract<a * d - c * b, b * d>(); 00135 } 00136 }; 00137 00138 template<int a, int b, int c, int d> 00139 struct Product<FractionStruct<a, b>, FractionStruct<c, d> > { 00140 typedef typename Fraction<a * c, b * d>::type type; 00141 inline static type combine(const FractionStruct<a, b>&, const FractionStruct<c, d>&) { 00142 return fract<a * c, b * d>(); 00143 } 00144 }; 00145 00146 template<int a, int b, int c, int d> 00147 struct Ratio<FractionStruct<a, b>, FractionStruct<c, d> > { 00148 typedef typename Fraction<a * d, b * c>::type type; 00149 inline static type combine(const FractionStruct<a, b>&, const FractionStruct<c, d>& ) { 00150 return fract<a * d, b * c>(); 00151 } 00152 }; 00153 00154 } 00155 00156 #endif