00001
00012
00013 #ifndef LHCBMATH_LHCBMATH_H
00014 #define LHCBMATH_LHCBMATH_H 1
00015
00016
00017
00018
00019
00020 #include <cmath>
00021 #include <algorithm>
00022 #include <functional>
00023
00024
00025
00026 #include "boost/call_traits.hpp"
00027 #include "boost/integer_traits.hpp"
00028 #include "boost/static_assert.hpp"
00029
00030 namespace LHCb
00031 {
00032
00036 namespace Math
00037 {
00039 static const double hiTolerance = 1e-40;
00040 static const double lowTolerance = 1e-20;
00041 static const double looseTolerance = 1e-5;
00042 static const double sqrt_12 = 3.4641016151377546;
00043 static const double inv_sqrt_12 = 0.2886751345948129;
00044
00050 template <class TYPE>
00051 struct abs_less : std::binary_function<TYPE,TYPE,TYPE>
00052 {
00053 inline TYPE operator()
00054 ( typename boost::call_traits<const TYPE>::param_type v1 ,
00055 typename boost::call_traits<const TYPE>::param_type v2 ) const
00056 {
00057 return m_eval ( std::fabs( v1 ) , std::fabs( v2 ) ) ;
00058 }
00060 std::less<TYPE> m_eval ;
00061 } ;
00062
00068 template <class TYPE>
00069 struct abs_greater : std::binary_function<TYPE,TYPE,TYPE>
00070 {
00071 inline TYPE operator()
00072 ( typename boost::call_traits<const TYPE>::param_type v1 ,
00073 typename boost::call_traits<const TYPE>::param_type v2 ) const
00074 {
00075 return m_eval ( std::fabs( v1 ) , std::fabs( v2 ) ) ;
00076 }
00078 std::greater<TYPE> m_eval ;
00079 } ;
00080
00085 template <class TYPE>
00086 inline TYPE absMin ( TYPE v1 , TYPE v2 )
00087 { return std::min ( std::fabs ( v1 ) , std::fabs ( v2 ) ) ; }
00088
00093 template <class TYPE>
00094 inline TYPE absMax ( TYPE v1 , TYPE v2 )
00095 { return std::max ( std::fabs ( v1 ) , std::fabs ( v2 ) ) ; }
00096
00097
00108 bool equal_to_double
00109 ( const double value1 ,
00110 const double value2 ,
00111 const double epsilon = 1.0e-6 ) ;
00112
00118 template <class TYPE>
00119 struct Equal_To : public std::binary_function<TYPE,TYPE,bool>
00120 {
00121 typedef typename boost::call_traits<const TYPE>::param_type T ;
00123 Equal_To ( T ) {}
00125 inline bool operator() ( T v1 , T v2 ) const
00126 {
00127 std::equal_to<TYPE> cmp ;
00128 return cmp ( v1 , v2 ) ;
00129 }
00130 } ;
00131
00133 template <class TYPE>
00134 struct Equal_To<const TYPE>: public Equal_To<TYPE>{} ;
00135
00137 template <class TYPE>
00138 struct Equal_To<TYPE&>: public Equal_To<TYPE>{} ;
00139
00141 template <>
00142 struct Equal_To<double>
00143 {
00145 Equal_To ( const double eps = 1.0e-6 ) : m_eps ( eps ) {}
00147 inline bool operator() ( const double v1 , const double v2 ) const
00148 {
00149 return equal_to_double ( v1 , v2 , m_eps ) ;
00150 }
00151 private :
00153 double m_eps ;
00154 };
00155
00157 template <>
00158 struct Equal_To<long double>
00159 {
00161 Equal_To ( const long double eps = 1.0e-6 ) : m_eps ( eps ) {}
00163 inline bool operator() ( const long double v1 ,
00164 const long double v2 ) const
00165 {
00166 return equal_to_double
00167 ( static_cast<double> ( v1 ) ,
00168 static_cast<double> ( v2 ) ,
00169 static_cast<double> ( m_eps ) ) ;
00170 }
00171 private :
00173 long double m_eps ;
00174 };
00175
00177 template <>
00178 struct Equal_To<float>
00179 {
00181 Equal_To ( const float eps = 1.0e-6 ) : m_eps ( eps ) {}
00183 inline bool operator() ( const float v1 , const float v2 ) const
00184 {
00185 return equal_to_double ( v1 , v2 , m_eps ) ;
00186 }
00187 private :
00189 float m_eps ;
00190 } ;
00191
00195 inline int round ( const double x ) {
00196 int i;
00197 LHCb::Math::Equal_To<double> equal_to(lowTolerance);
00198 if (x >= 0.0) {
00199 i = int(x + 0.5);
00200 if (equal_to(x + 0.5, double(i)) && i & 1) --i;
00201 }
00202 else {
00203 i = int(x - 0.5);
00204 if (equal_to(x - 0.5 , double(i)) && i & 1) ++i;
00205
00206 }
00207 return i;
00208 }
00209
00213 inline int round ( const float x )
00214 {
00215 return LHCb::Math::round ( double ( x ) ) ;
00216 }
00217
00226 inline bool equal_to_int
00227 ( const double val ,
00228 const int ref ,
00229 const double eps1 = 1.e-6 ,
00230 const double eps2 = 0.5e-3 / boost::integer_traits<int>::const_max )
00231 {
00232 BOOST_STATIC_ASSERT(boost::integer_traits<int>::is_specialized ) ;
00233
00234 if ( val == ref ) { return true ; }
00235
00236 if ( val > boost::integer_traits<int>::const_max ||
00237 val < boost::integer_traits<int>::const_min ) { return false ; }
00238
00239 if ( std::fabs ( val - ref ) <= eps1 ) { return true ; }
00240
00241 LHCb::Math::Equal_To<double> cmp ( eps2 ) ;
00242 return cmp ( val , ref ) ;
00243 }
00244
00253 inline bool equal_to_int
00254 ( const int ref ,
00255 const double val ,
00256 const double eps1 = 1.e-6 ,
00257 const double eps2 = 0.5e-3 / boost::integer_traits<int>::const_max )
00258 {
00259 BOOST_STATIC_ASSERT(boost::integer_traits<int>::is_specialized ) ;
00260 return equal_to_int ( val , ref , eps1 , eps2 ) ;
00261 }
00262
00271 inline bool equal_to_uint
00272 ( const double val ,
00273 const unsigned int ref ,
00274 const double eps1 = 1.e-6 ,
00275 const double eps2 = 1.e-3 / boost::integer_traits<unsigned int>::const_max )
00276 {
00277 BOOST_STATIC_ASSERT(boost::integer_traits<unsigned int>::is_specialized ) ;
00278
00279 if ( val == ref ) { return true ; }
00280
00281 if ( val > boost::integer_traits<unsigned int>::const_max ||
00282 val < boost::integer_traits<unsigned int>::const_min ) { return false ; }
00283
00284 if ( std::fabs ( val - ref ) <= eps1 ) { return true ; }
00285
00286 LHCb::Math::Equal_To<double> cmp ( eps2 ) ;
00287 return cmp ( val , ref ) ;
00288 }
00289
00297 inline bool equal_to_uint
00298 ( const unsigned int ref ,
00299 const double val ,
00300 const double eps1 = 1.e-6 ,
00301 const double eps2 = 1.e-3 / boost::integer_traits<unsigned int>::const_max )
00302 { return equal_to_uint ( val , ref , eps1 , eps2 ) ; }
00303
00304 }
00305
00306 }
00307
00308
00309
00310 #endif // LHCBMATH_LHCBMATH_H
00311