Mesh Oriented datABase  (version 5.5.0)
An array-based unstructured mesh library
BitTag.cpp
Go to the documentation of this file.
1 #include "BitTag.hpp"
2 #include "BitPage.hpp"
3 #include "moab/Range.hpp"
4 #include "TagCompare.hpp"
5 #include "SequenceManager.hpp"
6 #include "moab/Error.hpp"
7 #include "moab/ErrorHandler.hpp"
8 #include <cstdlib>
9 #include <cstring>
10 
11 namespace moab
12 {
13 
15 {
16  release_all_data( 0, 0, true );
17 }
18 
20 {
21  return MB_TAG_BIT;
22 }
23 
24 BitTag* BitTag::create_tag( const char* name, int size, const void* default_value )
25 {
26  BitTag* result = new BitTag( name, size, default_value );
27  if( MB_SUCCESS != result->reserve( size ) )
28  {
29  delete result;
30  result = NULL;
31  }
32 
33  return result;
34 }
35 
36 ErrorCode BitTag::reserve( unsigned bits )
37 {
38  if( bits > 8 ) return MB_FAILURE;
39 
41  // Store smallest power of two greater than or
42  // equal to the number of bits
44  unsigned ln2storedbits = 0;
45  while( storedBitsPerEntity < bits )
46  {
48  ++ln2storedbits;
49  }
50 
51  // pageShift = log2(ents_per_page())
52  // = log2(8 * pageSize / storedBitsPerEntity )
53  // = log2(8) + log2(pageSize) - log2(storedBitsPerEntity)
54  // = 3 + Ln2PageSize - ln2storedbits;
55  pageShift = 3 + Ln2PageSize - ln2storedbits;
56 
57  return MB_SUCCESS;
58 }
59 
61 {
62  for( EntityType t = (EntityType)0; t != MBMAXTYPE; ++t )
63  {
64  for( size_t i = 0; i < pageList[t].size(); ++i )
65  delete pageList[t][i];
66  pageList[t].clear();
67  }
68 
69  return MB_SUCCESS;
70 }
71 
73  Error*,
74  const EntityHandle* handles,
75  size_t num_handles,
76  void* gen_data ) const
77 {
78  EntityType type;
79  size_t page;
80  int offset;
81  unsigned char def = default_val();
82  unsigned char* data = reinterpret_cast< unsigned char* >( gen_data );
83  for( size_t i = 0; i < num_handles; ++i )
84  {
85  unpack( handles[i], type, page, offset );
86  if( pageList[type].size() <= page || !pageList[type][page] )
87  data[i] = def;
88  else
89  data[i] = pageList[type][page]->get_bits( offset, storedBitsPerEntity );
90  }
91 
92  return MB_SUCCESS;
93 }
94 
96  Error* /* error */,
97  const EntityHandle* handles,
98  size_t num_handles,
99  const void* gen_data )
100 {
101  ErrorCode rval = seqman->check_valid_entities( NULL, handles, num_handles, true );MB_CHK_ERR( rval );
102 
103  EntityType type;
104  size_t page;
105  int offset;
106  const unsigned char* data = reinterpret_cast< const unsigned char* >( gen_data );
107  for( size_t i = 0; i < num_handles; ++i )
108  {
109  unpack( handles[i], type, page, offset );
110  if( pageList[type].size() <= page ) pageList[type].resize( page + 1, 0 );
111  if( !pageList[type][page] ) pageList[type][page] = new BitPage( storedBitsPerEntity, default_val() );
112  pageList[type][page]->set_bits( offset, storedBitsPerEntity, data[i] );
113  }
114 
115  return MB_SUCCESS;
116 }
117 
119  Error* /* error */,
120  const EntityHandle* handles,
121  size_t num_handles,
122  const void* value_ptr,
123  int value_len )
124 {
125  if( value_len ) return MB_INVALID_SIZE;
126 
127  ErrorCode rval = seqman->check_valid_entities( NULL, handles, num_handles, true );MB_CHK_ERR( rval );
128 
129  EntityType type;
130  size_t page;
131  int offset;
132  const unsigned char value = *reinterpret_cast< const unsigned char* >( value_ptr );
133  for( size_t i = 0; i < num_handles; ++i )
134  {
135  unpack( handles[i], type, page, offset );
136  if( pageList[type].size() <= page ) pageList[type].resize( page + 1, 0 );
137  if( !pageList[type][page] ) pageList[type][page] = new BitPage( storedBitsPerEntity, default_val() );
138  pageList[type][page]->set_bits( offset, storedBitsPerEntity, value );
139  }
140 
141  return MB_SUCCESS;
142 }
143 
144 ErrorCode BitTag::remove_data( SequenceManager*, Error*, const EntityHandle* handles, size_t num_handles )
145 {
146  EntityType type;
147  size_t page;
148  int offset;
149  const unsigned char val = default_val();
150  for( size_t i = 0; i < num_handles; ++i )
151  {
152  unpack( handles[i], type, page, offset );
153  if( pageList[type].size() > page && pageList[type][page] )
154  pageList[type][page]->set_bits( offset, storedBitsPerEntity, val );
155  }
156 
157  return MB_SUCCESS;
158 }
159 
160 ErrorCode BitTag::get_data( const SequenceManager*, Error*, const Range& handles, void* gen_data ) const
161 {
162  EntityType type;
163  EntityID count;
164  size_t page;
165  int offset, per_page = ents_per_page();
166  unsigned char def = default_val();
167  unsigned char* data = reinterpret_cast< unsigned char* >( gen_data );
169  for( i = handles.const_pair_begin(); i != handles.const_pair_end(); ++i )
170  {
171  unpack( i->first, type, page, offset );
172  assert( TYPE_FROM_HANDLE( i->second ) == type ); // Should be true because id of zero is never used
173  count = i->second - i->first + 1;
174  if( page >= pageList[type].size() )
175  {
176  memset( data, def, count );
177  data += count;
178  continue;
179  }
180 
181  while( count )
182  {
183  size_t pcount = std::min( (EntityID)( per_page - offset ), count );
184  if( pageList[type][page] )
185  pageList[type][page]->get_bits( offset, pcount, storedBitsPerEntity, data );
186  else
187  memset( data, def, pcount );
188  data += pcount;
189  count -= pcount;
190  offset = 0;
191  ++page;
192  }
193  }
194 
195  return MB_SUCCESS;
196 }
197 
198 ErrorCode BitTag::set_data( SequenceManager* seqman, Error* /* error */, const Range& handles, const void* gen_data )
199 {
200  ErrorCode rval = seqman->check_valid_entities( NULL, handles );MB_CHK_ERR( rval );
201 
202  EntityType type;
203  EntityID count;
204  size_t page;
205  int offset, per_page = ents_per_page();
206  unsigned char def = default_val();
207  const unsigned char* data = reinterpret_cast< const unsigned char* >( gen_data );
209  for( i = handles.const_pair_begin(); i != handles.const_pair_end(); ++i )
210  {
211  unpack( i->first, type, page, offset );
212  assert( TYPE_FROM_HANDLE( i->second ) == type ); // Should be true because id of zero is never used
213  count = i->second - i->first + 1;
214 
215  while( count )
216  {
217  if( page >= pageList[type].size() ) pageList[type].resize( page + 1, 0 );
218  if( !pageList[type][page] ) pageList[type][page] = new BitPage( storedBitsPerEntity, def );
219 
220  size_t pcount = std::min( (EntityID)( per_page - offset ), count );
221  pageList[type][page]->set_bits( offset, pcount, storedBitsPerEntity, data );
222  data += pcount;
223  count -= pcount;
224  offset = 0;
225  ++page;
226  }
227  }
228 
229  return MB_SUCCESS;
230 }
231 
233  Error* /* error */,
234  const Range& handles,
235  const void* value_ptr,
236  int value_len )
237 {
238  if( value_len ) return MB_INVALID_SIZE;
239 
240  ErrorCode rval = seqman->check_valid_entities( NULL, handles );MB_CHK_ERR( rval );
241 
242  EntityType type;
243  EntityID count;
244  size_t page;
245  int offset, per_page = ents_per_page();
246  const unsigned char value = *reinterpret_cast< const unsigned char* >( value_ptr );
248  for( i = handles.const_pair_begin(); i != handles.const_pair_end(); ++i )
249  {
250  unpack( i->first, type, page, offset );
251  assert( TYPE_FROM_HANDLE( i->second ) == type ); // Should be true because id of zero is never used
252  count = i->second - i->first + 1;
253 
254  while( count )
255  {
256  if( page >= pageList[type].size() ) pageList[type].resize( page + 1, 0 );
257  if( !pageList[type][page] ) pageList[type][page] = new BitPage( storedBitsPerEntity, default_val() );
258 
259  size_t pcount = std::min( (EntityID)( per_page - offset ), count );
260  pageList[type][page]->set_bits( offset, pcount, storedBitsPerEntity, value );
261  count -= pcount;
262  offset = 0;
263  ++page;
264  }
265  }
266 
267  return MB_SUCCESS;
268 }
269 
271 {
272  EntityType type;
273  EntityID count;
274  size_t page;
275  int offset, per_page = ents_per_page();
276  unsigned char val = default_val();
278  for( i = handles.const_pair_begin(); i != handles.const_pair_end(); ++i )
279  {
280  unpack( i->first, type, page, offset );
281  assert( TYPE_FROM_HANDLE( i->second ) == type ); // Should be true because id of zero is never used
282  count = i->second - i->first + 1;
283 
284  while( count )
285  {
286  size_t pcount = std::min( (EntityID)( per_page - offset ), count );
287  if( page < pageList[type].size() && pageList[type][page] )
288  pageList[type][page]->set_bits( offset, pcount, storedBitsPerEntity, val );
289  count -= pcount;
290  offset = 0;
291  ++page;
292  }
293  }
294 
295  return MB_SUCCESS;
296 }
297 
299  Error* /* error */,
300  const EntityHandle*,
301  size_t,
302  const void**,
303  int* ) const
304 {
305  MB_SET_ERR( MB_TYPE_OUT_OF_RANGE, "Operation get_data not supported for bit tags" );
306 }
307 
308 ErrorCode BitTag::get_data( const SequenceManager*, Error* /* error */, const Range&, const void**, int* ) const
309 {
310  MB_SET_ERR( MB_TYPE_OUT_OF_RANGE, "Operation get_data not supported for bit tags" );
311 }
312 
314  Error* /* error */,
315  const EntityHandle*,
316  size_t,
317  void const* const*,
318  const int* )
319 {
320  MB_SET_ERR( MB_TYPE_OUT_OF_RANGE, "Operation set_data not supported for bit tags" );
321 }
322 
323 ErrorCode BitTag::set_data( SequenceManager*, Error* /* error */, const Range&, void const* const*, const int* )
324 {
325  MB_SET_ERR( MB_TYPE_OUT_OF_RANGE, "Operation set_data not supported for bit tags" );
326 }
327 
329  Error* /* error */,
331  const Range::iterator&,
332  void*&,
333  bool )
334 {
335  MB_SET_ERR( MB_TYPE_OUT_OF_RANGE, "Operation tag_iterate not supported for bit tags" );
336 }
337 
338 template < class Container >
339 inline void BitTag::get_tagged( EntityType type, Container& entities ) const
340 {
341  std::pair< EntityType, EntityType > r = type_range( type );
342  typename Container::iterator hint = entities.begin();
343  const int per_page = ents_per_page();
344  for( EntityType t = r.first; t != r.second; ++t )
345  {
346  for( size_t i = 0; i < pageList[t].size(); ++i )
347  {
348  if( pageList[t][i] )
349  {
350  EntityID id = i * per_page;
351  EntityHandle h = CREATE_HANDLE( t, id );
352  EntityHandle last = h + per_page - 1;
353  // Never zero ID
354  if( 0 == id ) ++h;
355  hint = entities.insert( hint, h, last );
356  }
357  }
358  }
359 }
360 
361 template < class Container >
362 inline void BitTag::get_tagged( Range::const_iterator begin, Range::const_iterator end, Container& entities ) const
363 {
364  EntityType type;
365  EntityID count;
366  size_t page;
367  int offset, per_page = ents_per_page();
368  typename Container::iterator hint = entities.begin();
369  EntityHandle h;
370  Range::const_iterator i = begin;
371  while( i != end )
372  {
373  h = *i;
374  unpack( h, type, page, offset );
375 
376  i = i.end_of_block();
377  count = *i - h + 1;
378  ++i;
379  while( count > 0 )
380  {
381  EntityID pcount = std::min( count, (EntityID)( per_page - offset ) );
382  if( page < pageList[type].size() && pageList[type][page] )
383  hint = entities.insert( hint, h, h + pcount - 1 );
384 
385  count -= pcount;
386  h += pcount;
387  assert( TYPE_FROM_HANDLE( h ) == type );
388  offset = 0;
389  ++page;
390  }
391  }
392 }
393 
394 template < class Container >
395 inline void BitTag::get_tagged( Container& entities, EntityType type, const Range* intersect ) const
396 
397 {
398  if( !intersect )
399  get_tagged< Container >( type, entities );
400  else if( MBMAXTYPE == type )
401  get_tagged< Container >( intersect->begin(), intersect->end(), entities );
402  else
403  {
404  std::pair< Range::iterator, Range::iterator > r = intersect->equal_range( type );
405  get_tagged< Container >( r.first, r.second, entities );
406  }
407 }
408 
410  Range& entities,
411  EntityType type,
412  const Range* intersect ) const
413 {
414  get_tagged< Range >( entities, type, intersect );
415  return MB_SUCCESS;
416 }
417 
419  size_t& count,
420  EntityType type,
421  const Range* intersect ) const
422 {
423  InsertCount counter( count );
424  get_tagged< InsertCount >( counter, type, intersect );
425  count = counter.end();
426  return MB_SUCCESS;
427 }
428 
430  Error* /* error */,
431  Range& output_entities,
432  const void* value,
433  int value_bytes,
434  EntityType type,
435  const Range* intersect_entities ) const
436 {
437  if( value_bytes && value_bytes != 1 )
438  {
439  MB_SET_ERR( MB_INVALID_SIZE, "Invalid tag size for bit tag: " << value_bytes << " bytes" );
440  }
441 
442  const signed char bits = *reinterpret_cast< const unsigned char* >( value );
443  if( intersect_entities )
444  return get_entities_with_bits( *intersect_entities, type, output_entities, bits );
445  else
446  return get_entities_with_bits( type, output_entities, bits );
447 }
448 
449 ErrorCode BitTag::get_entities_with_bits( EntityType type, Range& entities, unsigned char bits ) const
450 {
451  std::pair< EntityType, EntityType > r = type_range( type );
452  const int per_page = ents_per_page();
453  for( EntityType t = r.first; t != r.second; ++t )
454  {
455  for( size_t i = 0; i < pageList[t].size(); ++i )
456  {
457  if( pageList[t][i] )
458  {
459  EntityID id = i * per_page;
460  EntityHandle h = CREATE_HANDLE( t, id );
461  int off = !i; // Never zero ID
462  pageList[t][i]->search( bits, off, per_page - off, storedBitsPerEntity, entities, h + off );
463  }
464  }
465  }
466 
467  return MB_SUCCESS;
468 }
469 
471  EntityType in_type,
472  Range& entities,
473  unsigned char bits ) const
474 {
475  if( MBMAXTYPE == in_type )
476  {
477  ErrorCode rval;
478  for( --in_type; in_type >= MBVERTEX; --in_type )
479  {
480  rval = get_entities_with_bits( range, in_type, entities, bits );MB_CHK_ERR( rval );
481  }
482  return MB_SUCCESS;
483  }
484 
485  EntityType type;
486  EntityID count;
487  size_t page;
488  int offset, per_page = ents_per_page();
489  Range::const_iterator i, end;
490  std::pair< Range::iterator, Range::iterator > r = range.equal_range( in_type );
491  i = r.first;
492  end = r.second;
493  EntityHandle h;
494  while( i != end )
495  {
496  h = *i;
497  unpack( h, type, page, offset );
498  assert( MBMAXTYPE == in_type || type == in_type );
499 
500  i = i.end_of_block();
501  count = *i - h + 1;
502  ++i;
503  while( count > 0 )
504  {
505  EntityID pcount = std::min( count, (EntityID)( per_page - offset ) );
506  if( page < pageList[type].size() && pageList[type][page] )
507  pageList[type][page]->search( bits, offset, pcount, storedBitsPerEntity, entities, h );
508 
509  count -= pcount;
510  h += pcount;
511  assert( TYPE_FROM_HANDLE( h ) == type );
512  offset = 0;
513  ++page;
514  }
515  }
516 
517  return MB_SUCCESS;
518 }
519 
520 ErrorCode BitTag::get_memory_use( const SequenceManager*, unsigned long& total, unsigned long& per_entity ) const
521 {
522  per_entity = ( storedBitsPerEntity > 4 ); // Cannot return fraction of bytes, so round
523  total = 0;
524  for( EntityType t = (EntityType)0; t < MBMAXTYPE; ++t )
525  {
526  total += pageList[t].capacity() * sizeof( BitPage* );
527  for( size_t i = 0; i < pageList[t].size(); ++i )
528  if( pageList[t][i] ) total += sizeof( BitPage );
529  }
530 
531  return MB_SUCCESS;
532 }
533 
535 {
536  EntityType type;
537  size_t page;
538  int offset;
539  unpack( h, type, page, offset );
540  return page < pageList[type].size() && pageList[type][page];
541 }
542 
543 } // namespace moab