![]() |
Mesh Oriented datABase
(version 5.4.1)
Array-based unstructured mesh datastructure
|
00001 #include "BitTag.hpp"
00002 #include "BitPage.hpp"
00003 #include "moab/Range.hpp"
00004 #include "TagCompare.hpp"
00005 #include "SequenceManager.hpp"
00006 #include "moab/Error.hpp"
00007 #include "moab/ErrorHandler.hpp"
00008 #include
00009 #include
00010
00011 namespace moab
00012 {
00013
00014 BitTag::~BitTag()
00015 {
00016 release_all_data( 0, 0, true );
00017 }
00018
00019 TagType BitTag::get_storage_type() const
00020 {
00021 return MB_TAG_BIT;
00022 }
00023
00024 BitTag* BitTag::create_tag( const char* name, int size, const void* default_value )
00025 {
00026 BitTag* result = new BitTag( name, size, default_value );
00027 if( MB_SUCCESS != result->reserve( size ) )
00028 {
00029 delete result;
00030 result = NULL;
00031 }
00032
00033 return result;
00034 }
00035
00036 ErrorCode BitTag::reserve( unsigned bits )
00037 {
00038 if( bits > 8 ) return MB_FAILURE;
00039
00040 requestedBitsPerEntity = bits;
00041 // Store smallest power of two greater than or
00042 // equal to the number of bits
00043 storedBitsPerEntity = 1;
00044 unsigned ln2storedbits = 0;
00045 while( storedBitsPerEntity < bits )
00046 {
00047 storedBitsPerEntity *= 2;
00048 ++ln2storedbits;
00049 }
00050
00051 // pageShift = log2(ents_per_page())
00052 // = log2(8 * pageSize / storedBitsPerEntity )
00053 // = log2(8) + log2(pageSize) - log2(storedBitsPerEntity)
00054 // = 3 + Ln2PageSize - ln2storedbits;
00055 pageShift = 3 + Ln2PageSize - ln2storedbits;
00056
00057 return MB_SUCCESS;
00058 }
00059
00060 ErrorCode BitTag::release_all_data( SequenceManager*, Error*, bool )
00061 {
00062 for( EntityType t = (EntityType)0; t != MBMAXTYPE; ++t )
00063 {
00064 for( size_t i = 0; i < pageList[t].size(); ++i )
00065 delete pageList[t][i];
00066 pageList[t].clear();
00067 }
00068
00069 return MB_SUCCESS;
00070 }
00071
00072 ErrorCode BitTag::get_data( const SequenceManager*,
00073 Error*,
00074 const EntityHandle* handles,
00075 size_t num_handles,
00076 void* gen_data ) const
00077 {
00078 EntityType type;
00079 size_t page;
00080 int offset;
00081 unsigned char def = default_val();
00082 unsigned char* data = reinterpret_cast< unsigned char* >( gen_data );
00083 for( size_t i = 0; i < num_handles; ++i )
00084 {
00085 unpack( handles[i], type, page, offset );
00086 if( pageList[type].size() <= page || !pageList[type][page] )
00087 data[i] = def;
00088 else
00089 data[i] = pageList[type][page]->get_bits( offset, storedBitsPerEntity );
00090 }
00091
00092 return MB_SUCCESS;
00093 }
00094
00095 ErrorCode BitTag::set_data( SequenceManager* seqman,
00096 Error* /* error */,
00097 const EntityHandle* handles,
00098 size_t num_handles,
00099 const void* gen_data )
00100 {
00101 ErrorCode rval = seqman->check_valid_entities( NULL, handles, num_handles, true );MB_CHK_ERR( rval );
00102
00103 EntityType type;
00104 size_t page;
00105 int offset;
00106 const unsigned char* data = reinterpret_cast< const unsigned char* >( gen_data );
00107 for( size_t i = 0; i < num_handles; ++i )
00108 {
00109 unpack( handles[i], type, page, offset );
00110 if( pageList[type].size() <= page ) pageList[type].resize( page + 1, 0 );
00111 if( !pageList[type][page] ) pageList[type][page] = new BitPage( storedBitsPerEntity, default_val() );
00112 pageList[type][page]->set_bits( offset, storedBitsPerEntity, data[i] );
00113 }
00114
00115 return MB_SUCCESS;
00116 }
00117
00118 ErrorCode BitTag::clear_data( SequenceManager* seqman,
00119 Error* /* error */,
00120 const EntityHandle* handles,
00121 size_t num_handles,
00122 const void* value_ptr,
00123 int value_len )
00124 {
00125 if( value_len ) return MB_INVALID_SIZE;
00126
00127 ErrorCode rval = seqman->check_valid_entities( NULL, handles, num_handles, true );MB_CHK_ERR( rval );
00128
00129 EntityType type;
00130 size_t page;
00131 int offset;
00132 const unsigned char value = *reinterpret_cast< const unsigned char* >( value_ptr );
00133 for( size_t i = 0; i < num_handles; ++i )
00134 {
00135 unpack( handles[i], type, page, offset );
00136 if( pageList[type].size() <= page ) pageList[type].resize( page + 1, 0 );
00137 if( !pageList[type][page] ) pageList[type][page] = new BitPage( storedBitsPerEntity, default_val() );
00138 pageList[type][page]->set_bits( offset, storedBitsPerEntity, value );
00139 }
00140
00141 return MB_SUCCESS;
00142 }
00143
00144 ErrorCode BitTag::remove_data( SequenceManager*, Error*, const EntityHandle* handles, size_t num_handles )
00145 {
00146 EntityType type;
00147 size_t page;
00148 int offset;
00149 const unsigned char val = default_val();
00150 for( size_t i = 0; i < num_handles; ++i )
00151 {
00152 unpack( handles[i], type, page, offset );
00153 if( pageList[type].size() > page && pageList[type][page] )
00154 pageList[type][page]->set_bits( offset, storedBitsPerEntity, val );
00155 }
00156
00157 return MB_SUCCESS;
00158 }
00159
00160 ErrorCode BitTag::get_data( const SequenceManager*, Error*, const Range& handles, void* gen_data ) const
00161 {
00162 EntityType type;
00163 EntityID count;
00164 size_t page;
00165 int offset, per_page = ents_per_page();
00166 unsigned char def = default_val();
00167 unsigned char* data = reinterpret_cast< unsigned char* >( gen_data );
00168 Range::const_pair_iterator i;
00169 for( i = handles.const_pair_begin(); i != handles.const_pair_end(); ++i )
00170 {
00171 unpack( i->first, type, page, offset );
00172 assert( TYPE_FROM_HANDLE( i->second ) == type ); // Should be true because id of zero is never used
00173 count = i->second - i->first + 1;
00174 if( page >= pageList[type].size() )
00175 {
00176 memset( data, def, count );
00177 data += count;
00178 continue;
00179 }
00180
00181 while( count )
00182 {
00183 size_t pcount = std::min( (EntityID)( per_page - offset ), count );
00184 if( pageList[type][page] )
00185 pageList[type][page]->get_bits( offset, pcount, storedBitsPerEntity, data );
00186 else
00187 memset( data, def, pcount );
00188 data += pcount;
00189 count -= pcount;
00190 offset = 0;
00191 ++page;
00192 }
00193 }
00194
00195 return MB_SUCCESS;
00196 }
00197
00198 ErrorCode BitTag::set_data( SequenceManager* seqman, Error* /* error */, const Range& handles, const void* gen_data )
00199 {
00200 ErrorCode rval = seqman->check_valid_entities( NULL, handles );MB_CHK_ERR( rval );
00201
00202 EntityType type;
00203 EntityID count;
00204 size_t page;
00205 int offset, per_page = ents_per_page();
00206 unsigned char def = default_val();
00207 const unsigned char* data = reinterpret_cast< const unsigned char* >( gen_data );
00208 Range::const_pair_iterator i;
00209 for( i = handles.const_pair_begin(); i != handles.const_pair_end(); ++i )
00210 {
00211 unpack( i->first, type, page, offset );
00212 assert( TYPE_FROM_HANDLE( i->second ) == type ); // Should be true because id of zero is never used
00213 count = i->second - i->first + 1;
00214
00215 while( count )
00216 {
00217 if( page >= pageList[type].size() ) pageList[type].resize( page + 1, 0 );
00218 if( !pageList[type][page] ) pageList[type][page] = new BitPage( storedBitsPerEntity, def );
00219
00220 size_t pcount = std::min( (EntityID)( per_page - offset ), count );
00221 pageList[type][page]->set_bits( offset, pcount, storedBitsPerEntity, data );
00222 data += pcount;
00223 count -= pcount;
00224 offset = 0;
00225 ++page;
00226 }
00227 }
00228
00229 return MB_SUCCESS;
00230 }
00231
00232 ErrorCode BitTag::clear_data( SequenceManager* seqman,
00233 Error* /* error */,
00234 const Range& handles,
00235 const void* value_ptr,
00236 int value_len )
00237 {
00238 if( value_len ) return MB_INVALID_SIZE;
00239
00240 ErrorCode rval = seqman->check_valid_entities( NULL, handles );MB_CHK_ERR( rval );
00241
00242 EntityType type;
00243 EntityID count;
00244 size_t page;
00245 int offset, per_page = ents_per_page();
00246 const unsigned char value = *reinterpret_cast< const unsigned char* >( value_ptr );
00247 Range::const_pair_iterator i;
00248 for( i = handles.const_pair_begin(); i != handles.const_pair_end(); ++i )
00249 {
00250 unpack( i->first, type, page, offset );
00251 assert( TYPE_FROM_HANDLE( i->second ) == type ); // Should be true because id of zero is never used
00252 count = i->second - i->first + 1;
00253
00254 while( count )
00255 {
00256 if( page >= pageList[type].size() ) pageList[type].resize( page + 1, 0 );
00257 if( !pageList[type][page] ) pageList[type][page] = new BitPage( storedBitsPerEntity, default_val() );
00258
00259 size_t pcount = std::min( (EntityID)( per_page - offset ), count );
00260 pageList[type][page]->set_bits( offset, pcount, storedBitsPerEntity, value );
00261 count -= pcount;
00262 offset = 0;
00263 ++page;
00264 }
00265 }
00266
00267 return MB_SUCCESS;
00268 }
00269
00270 ErrorCode BitTag::remove_data( SequenceManager*, Error*, const Range& handles )
00271 {
00272 EntityType type;
00273 EntityID count;
00274 size_t page;
00275 int offset, per_page = ents_per_page();
00276 unsigned char val = default_val();
00277 Range::const_pair_iterator i;
00278 for( i = handles.const_pair_begin(); i != handles.const_pair_end(); ++i )
00279 {
00280 unpack( i->first, type, page, offset );
00281 assert( TYPE_FROM_HANDLE( i->second ) == type ); // Should be true because id of zero is never used
00282 count = i->second - i->first + 1;
00283
00284 while( count )
00285 {
00286 size_t pcount = std::min( (EntityID)( per_page - offset ), count );
00287 if( page < pageList[type].size() && pageList[type][page] )
00288 pageList[type][page]->set_bits( offset, pcount, storedBitsPerEntity, val );
00289 count -= pcount;
00290 offset = 0;
00291 ++page;
00292 }
00293 }
00294
00295 return MB_SUCCESS;
00296 }
00297
00298 ErrorCode BitTag::get_data( const SequenceManager*,
00299 Error* /* error */,
00300 const EntityHandle*,
00301 size_t,
00302 const void**,
00303 int* ) const
00304 {
00305 MB_SET_ERR( MB_TYPE_OUT_OF_RANGE, "Operation get_data not supported for bit tags" );
00306 }
00307
00308 ErrorCode BitTag::get_data( const SequenceManager*, Error* /* error */, const Range&, const void**, int* ) const
00309 {
00310 MB_SET_ERR( MB_TYPE_OUT_OF_RANGE, "Operation get_data not supported for bit tags" );
00311 }
00312
00313 ErrorCode BitTag::set_data( SequenceManager*,
00314 Error* /* error */,
00315 const EntityHandle*,
00316 size_t,
00317 void const* const*,
00318 const int* )
00319 {
00320 MB_SET_ERR( MB_TYPE_OUT_OF_RANGE, "Operation set_data not supported for bit tags" );
00321 }
00322
00323 ErrorCode BitTag::set_data( SequenceManager*, Error* /* error */, const Range&, void const* const*, const int* )
00324 {
00325 MB_SET_ERR( MB_TYPE_OUT_OF_RANGE, "Operation set_data not supported for bit tags" );
00326 }
00327
00328 ErrorCode BitTag::tag_iterate( SequenceManager*,
00329 Error* /* error */,
00330 Range::iterator&,
00331 const Range::iterator&,
00332 void*&,
00333 bool )
00334 {
00335 MB_SET_ERR( MB_TYPE_OUT_OF_RANGE, "Operation tag_iterate not supported for bit tags" );
00336 }
00337
00338 template < class Container >
00339 inline void BitTag::get_tagged( EntityType type, Container& entities ) const
00340 {
00341 std::pair< EntityType, EntityType > r = type_range( type );
00342 typename Container::iterator hint = entities.begin();
00343 const int per_page = ents_per_page();
00344 for( EntityType t = r.first; t != r.second; ++t )
00345 {
00346 for( size_t i = 0; i < pageList[t].size(); ++i )
00347 {
00348 if( pageList[t][i] )
00349 {
00350 EntityID id = i * per_page;
00351 EntityHandle h = CREATE_HANDLE( t, id );
00352 EntityHandle last = h + per_page - 1;
00353 // Never zero ID
00354 if( 0 == id ) ++h;
00355 hint = entities.insert( hint, h, last );
00356 }
00357 }
00358 }
00359 }
00360
00361 template < class Container >
00362 inline void BitTag::get_tagged( Range::const_iterator begin, Range::const_iterator end, Container& entities ) const
00363 {
00364 EntityType type;
00365 EntityID count;
00366 size_t page;
00367 int offset, per_page = ents_per_page();
00368 typename Container::iterator hint = entities.begin();
00369 EntityHandle h;
00370 Range::const_iterator i = begin;
00371 while( i != end )
00372 {
00373 h = *i;
00374 unpack( h, type, page, offset );
00375
00376 i = i.end_of_block();
00377 count = *i - h + 1;
00378 ++i;
00379 while( count > 0 )
00380 {
00381 EntityID pcount = std::min( count, (EntityID)( per_page - offset ) );
00382 if( page < pageList[type].size() && pageList[type][page] )
00383 hint = entities.insert( hint, h, h + pcount - 1 );
00384
00385 count -= pcount;
00386 h += pcount;
00387 assert( TYPE_FROM_HANDLE( h ) == type );
00388 offset = 0;
00389 ++page;
00390 }
00391 }
00392 }
00393
00394 template < class Container >
00395 inline void BitTag::get_tagged( Container& entities, EntityType type, const Range* intersect ) const
00396
00397 {
00398 if( !intersect )
00399 get_tagged< Container >( type, entities );
00400 else if( MBMAXTYPE == type )
00401 get_tagged< Container >( intersect->begin(), intersect->end(), entities );
00402 else
00403 {
00404 std::pair< Range::iterator, Range::iterator > r = intersect->equal_range( type );
00405 get_tagged< Container >( r.first, r.second, entities );
00406 }
00407 }
00408
00409 ErrorCode BitTag::get_tagged_entities( const SequenceManager*,
00410 Range& entities,
00411 EntityType type,
00412 const Range* intersect ) const
00413 {
00414 get_tagged< Range >( entities, type, intersect );
00415 return MB_SUCCESS;
00416 }
00417
00418 ErrorCode BitTag::num_tagged_entities( const SequenceManager*,
00419 size_t& count,
00420 EntityType type,
00421 const Range* intersect ) const
00422 {
00423 InsertCount counter( count );
00424 get_tagged< InsertCount >( counter, type, intersect );
00425 count = counter.end();
00426 return MB_SUCCESS;
00427 }
00428
00429 ErrorCode BitTag::find_entities_with_value( const SequenceManager*,
00430 Error* /* error */,
00431 Range& output_entities,
00432 const void* value,
00433 int value_bytes,
00434 EntityType type,
00435 const Range* intersect_entities ) const
00436 {
00437 if( value_bytes && value_bytes != 1 )
00438 {
00439 MB_SET_ERR( MB_INVALID_SIZE, "Invalid tag size for bit tag: " << value_bytes << " bytes" );
00440 }
00441
00442 const signed char bits = *reinterpret_cast< const unsigned char* >( value );
00443 if( intersect_entities )
00444 return get_entities_with_bits( *intersect_entities, type, output_entities, bits );
00445 else
00446 return get_entities_with_bits( type, output_entities, bits );
00447 }
00448
00449 ErrorCode BitTag::get_entities_with_bits( EntityType type, Range& entities, unsigned char bits ) const
00450 {
00451 std::pair< EntityType, EntityType > r = type_range( type );
00452 const int per_page = ents_per_page();
00453 for( EntityType t = r.first; t != r.second; ++t )
00454 {
00455 for( size_t i = 0; i < pageList[t].size(); ++i )
00456 {
00457 if( pageList[t][i] )
00458 {
00459 EntityID id = i * per_page;
00460 EntityHandle h = CREATE_HANDLE( t, id );
00461 int off = !i; // Never zero ID
00462 pageList[t][i]->search( bits, off, per_page - off, storedBitsPerEntity, entities, h + off );
00463 }
00464 }
00465 }
00466
00467 return MB_SUCCESS;
00468 }
00469
00470 ErrorCode BitTag::get_entities_with_bits( const Range& range,
00471 EntityType in_type,
00472 Range& entities,
00473 unsigned char bits ) const
00474 {
00475 if( MBMAXTYPE == in_type )
00476 {
00477 ErrorCode rval;
00478 for( --in_type; in_type >= MBVERTEX; --in_type )
00479 {
00480 rval = get_entities_with_bits( range, in_type, entities, bits );MB_CHK_ERR( rval );
00481 }
00482 return MB_SUCCESS;
00483 }
00484
00485 EntityType type;
00486 EntityID count;
00487 size_t page;
00488 int offset, per_page = ents_per_page();
00489 Range::const_iterator i, end;
00490 std::pair< Range::iterator, Range::iterator > r = range.equal_range( in_type );
00491 i = r.first;
00492 end = r.second;
00493 EntityHandle h;
00494 while( i != end )
00495 {
00496 h = *i;
00497 unpack( h, type, page, offset );
00498 assert( MBMAXTYPE == in_type || type == in_type );
00499
00500 i = i.end_of_block();
00501 count = *i - h + 1;
00502 ++i;
00503 while( count > 0 )
00504 {
00505 EntityID pcount = std::min( count, (EntityID)( per_page - offset ) );
00506 if( page < pageList[type].size() && pageList[type][page] )
00507 pageList[type][page]->search( bits, offset, pcount, storedBitsPerEntity, entities, h );
00508
00509 count -= pcount;
00510 h += pcount;
00511 assert( TYPE_FROM_HANDLE( h ) == type );
00512 offset = 0;
00513 ++page;
00514 }
00515 }
00516
00517 return MB_SUCCESS;
00518 }
00519
00520 ErrorCode BitTag::get_memory_use( const SequenceManager*, unsigned long& total, unsigned long& per_entity ) const
00521 {
00522 per_entity = ( storedBitsPerEntity > 4 ); // Cannot return fraction of bytes, so round
00523 total = 0;
00524 for( EntityType t = (EntityType)0; t < MBMAXTYPE; ++t )
00525 {
00526 total += pageList[t].capacity() * sizeof( BitPage* );
00527 for( size_t i = 0; i < pageList[t].size(); ++i )
00528 if( pageList[t][i] ) total += sizeof( BitPage );
00529 }
00530
00531 return MB_SUCCESS;
00532 }
00533
00534 bool BitTag::is_tagged( const SequenceManager*, EntityHandle h ) const
00535 {
00536 EntityType type;
00537 size_t page;
00538 int offset;
00539 unpack( h, type, page, offset );
00540 return page < pageList[type].size() && pageList[type][page];
00541 }
00542
00543 } // namespace moab