CMS 3D CMS Logo

CMSSW_4_4_3_patch1/src/PhysicsTools/Utilities/interface/Fraction.h

Go to the documentation of this file.
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