00001
00002
00003 #ifndef LHCBMATH_BIT_H
00004 #define LHCBMATH_BIT_H 1
00005
00006
00007
00008
00009
00010 #include <functional>
00011
00012
00013
00014 #include "LHCbMath/TypeWrapper.h"
00015
00016
00017
00018 #include "boost/integer_traits.hpp"
00019 #include "boost/static_assert.hpp"
00020
00061
00062 namespace Gaudi
00063 {
00064 namespace Math
00065 {
00066 namespace detail
00067 {
00068
00075 template <class TYPE,unsigned int N>
00076 struct Check
00077 {
00078
00079 BOOST_STATIC_ASSERT( boost::integer_traits<TYPE>::is_specialized
00080 && boost::integer_traits<TYPE>::is_integral
00081 &&!boost::integer_traits<TYPE>::is_signed ) ;
00082
00083 enum { value = N < (unsigned int) boost::integer_traits <TYPE>::digits } ;
00084
00085 };
00086
00092 template <class TYPE,
00093 typename Gaudi::Math::TypeWrapper<TYPE>::value_type I,
00094 unsigned int N>
00095 struct _IBit
00096 {
00097 private:
00098
00099 BOOST_STATIC_ASSERT( boost::integer_traits<TYPE>::is_specialized
00100 &&!boost::integer_traits<TYPE>::is_signed ) ;
00101
00102 public:
00103
00104 enum { value = 0 < ( I & ( static_cast<TYPE>(1) << N ) ) } ;
00105
00106 };
00107
00114 template <class TYPE,
00115 typename Gaudi::Math::TypeWrapper<TYPE>::value_type I,
00116 unsigned int N1,
00117 unsigned int N2>
00118 struct _IBits
00119 {
00120 private:
00121
00122 BOOST_STATIC_ASSERT( boost::integer_traits<TYPE>::is_specialized
00123 &&!boost::integer_traits<TYPE>::is_signed ) ;
00124
00125 public:
00126
00127 enum
00128 {
00129 value =
00130 ( I & ( static_cast<TYPE> ( -1 )
00131 << ( boost::integer_traits<TYPE>::digits + N1 - N2 )
00132 >> ( boost::integer_traits<TYPE>::digits - N2 ) ) )
00133 >> N1
00134 } ;
00135
00136 };
00137
00143 template <class TYPE, unsigned int N>
00144 struct _Bit : public std::unary_function<TYPE,bool>
00145 {
00146 private:
00147
00148 BOOST_STATIC_ASSERT( boost::integer_traits<TYPE>::is_specialized
00149 && boost::integer_traits<TYPE>::is_integral
00150 &&!boost::integer_traits<TYPE>::is_signed ) ;
00151
00152 public:
00153
00154 inline bool operator() ( const TYPE value ) const
00155 {
00156 static const TYPE s_mask = static_cast<TYPE> ( 1 ) << N ;
00157 return value & s_mask ;
00158 }
00159
00160 };
00161
00167 template <class TYPE,unsigned int N1,unsigned int N2>
00168 struct _Bits : public std::unary_function<TYPE,TYPE>
00169 {
00170 private:
00171
00172 BOOST_STATIC_ASSERT( boost::integer_traits<TYPE>::is_specialized
00173 && boost::integer_traits<TYPE>::is_integral
00174 &&!boost::integer_traits<TYPE>::is_signed ) ;
00175
00176 BOOST_STATIC_ASSERT( N1 < N2 &&
00177 N1 < (unsigned int) boost::integer_traits<TYPE>::digits &&
00178 N2 <= (unsigned int) boost::integer_traits<TYPE>::digits ) ;
00179
00180 public:
00181
00182 inline TYPE operator() ( const TYPE value ) const
00183 {
00184
00185 static const TYPE s_mask =
00186 ( static_cast<TYPE> ( -1 )
00187 << ( boost::integer_traits<TYPE>::digits + N1 - N2 ) )
00188 >> ( boost::integer_traits<TYPE>::digits - N2 ) ;
00189
00190 return ( value & s_mask ) >> N1 ;
00191
00192 }
00193
00194 } ;
00195
00196 }
00197
00215 template <class TYPE,
00216 typename Gaudi::Math::TypeWrapper<TYPE>::value_type I,
00217 unsigned int N>
00218 struct IBit : public detail::_IBit<TYPE,I,N>
00219 {
00220
00221 BOOST_STATIC_ASSERT ( ( detail::Check<TYPE,N>::value ) ) ;
00222 BOOST_STATIC_ASSERT( boost::integer_traits<TYPE>::is_specialized
00223 && boost::integer_traits<TYPE>::is_integral
00224 &&!boost::integer_traits<TYPE>::is_signed ) ;
00225
00226 };
00227
00244 template <class TYPE,
00245 typename Gaudi::Math::TypeWrapper<TYPE>::value_type I,
00246 unsigned int N1,
00247 unsigned int N2>
00248 struct IBits : public detail::_IBits<TYPE,I,N1,N2>
00249 {
00250
00251 BOOST_STATIC_ASSERT( N1 < N2
00252 && boost::integer_traits<TYPE>::is_specialized
00253 && boost::integer_traits<TYPE>::is_integral
00254 &&!boost::integer_traits<TYPE>::is_signed ) ;
00255
00256 BOOST_STATIC_ASSERT( N1 < (unsigned int) boost::integer_traits<TYPE>::digits &&
00257 N2 < 1 + boost::integer_traits<TYPE>::digits ) ;
00258
00259 };
00260
00280 template <class TYPE, unsigned int N>
00281 struct Bit : public detail::_Bit<TYPE,N>
00282 {
00283
00284 BOOST_STATIC_ASSERT ( ( detail::Check<TYPE,N>::value ) ) ;
00285 BOOST_STATIC_ASSERT ( boost::integer_traits<TYPE>::is_specialized
00286 && boost::integer_traits<TYPE>::is_integral
00287 &&!boost::integer_traits<TYPE>::is_signed ) ;
00288
00289 };
00290
00309 template <class TYPE, unsigned int N1, unsigned int N2>
00310 struct Bits : public detail::_Bits<TYPE,N1,N2>
00311 {
00312
00313 BOOST_STATIC_ASSERT( N1 < N2
00314 && boost::integer_traits<TYPE>::is_specialized
00315 && boost::integer_traits<TYPE>::is_integral
00316 &&!boost::integer_traits<TYPE>::is_signed ) ;
00317
00318 BOOST_STATIC_ASSERT( N1 < (unsigned int) boost::integer_traits<TYPE>::digits &&
00319 N2 < 1 + boost::integer_traits<TYPE>::digits ) ;
00320
00321 };
00322
00339 template <class TYPE>
00340 inline bool bit ( const TYPE value , const unsigned int N )
00341 {
00342
00343 BOOST_STATIC_ASSERT( boost::integer_traits<TYPE>::is_specialized
00344 && boost::integer_traits<TYPE>::is_integral
00345 &&!boost::integer_traits<TYPE>::is_signed ) ;
00346
00347 static const TYPE one = static_cast<TYPE>(1) ;
00348 return N < (unsigned int) boost::integer_traits <TYPE>::digits ?
00349 ( value & ( one << N ) ) : 0 ;
00350
00351 }
00352
00353 template <class TYPE>
00354 inline TYPE bits ( const TYPE value ,
00355 const unsigned int N1 ,
00356 const unsigned int N2 )
00357 {
00358
00359 BOOST_STATIC_ASSERT( boost::integer_traits<TYPE>::is_specialized
00360 && boost::integer_traits<TYPE>::is_integral
00361 &&!boost::integer_traits<TYPE>::is_signed ) ;
00362
00363 if ( N2 > (unsigned int) boost::integer_traits<TYPE>::digits )
00364 { return bits ( value , N1 , boost::integer_traits<TYPE>::digits ) ; }
00365
00366 if ( N1 >= N2 ||
00367 N1 >= (unsigned int) boost::integer_traits<TYPE>::digits ) { return 0 ; }
00368
00369 const TYPE mask =
00370 ( static_cast<TYPE> ( -1 )
00371 << ( boost::integer_traits<TYPE>::digits + N1 - N2 ) )
00372 >> ( boost::integer_traits<TYPE>::digits - N2 ) ;
00373
00374 return ( value & mask ) >> N1 ;
00375
00376 }
00377
00378 }
00379
00380 }
00381
00382
00383
00384 #endif // LHCBMATH_DIGIT_H
00385