| Classes | Job Modules | Data Objects | Services | Algorithms | Tools | Packages | Directories | Tracs |

In This Package:

Digit.h

Go to the documentation of this file.
00001 // $Id: Digit.h,v 1.4 2009/01/10 12:58:54 ibelyaev Exp $
00002 // ============================================================================
00003 #ifndef LHCBMATH_DIGIT_H 
00004 #define LHCBMATH_DIGIT_H 1
00005 // ============================================================================
00006 // Include files
00007 // ============================================================================
00008 // LHCbMath
00009 // ============================================================================
00010 #include "LHCbMath/TypeWrapper.h"
00011 #include "LHCbMath/IPower.hpp"
00012 #include "LHCbMath/Power.h"
00013 // ============================================================================
00014 // Boost
00015 // ============================================================================
00016 #include "boost/integer_traits.hpp"
00017 #include "boost/static_assert.hpp"
00018 // ============================================================================
00059 // ============================================================================
00060 namespace Gaudi
00061 {
00062   namespace Math 
00063   {
00064     namespace detail 
00065     {
00066       // ======================================================================
00079       template <class TYPE,unsigned int N>
00080       struct Check10 
00081       {
00082         // ====================================================================
00083         BOOST_STATIC_ASSERT(  boost::integer_traits<TYPE>::is_specialized ) ;
00084         BOOST_STATIC_ASSERT(  boost::integer_traits<TYPE>::is_integral    ) ;
00085         BOOST_STATIC_ASSERT( !boost::integer_traits<TYPE>::is_signed      ) ;
00086         // ====================================================================
00087         enum
00088           {
00090             safe  = ( N <  (unsigned int) boost::integer_traits<TYPE>::digits10 ) ,
00092             value = ( N <= (unsigned int) boost::integer_traits<TYPE>::digits10 )
00093           } ;
00094         // ====================================================================
00095       };
00096       // ======================================================================
00107       template <class TYPE,
00108                 typename TypeWrapper<TYPE>::value_type I , 
00109                 unsigned int N>
00110       struct _IDigit
00111       {
00112         // ====================================================================
00113         BOOST_STATIC_ASSERT(  boost::integer_traits<TYPE>::is_specialized ) ;
00114         BOOST_STATIC_ASSERT(  boost::integer_traits<TYPE>::is_integral    ) ;
00115         BOOST_STATIC_ASSERT( !boost::integer_traits<TYPE>::is_signed      ) ;
00116         // ====================================================================
00117         enum 
00118           { 
00119             value = 
00120             Check10<TYPE,N>::safe ? 
00121             (I/Gaudi::Math::IPower<TYPE              ,10,N>::value )%10 :
00122             (I/Gaudi::Math::IPower<unsigned long long,10,N>::value )%10 
00123           } ;
00124       private:
00125         // ======================================================================
00126         enum {
00127           _imax10 = boost::integer_traits<TYPE>::digits10 ,
00128           check   = N <= _imax10 
00129         } ;
00130         // ======================================================================  
00131         BOOST_STATIC_ASSERT( check ) ;
00132         // ======================================================================
00133       } ;
00134       // ======================================================================
00144       template <class TYPE,
00145                 typename TypeWrapper<TYPE>::value_type I , 
00146                 unsigned int N1 ,
00147                 unsigned int N2 >  
00148       struct _IDigits
00149       {
00150         // ====================================================================
00151         BOOST_STATIC_ASSERT(  boost::integer_traits<TYPE>::is_specialized ) ;
00152         BOOST_STATIC_ASSERT(  boost::integer_traits<TYPE>::is_integral    ) ;
00153         BOOST_STATIC_ASSERT( !boost::integer_traits<TYPE>::is_signed      ) ;
00154         // ====================================================================
00155         enum 
00156           { 
00157             value = 
00158             Check10<TYPE,N1>::safe && Check10<TYPE,N2-N1>::safe     ?
00159             (I/Gaudi::Math::IPower<TYPE              ,10,N1>::value )%
00160             Gaudi::Math::IPower<TYPE,10,N2-N1>::value :
00161             (I/Gaudi::Math::IPower<unsigned long long,10,N1>::value )%
00162             Gaudi::Math::IPower<unsigned long long,10,N2-N1>::value 
00163           };
00164         // ====================================================================
00165       private:
00166         // ====================================================================
00167         enum {
00168           _imax10 = boost::integer_traits<TYPE>::digits10 ,
00169           check1  = N1 < N2 ,
00170           check2  = N1 <= _imax10 ,
00171           check3  = N2 <= _imax10 + 1 
00172         } ;
00173         // ====================================================================
00174         BOOST_STATIC_ASSERT( check1 ) ;
00175         BOOST_STATIC_ASSERT( check2 ) ;
00176         BOOST_STATIC_ASSERT( check3 ) ;
00177         // ====================================================================`
00178       } ;
00179       // ======================================================================
00188       template <class TYPE, unsigned int N>
00189       struct _Digit : public std::unary_function<TYPE,int>
00190       {
00191         // ====================================================================
00192         BOOST_STATIC_ASSERT(  boost::integer_traits<TYPE>::is_specialized ) ;
00193         BOOST_STATIC_ASSERT(  boost::integer_traits<TYPE>::is_integral    ) ;
00194         BOOST_STATIC_ASSERT( !boost::integer_traits<TYPE>::is_signed      ) ;
00195         // ====================================================================
00196         enum { value = Gaudi::Math::IPower<unsigned long long,10,N>::value } ;
00197         // ====================================================================
00198         inline int operator () ( const TYPE v ) const { return (v/value)%10 ; }
00199         // ====================================================================
00200       private:
00201         // ====================================================================
00202         enum {
00203           _imax10 = boost::integer_traits<TYPE>::digits10 
00204         } ;
00205         // ====================================================================
00206         BOOST_STATIC_ASSERT( N <= _imax10 ) ;
00207         // ====================================================================
00208       } ;
00209       // ======================================================================
00210       template <class TYPE, unsigned int N, bool OK>
00211       struct __Dig10 
00212       { enum { value = Gaudi::Math::IPower<TYPE,10,N>::value } ; } ;
00213       // ======================================================================
00214       template <class TYPE, unsigned int N>
00215       struct __Dig10<TYPE,N,false> 
00216       { enum { value = Gaudi::Math::IPower<unsigned long long,10,N>::value } ; } ;
00217       // ======================================================================
00227       template <class TYPE, 
00228                 unsigned int N1,
00229                 unsigned int N2>
00230       struct _Digits : public std::unary_function<TYPE,int>
00231       {
00232       private:
00233         // ====================================================================
00234         BOOST_STATIC_ASSERT(  boost::integer_traits<TYPE>::is_specialized ) ;
00235         BOOST_STATIC_ASSERT(  boost::integer_traits<TYPE>::is_integral    ) ;
00236         BOOST_STATIC_ASSERT( !boost::integer_traits<TYPE>::is_signed      ) ;
00237         // ====================================================================
00238         enum
00239           {
00240             val1 = __Dig10<TYPE,N1,
00241             Check10<TYPE,N1>::safe && Check10<TYPE,N2-N1>::safe>:: value ,
00242             val2 = __Dig10<TYPE,N2-N1,
00243             Check10<TYPE,N1>::safe && Check10<TYPE,N2-N1>::safe>:: value 
00244           } ;
00245         // ====================================================================        
00246       public:
00247         // ====================================================================
00249         inline int operator() ( const TYPE v ) const { return (v/val1)%val2 ; }
00250         // ====================================================================
00251       private:
00252         // ====================================================================
00253         enum {
00254           _imax10 = boost::integer_traits<TYPE>::digits10 
00255         } ;
00256         // ====================================================================
00257         BOOST_STATIC_ASSERT( N1 < N2 ) ;
00258         BOOST_STATIC_ASSERT( N1 <= _imax10     ) ;
00259         BOOST_STATIC_ASSERT( N2 <= _imax10 + 1 ) ;
00260         // ====================================================================
00261       };
00262     } // end of namespace detail 
00263     // ========================================================================
00279     // ========================================================================
00280     template <class TYPE, 
00281               typename Gaudi::Math::TypeWrapper<TYPE>::value_type I , 
00282               unsigned int N>
00283     struct IDigit : public detail::_IDigit<TYPE,I,N>
00284     {
00285       // ======================================================================
00286       BOOST_STATIC_ASSERT(  boost::integer_traits<TYPE>::is_specialized ) ;
00287       BOOST_STATIC_ASSERT(  boost::integer_traits<TYPE>::is_integral    ) ;
00288       BOOST_STATIC_ASSERT( !boost::integer_traits<TYPE>::is_signed      ) ;
00289       // ======================================================================
00290     };
00291     // ========================================================================
00308     template <class TYPE, 
00309               typename Gaudi::Math::TypeWrapper<TYPE>::value_type I , 
00310               unsigned int N1 , 
00311               unsigned int N2 >
00312     struct IDigits : public detail::_IDigits<TYPE,I,N1,N2>     
00313     {
00314       // ======================================================================
00315       BOOST_STATIC_ASSERT(  boost::integer_traits<TYPE>::is_specialized ) ;
00316       BOOST_STATIC_ASSERT(  boost::integer_traits<TYPE>::is_integral    ) ;
00317       BOOST_STATIC_ASSERT( !boost::integer_traits<TYPE>::is_signed      ) ;
00318       // ======================================================================
00319     };
00320     // ========================================================================
00340     template <class TYPE, unsigned int N>
00341     struct Digit : public detail::_Digit<TYPE,N>
00342     {
00343       // ======================================================================
00344       BOOST_STATIC_ASSERT(  boost::integer_traits<TYPE>::is_specialized ) ;
00345       BOOST_STATIC_ASSERT(  boost::integer_traits<TYPE>::is_integral    ) ;
00346       BOOST_STATIC_ASSERT( !boost::integer_traits<TYPE>::is_signed      ) ;
00347       // ======================================================================
00348     };
00349     // ========================================================================
00369     template <class        TYPE , 
00370               unsigned int N1   , 
00371               unsigned int N2   >
00372     struct Digits : public detail::_Digits<TYPE,N1,N2>
00373     {
00374       // ======================================================================
00375       BOOST_STATIC_ASSERT(  boost::integer_traits<TYPE>::is_specialized ) ;
00376       BOOST_STATIC_ASSERT(  boost::integer_traits<TYPE>::is_integral    ) ;
00377       BOOST_STATIC_ASSERT( !boost::integer_traits<TYPE>::is_signed      ) ;
00378       // ======================================================================
00379     };
00380     // ========================================================================
00398     template <class TYPE>
00399     inline TYPE digit ( const TYPE value , const unsigned int N  ) 
00400     {
00401       // ======================================================================
00402       BOOST_STATIC_ASSERT (  boost::integer_traits<TYPE>::is_specialized ) ;
00403       BOOST_STATIC_ASSERT (  boost::integer_traits<TYPE>::is_integral    ) ;
00404       BOOST_STATIC_ASSERT ( !boost::integer_traits<TYPE>::is_signed      ) ;
00405       // ======================================================================
00406       if      (  N > (unsigned int) boost::integer_traits<TYPE>::digits10 ) { return 0 ; } // RETURN 
00407       else if (  N < (unsigned int) boost::integer_traits<TYPE>::digits10 ) 
00408       {
00409         // ====================================================================
00410         const TYPE ten = 10 ;
00411         const TYPE aux = Gaudi::Math::pow ( ten , N ) ;
00412         return (value/aux)%10 ;                                       // RETURN 
00413         // ====================================================================
00414       }
00415       // ======================================================================
00416       const unsigned long long val = value ;
00417       const unsigned long long ten = 10    ;
00418       const unsigned long long aux = Gaudi::Math::pow ( ten , N ) ;
00419       return (val/aux)%10 ;                                         // RETURN
00420       // ======================================================================
00421     }  
00422     // ========================================================================
00441     template <class TYPE>
00442     inline TYPE digits ( const TYPE         value , 
00443                          const unsigned int N1    ,
00444                          const unsigned int N2    ) 
00445     {
00446       // ======================================================================
00447       BOOST_STATIC_ASSERT (  boost::integer_traits<TYPE>::is_specialized ) ;
00448       BOOST_STATIC_ASSERT (  boost::integer_traits<TYPE>::is_integral    ) ;
00449       BOOST_STATIC_ASSERT ( !boost::integer_traits<TYPE>::is_signed      ) ;
00450       // ======================================================================
00451       if      (  N2 >  1 + boost::integer_traits<TYPE>::digits10 )
00452       { return digits ( value , N1 , 1 + boost::integer_traits<TYPE>::digits10 ) ; }
00453       // ======================================================================
00454       if      (  N1 >= N2 || 
00455                  N1 > (unsigned int) boost::integer_traits<TYPE>::digits10 )
00456       { return 0 ; }                                                  // RETURN 
00457       //
00458       if ( N1      < (unsigned int) boost::integer_traits<TYPE>::digits10 && 
00459            N2 - N1 < (unsigned int) boost::integer_traits<TYPE>::digits10 ) 
00460       {
00461         // ====================================================================
00462         const TYPE ten = 10 ;
00463         const TYPE aux1 = Gaudi::Math::pow ( ten ,      N1 ) ;
00464         const TYPE aux2 = Gaudi::Math::pow ( ten , N2 - N1 ) ;
00465         return (value/aux1)%aux2 ;                                    // RETURN 
00466         // ====================================================================
00467       }
00468       // ======================================================================
00469       const unsigned long long val  = value ;
00470       const unsigned long long ten  = 10 ;
00471       const unsigned long long aux1 = Gaudi::Math::pow ( ten , N1      ) ;
00472       const unsigned long long aux2 = Gaudi::Math::pow ( ten , N2 - N1 ) ;
00473       return (val/aux1)%aux2 ;                                        // RETURN
00474       // ======================================================================
00475     }
00476     // ========================================================================
00477   } // end of namespace Gaudi::Math
00478 } // end of namespace Gaudi
00479 // ============================================================================
00480 // The END 
00481 // ============================================================================
00482 #endif // LHCBMATH_DIGIT_H
00483 // ============================================================================
| Classes | Job Modules | Data Objects | Services | Algorithms | Tools | Packages | Directories | Tracs |

Generated on Mon Apr 11 20:02:57 2011 for LHCbMath by doxygen 1.4.7