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 <cstdlib> 00009 #include <cstring> 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