DD4hep - The AIDA detector description toolkit for high energy physics experiments
DD4hep  Rev:Unversioneddirectory
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
BitField64.cpp
Go to the documentation of this file.
2 
3 #include <cmath>
4 #include <algorithm>
5 #include <stdexcept>
6 
7 namespace DD4hep{
8 
9 namespace DDSegmentation {
10 
11  BitFieldValue::BitFieldValue( long64& bitfield, const std::string& fieldName,
12  unsigned fieldOffset, int signedWidth ) :
13  _b(bitfield),
14  _mask(0),
15  _name( fieldName ),
16  _offset( fieldOffset ),
17  _width( abs( signedWidth ) ),
18  _minVal(0),
19  _maxVal(0),
20  _isSigned( signedWidth < 0 ) {
21 
22  // sanity check
23  if( _offset > 63 || _offset+_width > 64 ) {
24 
25  std::stringstream s ;
26  s << " BitFieldValue '" << _name << "': out of range - offset : "
27  << _offset << " width " << _width ;
28 
29  throw( std::runtime_error( s.str() ) ) ;
30  }
31 
32  _mask = ( ( 0x0001LL << _width ) - 1 ) << _offset ;
33 
34 
35  // compute extreme values for later checks
36  if( _isSigned ){
37 
38  _minVal = ( 1LL << ( _width - 1 ) ) - ( 1LL << _width ) ;
39  _maxVal = ( 1LL << ( _width - 1 ) ) - 1 ;
40 
41  } else {
42 
43  _maxVal = 0x0001<<_width ;
44  }
45 
46  // std::cout << " _mask :" << std::hex << _mask
47  // << std::dec << std::endl ;
48  // std::cout << " min " << _minVal
49  // << " max " << _maxVal
50  // << " width " << _width
51  // << std::endl ;
52 
53  }
54 
55 
57 
58  if( _isSigned ) {
59 
60  long64 val = ( _b & _mask ) >> _offset ;
61 
62  if( ( val & ( 1LL << ( _width - 1 ) ) ) != 0 ) { // negative value
63 
64  val -= ( 1LL << _width );
65  }
66 
67  return val ;
68 
69  } else {
70 
71  return ( _b & _mask ) >> _offset ;
72  }
73  }
74 
76 
77  if( _isSigned ) {
78 
79  long64 val = ( id & _mask ) >> _offset ;
80 
81  if( ( val & ( 1LL << ( _width - 1 ) ) ) != 0 ) { // negative value
82 
83  val -= ( 1LL << _width );
84  }
85 
86  return val ;
87 
88  } else {
89 
90  return ( id & _mask ) >> _offset ;
91  }
92  }
93 
95 
96  // check range
97  if( in < _minVal || in > _maxVal ) {
98 
99  std::stringstream s ;
100  s << " BitFieldValue '" << _name << "': out of range : " << in
101  << " for width " << _width ;
102 
103  throw( std::runtime_error( s.str() ) );
104  }
105 
106  _b &= ~_mask ; // zero out the field's range
107 
108  _b |= ( ( in << _offset ) & _mask ) ;
109 
110  return *this ;
111  }
112 
113 
114 
115 
116  size_t BitField64::index( const std::string& name) const {
117 
118  IndexMap::const_iterator it = _map.find( name ) ;
119 
120  if( it != _map.end() )
121 
122  return it->second ;
123 
124  else
125  throw std::runtime_error(" BitFieldValue: unknown name: " + name ) ;
126  }
127 
128  unsigned BitField64::highestBit() const {
129 
130  unsigned hb(0) ;
131 
132  for(unsigned i=0;i<_fields.size();i++){
133 
134  if( hb < ( _fields[i]->offset() + _fields[i]->width() ) )
135  hb = _fields[i]->offset() + _fields[i]->width() ;
136  }
137  return hb ;
138  }
139 
140 
141  std::string BitField64::valueString() const {
142 
143  std::stringstream os ;
144 
145  for(unsigned i=0;i<_fields.size();i++){
146 
147  if( i != 0 ) os << "," ;
148 
149  os << _fields[i]->name() << ":" << _fields[i]->value() ;
150 
151  }
152  return os.str() ;
153  }
154 
155  std::string BitField64::fieldDescription() const {
156 
157  std::stringstream os ;
158 
159  for(unsigned i=0;i<_fields.size();i++){
160 
161  if( i != 0 ) os << "," ;
162 
163  os << _fields[i]->name() << ":"
164  << _fields[i]->offset() << ":" ;
165 
166  if( _fields[i]->isSigned() )
167  os << "-" ;
168 
169  os << _fields[i]->width() ;
170 
171  }
172 // for( IndexMap::const_iterator it = _map.begin() ;
173 // it != _map.end() ; ++it ){
174 
175 // if( it != _map.begin() )
176 // os << "," ;
177 
178 // os << it->first << ":"
179 // << _fields[ it->second ]->offset() << ":" ;
180 
181 // if( _fields[ it->second ]->isSigned() )
182 // os << "-" ;
183 
184 // os << _fields[ it->second ]->width() ;
185 
186 // }
187 
188  return os.str() ;
189  }
190 
191  void BitField64::addField( const std::string& name, unsigned offset, int width ){
192 
193 
194  BitFieldValue* bfv = new BitFieldValue( _value, name, offset, width ) ;
195 
196  _fields.push_back( bfv ) ;
197 
198  _map[ name ] = _fields.size()-1 ;
199 
200  if( _joined & bfv->mask() ) {
201 
202  std::stringstream s ;
203  s << " BitFieldValue::addField(" << name << "): bits already used " << std::hex << _joined
204  << " for mask " << bfv->mask() ;
205 
206  throw( std::runtime_error( s.str() ) ) ;
207 
208  }
209 
210  _joined |= _fields.back()->mask() ;
211 
212  }
213 
214  void BitField64::init( const std::string& initString) {
215 
216  unsigned offset = 0 ;
217 
218  // need to compute bit field masks and offsets ...
219  std::vector<std::string> fieldDescriptors ;
220  StringTokenizer t( fieldDescriptors ,',') ;
221 
222  std::for_each( initString.begin(), initString.end(), t ) ;
223 
224  for(unsigned i=0; i< fieldDescriptors.size() ; i++ ){
225 
226  std::vector<std::string> subfields ;
227  StringTokenizer ts( subfields ,':') ;
228 
229  std::for_each( fieldDescriptors[i].begin(), fieldDescriptors[i].end(), ts );
230 
231  std::string name ;
232  int width ;
233  unsigned thisOffset ;
234 
235  switch( subfields.size() ){
236 
237  case 2:
238 
239  name = subfields[0] ;
240  width = atol( subfields[1].c_str() ) ;
241  thisOffset = offset ;
242 
243  offset += abs( width ) ;
244 
245  break ;
246 
247  case 3:
248  name = subfields[0] ;
249  thisOffset = atol( subfields[1].c_str() ) ;
250  width = atol( subfields[2].c_str() ) ;
251 
252  offset = thisOffset + abs( width ) ;
253 
254  break ;
255 
256  default:
257 
258  std::stringstream s ;
259  s << " BitField64: invalid number of subfields "
260  << fieldDescriptors[i] ;
261 
262  throw( std::runtime_error( s.str() ) ) ;
263  }
264 
265  addField( name , thisOffset, width ) ;
266  }
267  }
268 
269 
270 
271  std::ostream& operator<<(std::ostream& os, const BitField64& b){
272 
273  os << " bitfield: 0x" << std::hex // << std::ios::width(16) << std::ios::fill('0') <<
274  << b._value << std::dec << std::endl ;
275 
276  for( BitField64::IndexMap::const_iterator it = b._map.begin() ;
277  it != b._map.end() ; ++it ){
278 
279  os << " " << it->first << " [" << b[ it->second ].offset() << ":" ;
280 
281  if( b[ it->second ].isSigned() ) os << "-" ;
282 
283  os << b[ it->second ].width() << "] : " ;
284 
285 
286  os << b[ it->second ].value()
287  << std::endl ;
288 
289  }
290 
291  return os ;
292  }
293 
294 } // namespace
295 
296 } // namespace
std::ostream & operator<<(std::ostream &os, const BitField64 &b)
Definition: BitField64.cpp:271
size_t index(const std::string &name) const
Definition: BitField64.cpp:116
TGeoShape * s
Definition: Volumes.cpp:294
BitFieldValue & operator=(long64 in)
Definition: BitField64.cpp:94
void init(const std::string &initString)
Definition: BitField64.cpp:214
std::vector< BitFieldValue * > _fields
Definition: BitField64.h:165
std::string valueString() const
Definition: BitField64.cpp:141
void addField(const std::string &name, unsigned offset, int width)
Definition: BitField64.cpp:191
std::string fieldDescription() const
Definition: BitField64.cpp:155
BitFieldValue(long64 &bitfield, const std::string &name, unsigned offset, int signedWidth)
Definition: BitField64.cpp:11
long long int long64
Definition: BitField64.h:15