Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-02 07:53:07

0001 //==========================================================================
0002 //  AIDA Detector description implementation 
0003 //--------------------------------------------------------------------------
0004 // Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
0005 // All rights reserved.
0006 //
0007 // For the licensing terms see $DD4hepINSTALL/LICENSE.
0008 // For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
0009 //
0010 //==========================================================================
0011 #include <DDSegmentation/BitFieldCoder.h>
0012 
0013 #include <cmath>
0014 #include <algorithm>
0015 #include <sstream>
0016 #include <stdexcept>
0017 
0018 namespace dd4hep{
0019 
0020   namespace DDSegmentation {
0021   
0022     BitFieldElement::BitFieldElement( const std::string& fieldName,
0023                                       unsigned fieldOffset, int signedWidth ) :
0024       _mask(0), 
0025       _offset( fieldOffset ),
0026       _width( abs( signedWidth ) ),
0027       _minVal(0),
0028       _maxVal(0),
0029       _isSigned( signedWidth < 0 ),
0030       _name( fieldName ) {
0031     
0032       // sanity check
0033       if( _offset > 63 || _offset+_width > 64 ) {
0034       
0035         std::stringstream s ;
0036         s << " BitFieldElement '" << _name << "': out of range -  offset : " 
0037           << _offset  << " width " << _width  ;
0038       
0039         throw( std::runtime_error( s.str() ) ) ;
0040       }
0041     
0042       _mask = ( ( 0x0001LL << _width ) - 1 ) << _offset ;
0043     
0044     
0045       // compute extreme values for later checks
0046       if( _isSigned ){
0047       
0048         _minVal =  ( 1LL << ( _width - 1 ) ) - ( 1LL << _width )  ;
0049         _maxVal =  ( 1LL << ( _width - 1 ) ) - 1 ;
0050       
0051       } else {
0052         _maxVal = 0x0001<<_width  ;
0053       }
0054     }
0055   
0056     FieldID BitFieldElement::value(CellID id) const { 
0057       if(  _isSigned   ) {
0058         FieldID val = ( id & _mask ) >> _offset ;
0059         if( ( val  & ( 1LL << ( _width - 1 ) ) ) != 0 ) { // negative value
0060           val -= ( 1LL << _width );
0061         }
0062         return val ;
0063       } else { 
0064         return  ( id & _mask ) >> _offset ;
0065       }
0066     }
0067 
0068     void BitFieldElement::set(CellID& field, FieldID in) const {
0069     
0070       // check range 
0071       if( in < _minVal || in > _maxVal  ) {
0072         std::stringstream s ;
0073         s << " BitFieldElement '" << _name << "': out of range : " << in 
0074           << " for width " << _width  ; 
0075         throw( std::runtime_error( s.str() ) );
0076       }
0077     
0078       field &= ~_mask ;  // zero out the field's range
0079       field |=  ( (  in  << _offset )  & _mask  ) ; 
0080     }
0081   
0082 
0083 
0084 
0085     size_t BitFieldCoder::index( const std::string& name) const {
0086     
0087       IndexMap::const_iterator it = _map.find( name ) ;
0088     
0089       if( it != _map.end() ) 
0090       
0091         return it->second  ;
0092     
0093       else
0094         throw std::runtime_error(" BitFieldElement: unknown name: " + name ) ;
0095     }
0096   
0097     unsigned BitFieldCoder::highestBit() const {
0098     
0099       unsigned hb(0) ;
0100     
0101       for(unsigned i=0;i<_fields.size();i++){
0102       
0103         if( hb < ( _fields[i].offset() + _fields[i].width() ) )
0104           hb = _fields[i].offset() + _fields[i].width()  ;
0105       }    
0106       return hb ;
0107     }
0108 
0109 
0110     std::string BitFieldCoder::valueString(CellID bitfield) const {
0111 
0112       std::stringstream  os ;
0113 
0114       for(unsigned i=0;i<_fields.size();i++){
0115       
0116         if( i != 0 )   os << "," ;
0117 
0118         os << _fields[i].name() <<  ":" << _fields[i].value(bitfield) ;
0119 
0120       }
0121       return os.str() ;
0122     }
0123   
0124     std::string BitFieldCoder::fieldDescription() const {
0125     
0126       std::stringstream  os ;
0127     
0128       for(unsigned i=0;i<_fields.size();i++){
0129       
0130         if( i != 0 )   os << "," ;
0131       
0132         os << _fields[i].name() <<  ":"
0133            << _fields[i].offset() << ":" ;
0134       
0135         if(  _fields[i].isSigned()  )
0136           os << "-" ;
0137       
0138         os  << _fields[i].width() ;
0139       
0140       }
0141 
0142       return os.str() ;
0143     }
0144 
0145     void BitFieldCoder::addField( const std::string& name,  unsigned offset, int width ){
0146 
0147       
0148       _fields.emplace_back(name, offset, width);
0149       BitFieldElement& bfv = _fields.back() ;
0150 
0151       _map[ name ] = _fields.size()-1 ;
0152 
0153       if( _joined & bfv.mask()  ) {
0154       
0155         std::stringstream s ;
0156         s << " BitFieldElement::addField(" << name << "): bits already used " << std::hex << _joined
0157           << " for mask " <<  bfv.mask() ;
0158 
0159         throw( std::runtime_error( s.str() ) ) ;
0160       
0161       }
0162 
0163       _joined |= bfv.mask() ;
0164 
0165     }
0166 
0167     void BitFieldCoder::init( const std::string& initString) {
0168 
0169       unsigned offset = 0  ;
0170     
0171       // need to compute bit field masks and offsets ...
0172       std::vector<std::string> fieldDescriptors ;
0173       StringTokenizer t( fieldDescriptors ,',') ;
0174 
0175       std::for_each( initString.begin(), initString.end(), t ) ; 
0176 
0177       for(unsigned i=0; i< fieldDescriptors.size() ; i++ ){
0178       
0179         std::vector<std::string> subfields ;
0180         StringTokenizer ts( subfields ,':') ;
0181       
0182         std::for_each( fieldDescriptors[i].begin(), fieldDescriptors[i].end(), ts );
0183 
0184         std::string name ; 
0185         int  width ; 
0186         unsigned thisOffset ;
0187 
0188         switch( subfields.size() ){
0189     
0190         case 2: 
0191 
0192           name = subfields[0] ; 
0193           width = atol( subfields[1].c_str()  ) ;
0194           thisOffset = offset ;
0195 
0196           offset += abs( width ) ;
0197     
0198           break ;
0199     
0200         case 3: 
0201           name = subfields[0] ;
0202           thisOffset = atol( subfields[1].c_str()  ) ;
0203           width = atol( subfields[2].c_str()  ) ;
0204 
0205           offset = thisOffset + abs( width ) ;
0206 
0207           break ;
0208     
0209         default:
0210 
0211           std::stringstream s ;
0212           s << " BitFieldCoder: invalid number of subfields " 
0213             <<  fieldDescriptors[i] ;
0214 
0215           throw( std::runtime_error( s.str() ) ) ;
0216         }
0217 
0218         addField( name , thisOffset, width ) ;
0219       }
0220     }
0221 
0222 
0223 
0224 
0225   } // namespace
0226 
0227 } // namespace