![]() |
Mesh Oriented datABase
(version 5.4.1)
Array-based unstructured mesh datastructure
|
00001 /**
00002 * MOAB, a Mesh-Oriented datABase, is a software component for creating,
00003 * storing and accessing finite element mesh data.
00004 *
00005 * Copyright 2004 Sandia Corporation. Under the terms of Contract
00006 * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government
00007 * retains certain rights in this software.
00008 *
00009 * This library is free software; you can redistribute it and/or
00010 * modify it under the terms of the GNU Lesser General Public
00011 * License as published by the Free Software Foundation; either
00012 * version 2.1 of the License, or (at your option) any later version.
00013 *
00014 */
00015
00016 /****************************************************
00017 * File : Range.cpp
00018 *
00019 * Purpose : Stores contiguous or partially
00020 * contiguous values in an optimized
00021 * fashion. Partially contiguous
00022 * accessing patterns is also optimized.
00023 *
00024 * Creator : Clinton Stimpson
00025 *
00026 * Date : 15 April 2002
00027 *
00028 *******************************************************/
00029
00030 #include
00031 #include "moab/Range.hpp"
00032 #include "Internals.hpp"
00033 #include "moab/CN.hpp"
00034 #include
00035 #include
00036 #include
00037
00038 #ifdef HAVE_BOOST_POOL_SINGLETON_POOL_HPP
00039 #include
00040 typedef boost::singleton_pool< moab::Range::PairNode, sizeof( moab::Range::PairNode ) > PairAlloc;
00041 // static inline moab::Range::PairNode* alloc_pair()
00042 // { return new (PairAlloc::malloc()) moab::Range::PairNode; }
00043 static inline moab::Range::PairNode* alloc_pair( moab::Range::PairNode* n,
00044 moab::Range::PairNode* p,
00045 moab::EntityHandle f,
00046 moab::EntityHandle s )
00047 {
00048 return new( PairAlloc::malloc() ) moab::Range::PairNode( n, p, f, s );
00049 }
00050 static inline void free_pair( moab::Range::PairNode* node )
00051 {
00052 node->~PairNode();
00053 PairAlloc::free( node );
00054 }
00055 #else
00056 // static inline moab::Range::PairNode* alloc_pair()
00057 // { return new moab::Range::PairNode; }
00058 static inline moab::Range::PairNode* alloc_pair( moab::Range::PairNode* n,
00059 moab::Range::PairNode* p,
00060 moab::EntityHandle f,
00061 moab::EntityHandle s )
00062 {
00063 return new moab::Range::PairNode( n, p, f, s );
00064 }
00065 static inline void free_pair( moab::Range::PairNode* node )
00066 {
00067 delete node;
00068 }
00069 #endif
00070
00071 namespace moab
00072 {
00073
00074 /*!
00075 returns the number of values this list represents
00076 */
00077 size_t Range::size() const
00078 {
00079 // go through each pair and add up the number of values
00080 // we have.
00081 size_t sz = 0;
00082 for( PairNode* iter = mHead.mNext; iter != &mHead; iter = iter->mNext )
00083 {
00084 sz += ( ( iter->second - iter->first ) + 1 );
00085 }
00086 return sz;
00087 }
00088
00089 /*!
00090 advance iterator
00091 */
00092 Range::const_iterator& Range::const_iterator::operator+=( EntityID sstep )
00093 {
00094 // Check negative now to avoid infinite loop below.
00095 if( sstep < 0 )
00096 {
00097 return operator-=( -sstep );
00098 }
00099 EntityHandle step = sstep;
00100
00101 // Handle current PairNode. Either step is within the current
00102 // node or need to remove the remainder of the current node
00103 // from step.
00104 EntityHandle this_node_rem = mNode->second - mValue;
00105 if( this_node_rem >= step )
00106 {
00107 mValue += step;
00108 return *this;
00109 }
00110 step -= this_node_rem + 1;
00111
00112 // For each node we are stepping past, decrement step
00113 // by the size of the node.
00114 PairNode* node = mNode->mNext;
00115 EntityHandle node_size = node->second - node->first + 1;
00116 while( step >= node_size )
00117 {
00118 step -= node_size;
00119 node = node->mNext;
00120 node_size = node->second - node->first + 1;
00121 }
00122
00123 // Advance into the resulting node by whatever is
00124 // left in step.
00125 mNode = node;
00126 mValue = mNode->first + step;
00127 return *this;
00128 }
00129
00130 /*!
00131 regress iterator
00132 */
00133 Range::const_iterator& Range::const_iterator::operator-=( EntityID sstep )
00134 {
00135 // Check negative now to avoid infinite loop below.
00136 if( sstep < 0 )
00137 {
00138 return operator+=( -sstep );
00139 }
00140 EntityHandle step = sstep;
00141
00142 // Handle current PairNode. Either step is within the current
00143 // node or need to remove the remainder of the current node
00144 // from step.
00145 EntityHandle this_node_rem = mValue - mNode->first;
00146 if( this_node_rem >= step )
00147 {
00148 mValue -= step;
00149 return *this;
00150 }
00151 step -= this_node_rem + 1;
00152
00153 // For each node we are stepping past, decrement step
00154 // by the size of the node.
00155 PairNode* node = mNode->mPrev;
00156 EntityHandle node_size = node->second - node->first + 1;
00157 while( step >= node_size )
00158 {
00159 step -= node_size;
00160 node = node->mPrev;
00161 node_size = node->second - node->first + 1;
00162 }
00163
00164 // Advance into the resulting node by whatever is
00165 // left in step.
00166 mNode = node;
00167 mValue = mNode->second - step;
00168 return *this;
00169 }
00170
00171 //! another constructor that takes an initial range
00172 Range::Range( EntityHandle val1, EntityHandle val2 )
00173 {
00174 mHead.mNext = mHead.mPrev = alloc_pair( &mHead, &mHead, val1, val2 );
00175 mHead.first = mHead.second = 0;
00176 }
00177
00178 //! copy constructor
00179 Range::Range( const Range& copy )
00180 {
00181 // set the head node to point to itself
00182 mHead.mNext = mHead.mPrev = &mHead;
00183 mHead.first = mHead.second = 0;
00184
00185 const PairNode* copy_node = copy.mHead.mNext;
00186 PairNode* new_node = &mHead;
00187 for( ; copy_node != &( copy.mHead ); copy_node = copy_node->mNext )
00188 {
00189 PairNode* tmp_node = alloc_pair( new_node->mNext, new_node, copy_node->first, copy_node->second );
00190 new_node->mNext->mPrev = tmp_node;
00191 new_node->mNext = tmp_node;
00192 new_node = tmp_node;
00193 }
00194 }
00195
00196 //! clears the contents of the list
00197 void Range::clear()
00198 {
00199 PairNode* tmp_node = mHead.mNext;
00200 while( tmp_node != &mHead )
00201 {
00202 PairNode* to_delete = tmp_node;
00203 tmp_node = tmp_node->mNext;
00204 free_pair( to_delete );
00205 }
00206 mHead.mNext = &mHead;
00207 mHead.mPrev = &mHead;
00208 }
00209
00210 Range& Range::operator=( const Range& copy )
00211 {
00212 clear();
00213 const PairNode* copy_node = copy.mHead.mNext;
00214 PairNode* new_node = &mHead;
00215 for( ; copy_node != &( copy.mHead ); copy_node = copy_node->mNext )
00216 {
00217 PairNode* tmp_node = alloc_pair( new_node->mNext, new_node, copy_node->first, copy_node->second );
00218 new_node->mNext->mPrev = tmp_node;
00219 new_node->mNext = tmp_node;
00220 new_node = tmp_node;
00221 }
00222 return *this;
00223 }
00224
00225 /*!
00226 inserts a single value into this range
00227 */
00228
00229 Range::iterator Range::insert( Range::iterator hint, EntityHandle val )
00230 {
00231 // don't allow zero-valued handles in Range
00232 if( val == 0 ) return end();
00233
00234 // if this is empty, just add it and return an iterator to it
00235 if( &mHead == mHead.mNext )
00236 {
00237 mHead.mNext = mHead.mPrev = alloc_pair( &mHead, &mHead, val, val );
00238 return iterator( mHead.mNext, val );
00239 }
00240
00241 // find the location in the list where we can safely insert
00242 // new items and keep it ordered
00243 PairNode* hter = hint.mNode;
00244 PairNode* jter = hter->first <= val ? hter : mHead.mNext;
00245 for( ; ( jter != &mHead ) && ( jter->second < val ); jter = jter->mNext )
00246 ;
00247 PairNode* iter = jter;
00248 jter = jter->mPrev;
00249
00250 // if this val is already in the list
00251 if( ( iter->first <= val && iter->second >= val ) && ( iter != &mHead ) )
00252 {
00253 // return an iterator pointing to this location
00254 return iterator( iter, val );
00255 }
00256
00257 // one of a few things can happen at this point
00258 // 1. this range needs to be backwardly extended
00259 // 2. the previous range needs to be forwardly extended
00260 // 3. a new range needs to be added
00261
00262 // extend this range back a bit
00263 else if( ( iter->first == ( val + 1 ) ) && ( iter != &mHead ) )
00264 {
00265 iter->first = val;
00266 // see if we need to merge two ranges
00267 if( ( iter != mHead.mNext ) && ( jter->second == ( val - 1 ) ) )
00268 {
00269 jter->second = iter->second;
00270 iter->mPrev->mNext = iter->mNext;
00271 iter->mNext->mPrev = iter->mPrev;
00272 free_pair( iter );
00273 return iterator( jter, val );
00274 }
00275 else
00276 {
00277 return iterator( iter, val );
00278 }
00279 }
00280 // extend the previous range forward a bit
00281 else if( ( jter->second == ( val - 1 ) ) && ( iter != mHead.mNext ) )
00282 {
00283 jter->second = val;
00284 return iterator( jter, val );
00285 }
00286 // make a new range
00287 else
00288 {
00289 PairNode* new_node = alloc_pair( iter, iter->mPrev, val, val );
00290 iter->mPrev = new_node->mPrev->mNext = new_node;
00291 return iterator( new_node, val );
00292 }
00293 }
00294
00295 Range::iterator Range::insert( Range::iterator prev, EntityHandle val1, EntityHandle val2 )
00296 {
00297 if( val1 == 0 || val1 > val2 ) return end();
00298
00299 // Empty
00300 if( mHead.mNext == &mHead )
00301 {
00302 assert( prev == end() );
00303 PairNode* new_node = alloc_pair( &mHead, &mHead, val1, val2 );
00304 mHead.mNext = mHead.mPrev = new_node;
00305 return iterator( mHead.mNext, val1 );
00306 }
00307
00308 PairNode* iter = prev.mNode;
00309 // If iterator is at end, set it to last.
00310 // Thus if the hint was to append, we start searching
00311 // at the end of the list.
00312 if( iter == &mHead ) iter = mHead.mPrev;
00313 // if hint (prev) is past insert position, reset it to the beginning.
00314 if( iter != &mHead && iter->first > val2 + 1 ) iter = mHead.mNext;
00315
00316 // If hint is bogus then search backwards
00317 while( iter != mHead.mNext && iter->mPrev->second >= val1 - 1 )
00318 iter = iter->mPrev;
00319
00320 // Input range is before beginning?
00321 if( iter->mPrev == &mHead && val2 < iter->first - 1 )
00322 {
00323 PairNode* new_node = alloc_pair( iter, &mHead, val1, val2 );
00324 mHead.mNext = iter->mPrev = new_node;
00325 return iterator( mHead.mNext, val1 );
00326 }
00327
00328 // Find first intersecting list entry, or the next entry
00329 // if none intersects.
00330 while( iter != &mHead && iter->second + 1 < val1 )
00331 iter = iter->mNext;
00332
00333 // Need to insert new pair (don't intersect any existing pair)?
00334 if( iter == &mHead || iter->first - 1 > val2 )
00335 {
00336 PairNode* new_node = alloc_pair( iter, iter->mPrev, val1, val2 );
00337 iter->mPrev = iter->mPrev->mNext = new_node;
00338 return iterator( iter->mPrev, val1 );
00339 }
00340
00341 // Make the first intersecting pair the union of itself with [val1,val2]
00342 if( iter->first > val1 ) iter->first = val1;
00343 if( iter->second >= val2 ) return iterator( iter, val1 );
00344 iter->second = val2;
00345
00346 // Merge any remaining pairs that intersect [val1,val2]
00347 while( iter->mNext != &mHead && iter->mNext->first <= val2 + 1 )
00348 {
00349 PairNode* dead = iter->mNext;
00350 iter->mNext = dead->mNext;
00351 dead->mNext->mPrev = iter;
00352
00353 if( dead->second > val2 ) iter->second = dead->second;
00354 free_pair( dead );
00355 }
00356
00357 return iterator( iter, val1 );
00358 }
00359
00360 /*!
00361 erases an item from this list and returns an iterator to the next item
00362 */
00363
00364 Range::iterator Range::erase( iterator iter )
00365 {
00366 // one of a few things could happen
00367 // 1. shrink a range
00368 // 2. split a range
00369 // 3. remove a range
00370
00371 if( iter == end() ) return end();
00372
00373 // the iterator most likely to be returned
00374 iterator new_iter = iter;
00375 ++new_iter;
00376
00377 PairNode* kter = iter.mNode;
00378
00379 // just remove the range
00380 if( kter->first == kter->second )
00381 {
00382 kter->mNext->mPrev = kter->mPrev;
00383 kter->mPrev->mNext = kter->mNext;
00384 free_pair( kter );
00385 return new_iter;
00386 }
00387 // shrink it
00388 else if( kter->first == iter.mValue )
00389 {
00390 kter->first++;
00391 return new_iter;
00392 }
00393 // shrink it the other way
00394 else if( kter->second == iter.mValue )
00395 {
00396 kter->second--;
00397 return new_iter;
00398 }
00399 // split the range
00400 else
00401 {
00402 PairNode* new_node = alloc_pair( iter.mNode->mNext, iter.mNode, iter.mValue + 1, kter->second );
00403 new_node->mPrev->mNext = new_node->mNext->mPrev = new_node;
00404 iter.mNode->second = iter.mValue - 1;
00405 new_iter = const_iterator( new_node, new_node->first );
00406 return new_iter;
00407 }
00408 }
00409
00410 //! remove a range of items from the list
00411 Range::iterator Range::erase( iterator iter1, iterator iter2 )
00412 {
00413 iterator result;
00414
00415 if( iter1.mNode == iter2.mNode )
00416 {
00417 if( iter2.mValue <= iter1.mValue )
00418 {
00419 // empty range OK, otherwise invalid input
00420 return iter2;
00421 }
00422
00423 // If both iterators reference the same pair node, then
00424 // we're either removing values from the front of the
00425 // node or splitting the node. We can never be removing
00426 // the last value in the node in this case because iter2
00427 // points *after* the last entry to be removed.
00428
00429 PairNode* node = iter1.mNode;
00430 if( iter1.mValue == node->first )
00431 {
00432 node->first = iter2.mValue;
00433 result = iter2;
00434 }
00435 else
00436 {
00437 PairNode* new_node = alloc_pair( node->mNext, node, iter2.mValue, node->second );
00438 new_node->mNext->mPrev = new_node;
00439 new_node->mPrev->mNext = new_node;
00440 node->second = iter1.mValue - 1;
00441 result = iterator( new_node, new_node->first );
00442 }
00443 }
00444 else
00445 {
00446 if( iter1.mNode == &mHead ) return iter1;
00447 PairNode* dn = iter1.mNode;
00448 if( iter1.mValue > dn->first )
00449 {
00450 dn->second = iter1.mValue - 1;
00451 dn = dn->mNext;
00452 }
00453 if( iter2.mNode != &mHead ) iter2.mNode->first = iter2.mValue;
00454 while( dn != iter2.mNode )
00455 {
00456 PairNode* dead = dn;
00457 dn = dn->mNext;
00458
00459 dead->mPrev->mNext = dead->mNext;
00460 dead->mNext->mPrev = dead->mPrev;
00461 // dead->mPrev = dead->mNext = 0;
00462 delete_pair_node( dead );
00463 }
00464
00465 result = iter2;
00466 }
00467
00468 return result;
00469 }
00470
00471 void Range::delete_pair_node( PairNode* node )
00472 {
00473 if( node != &mHead )
00474 { // pop_front() and pop_back() rely on this check
00475 node->mPrev->mNext = node->mNext;
00476 node->mNext->mPrev = node->mPrev;
00477 free_pair( node );
00478 }
00479 }
00480
00481 //! remove first entity from range
00482 EntityHandle Range::pop_front()
00483 {
00484 EntityHandle retval = front();
00485 if( mHead.mNext->first == mHead.mNext->second ) // need to remove pair from range
00486 delete_pair_node( mHead.mNext );
00487 else
00488 ++( mHead.mNext->first ); // otherwise just adjust start value of pair
00489
00490 return retval;
00491 }
00492
00493 //! remove last entity from range
00494 EntityHandle Range::pop_back()
00495 {
00496 EntityHandle retval = back();
00497 if( mHead.mPrev->first == mHead.mPrev->second ) // need to remove pair from range
00498 delete_pair_node( mHead.mPrev );
00499 else
00500 --( mHead.mPrev->second ); // otherwise just adjust end value of pair
00501
00502 return retval;
00503 }
00504
00505 /*!
00506 finds a value in the list.
00507 this method is preferred over other algorithms because
00508 it can be found faster this way.
00509 */
00510 Range::const_iterator Range::find( EntityHandle val ) const
00511 {
00512 // iterator through the list
00513 PairNode* iter = mHead.mNext;
00514 for( ; iter != &mHead && ( val > iter->second ); iter = iter->mNext )
00515 ;
00516 return ( ( iter->second >= val ) && ( iter->first <= val ) ) ? const_iterator( iter, val ) : end();
00517 }
00518
00519 /*!
00520 merges another Range with this one
00521 */
00522
00523 void Range::insert( Range::const_iterator begini, Range::const_iterator endi )
00524 {
00525 if( begini == endi ) return;
00526
00527 PairNode* node = begini.mNode;
00528 if( endi.mNode == node )
00529 {
00530 insert( *begini, ( *endi ) - 1 );
00531 return;
00532 }
00533
00534 Range::iterator hint = insert( *begini, node->second );
00535 node = node->mNext;
00536 while( node != endi.mNode )
00537 {
00538 hint = insert( hint, node->first, node->second );
00539 node = node->mNext;
00540 }
00541
00542 if( *endi > node->first )
00543 {
00544 if( *endi <= node->second )
00545 insert( hint, node->first, *(endi)-1 );
00546 else
00547 insert( hint, node->first, node->second );
00548 }
00549 }
00550
00551 #include
00552
00553 // checks the range to make sure everything is A-Ok.
00554 void Range::sanity_check() const
00555 {
00556 if( empty() ) return;
00557
00558 const PairNode* node = mHead.mNext;
00559 std::vector< const PairNode* > seen_before;
00560 bool stop_it = false;
00561
00562 for( ; stop_it == false; node = node->mNext )
00563 {
00564 // have we seen this node before?
00565 assert( std::find( seen_before.begin(), seen_before.end(), node ) == seen_before.end() );
00566 seen_before.push_back( node );
00567
00568 // is the connection correct?
00569 assert( node->mNext->mPrev == node );
00570
00571 // are the values right?
00572 assert( node->first <= node->second );
00573 if( node != &mHead && node->mPrev != &mHead ) assert( node->mPrev->second < node->first );
00574
00575 if( node == &mHead ) stop_it = true;
00576 }
00577 }
00578
00579 const std::string Range::str_rep( const char* indent_prefix ) const
00580 {
00581 std::stringstream str_stream;
00582 std::string indent_prefix_str;
00583 if( NULL != indent_prefix )
00584 {
00585 indent_prefix_str += indent_prefix;
00586 }
00587
00588 if( empty() )
00589 {
00590 str_stream << indent_prefix_str << "\tempty" << std::endl;
00591 return str_stream.str().c_str();
00592 }
00593
00594 for( const_pair_iterator i = const_pair_begin(); i != const_pair_end(); ++i )
00595 {
00596 EntityType t1 = TYPE_FROM_HANDLE( i->first );
00597 EntityType t2 = TYPE_FROM_HANDLE( i->second );
00598
00599 str_stream << indent_prefix_str << "\t" << CN::EntityTypeName( t1 ) << " " << ID_FROM_HANDLE( i->first );
00600 if( i->first != i->second )
00601 {
00602 str_stream << " - ";
00603 if( t1 != t2 ) str_stream << CN::EntityTypeName( t2 ) << " ";
00604 str_stream << ID_FROM_HANDLE( i->second );
00605 }
00606 str_stream << std::endl;
00607 }
00608
00609 return str_stream.str();
00610 }
00611
00612 void Range::print( std::ostream& stream, const char* indent_prefix ) const
00613 {
00614 stream << str_rep( indent_prefix );
00615 }
00616
00617 // for debugging
00618 void Range::print( const char* indent_prefix ) const
00619 {
00620 print( std::cout, indent_prefix );
00621 }
00622
00623 // intersect two ranges, placing the results in the return range
00624 #define MAX( a, b ) ( ( a ) < ( b ) ? ( b ) : ( a ) )
00625 #define MIN( a, b ) ( ( a ) > ( b ) ? ( b ) : ( a ) )
00626 Range intersect( const Range& range1, const Range& range2 )
00627 {
00628 Range::const_pair_iterator r_it[2] = { range1.const_pair_begin(), range2.const_pair_begin() };
00629 EntityHandle low_it, high_it;
00630
00631 Range lhs;
00632 Range::iterator hint = lhs.begin();
00633
00634 // terminate the while loop when at least one "start" iterator is at the
00635 // end of the list
00636 while( r_it[0] != range1.end() && r_it[1] != range2.end() )
00637 {
00638
00639 if( r_it[0]->second < r_it[1]->first )
00640 // 1st subrange completely below 2nd subrange
00641 ++r_it[0];
00642 else if( r_it[1]->second < r_it[0]->first )
00643 // 2nd subrange completely below 1st subrange
00644 ++r_it[1];
00645
00646 else
00647 {
00648 // else ranges overlap; first find greater start and lesser end
00649 low_it = MAX( r_it[0]->first, r_it[1]->first );
00650 high_it = MIN( r_it[0]->second, r_it[1]->second );
00651
00652 // insert into result
00653 hint = lhs.insert( hint, low_it, high_it );
00654
00655 // now find bounds of this insertion and increment corresponding iterator
00656 if( high_it == r_it[0]->second ) ++r_it[0];
00657 if( high_it == r_it[1]->second ) ++r_it[1];
00658 }
00659 }
00660
00661 return lhs;
00662 }
00663
00664 Range subtract( const Range& range1, const Range& range2 )
00665 {
00666 const bool braindead = false;
00667
00668 if( braindead )
00669 {
00670 // brain-dead implementation right now
00671 Range res( range1 );
00672 for( Range::const_iterator rit = range2.begin(); rit != range2.end(); ++rit )
00673 res.erase( *rit );
00674
00675 return res;
00676 }
00677 else
00678 {
00679 Range lhs( range1 );
00680
00681 Range::pair_iterator r_it0 = lhs.pair_begin();
00682 Range::const_pair_iterator r_it1 = range2.const_pair_begin();
00683
00684 // terminate the while loop when at least one "start" iterator is at the
00685 // end of the list
00686 while( r_it0 != lhs.end() && r_it1 != range2.end() )
00687 {
00688 // case a: pair wholly within subtracted pair
00689 if( r_it0->first >= r_it1->first && r_it0->second <= r_it1->second )
00690 {
00691 Range::PairNode* rtmp = r_it0.node();
00692 ++r_it0;
00693 lhs.delete_pair_node( rtmp );
00694 }
00695 // case b: pair overlaps upper part of subtracted pair
00696 else if( r_it0->first <= r_it1->second && r_it0->first >= r_it1->first )
00697 {
00698 r_it0->first = r_it1->second + 1;
00699 ++r_it1;
00700 }
00701 // case c: pair overlaps lower part of subtracted pair
00702 else if( r_it0->second >= r_it1->first && r_it0->second <= r_it1->second )
00703 {
00704 r_it0->second = r_it1->first - 1;
00705 ++r_it0;
00706 }
00707 // case d: pair completely surrounds subtracted pair
00708 else if( r_it0->first < r_it1->first && r_it0->second > r_it1->second )
00709 {
00710 Range::PairNode* new_node =
00711 alloc_pair( r_it0.node(), r_it0.node()->mPrev, r_it0->first, r_it1->first - 1 );
00712 new_node->mPrev->mNext = new_node->mNext->mPrev = new_node;
00713 r_it0.node()->first = r_it1->second + 1;
00714 ++r_it1;
00715 }
00716 else
00717 {
00718 while( r_it0->second < r_it1->first && r_it0 != lhs.end() )
00719 ++r_it0;
00720 if( r_it0 == lhs.end() ) break;
00721 while( r_it1->second < r_it0->first && r_it1 != range2.end() )
00722 ++r_it1;
00723 }
00724 }
00725
00726 return lhs;
00727 }
00728 }
00729
00730 Range& Range::operator-=( const Range& range2 )
00731 {
00732 const bool braindead = false;
00733
00734 if( braindead )
00735 {
00736 // brain-dead implementation right now
00737 Range res( *this );
00738 for( Range::const_iterator rit = range2.begin(); rit != range2.end(); ++rit )
00739 res.erase( *rit );
00740
00741 return *this;
00742 }
00743 else
00744 {
00745 Range::pair_iterator r_it0 = this->pair_begin();
00746 Range::const_pair_iterator r_it1 = range2.const_pair_begin();
00747
00748 // terminate the while loop when at least one "start" iterator is at the
00749 // end of the list
00750 while( r_it0 != this->end() && r_it1 != range2.end() )
00751 {
00752 // case a: pair wholly within subtracted pair
00753 if( r_it0->first >= r_it1->first && r_it0->second <= r_it1->second )
00754 {
00755 Range::PairNode* rtmp = r_it0.node();
00756 ++r_it0;
00757 this->delete_pair_node( rtmp );
00758 }
00759 // case b: pair overlaps upper part of subtracted pair
00760 else if( r_it0->first <= r_it1->second && r_it0->first >= r_it1->first )
00761 {
00762 r_it0->first = r_it1->second + 1;
00763 ++r_it1;
00764 }
00765 // case c: pair overlaps lower part of subtracted pair
00766 else if( r_it0->second >= r_it1->first && r_it0->second <= r_it1->second )
00767 {
00768 r_it0->second = r_it1->first - 1;
00769 ++r_it0;
00770 }
00771 // case d: pair completely surrounds subtracted pair
00772 else if( r_it0->first < r_it1->first && r_it0->second > r_it1->second )
00773 {
00774 Range::PairNode* new_node =
00775 alloc_pair( r_it0.node(), r_it0.node()->mPrev, r_it0->first, r_it1->first - 1 );
00776 new_node->mPrev->mNext = new_node->mNext->mPrev = new_node;
00777 r_it0.node()->first = r_it1->second + 1;
00778 ++r_it1;
00779 }
00780 else
00781 {
00782 while( r_it0->second < r_it1->first && r_it0 != this->end() )
00783 ++r_it0;
00784 if( r_it0 == this->end() ) break;
00785 while( r_it1->second < r_it0->first && r_it1 != range2.end() )
00786 ++r_it1;
00787 }
00788 }
00789 return *this;
00790 }
00791 }
00792
00793 EntityID operator-( const Range::const_iterator& it2, const Range::const_iterator& it1 )
00794 {
00795 assert( !it2.mValue || *it2 >= *it1 );
00796 if( it2.mNode == it1.mNode )
00797 {
00798 return *it2 - *it1;
00799 }
00800
00801 EntityID result = it1.mNode->second - it1.mValue + 1;
00802 for( Range::PairNode* n = it1.mNode->mNext; n != it2.mNode; n = n->mNext )
00803 result += n->second - n->first + 1;
00804 if( it2.mValue ) // (it2.mNode != &mHead)
00805 result += it2.mValue - it2.mNode->first;
00806 return result;
00807 }
00808
00809 Range::const_iterator Range::lower_bound( Range::const_iterator first, Range::const_iterator last, EntityHandle val )
00810 {
00811 // Find the first pair whose end is >= val
00812 PairNode* iter;
00813 for( iter = first.mNode; iter != last.mNode; iter = iter->mNext )
00814 {
00815 if( iter->second >= val )
00816 {
00817 // This is the correct pair. Either 'val' is in the range, or
00818 // the range starts before 'val' and iter->first IS the lower_bound.
00819 if( iter->first > val ) return const_iterator( iter, iter->first );
00820 return const_iterator( iter, val );
00821 }
00822 }
00823
00824 if( iter->first >= val )
00825 return const_iterator( iter, iter->first );
00826 else if( *last > val )
00827 return const_iterator( iter, val );
00828 else
00829 return last;
00830 }
00831
00832 Range::const_iterator Range::upper_bound( Range::const_iterator first, Range::const_iterator last, EntityHandle val )
00833 {
00834 Range::const_iterator result = lower_bound( first, last, val );
00835 if( result != last && *result == val ) ++result;
00836 return result;
00837 }
00838
00839 Range::const_iterator Range::lower_bound( EntityType type ) const
00840 {
00841 int err;
00842 EntityHandle handle = CREATE_HANDLE( type, 0, err );
00843 return err ? end() : lower_bound( begin(), end(), handle );
00844 }
00845 Range::const_iterator Range::lower_bound( EntityType type, const_iterator first ) const
00846 {
00847 int err;
00848 EntityHandle handle = CREATE_HANDLE( type, 0, err );
00849 return err ? end() : lower_bound( first, end(), handle );
00850 }
00851
00852 Range::const_iterator Range::upper_bound( EntityType type ) const
00853 {
00854 // if (type+1) overflows, err will be true and we return end().
00855 int err;
00856 EntityHandle handle = CREATE_HANDLE( type + 1, 0, err );
00857 return err ? end() : lower_bound( begin(), end(), handle );
00858 }
00859 Range::const_iterator Range::upper_bound( EntityType type, const_iterator first ) const
00860 {
00861 // if (type+1) overflows, err will be true and we return end().
00862 int err;
00863 EntityHandle handle = CREATE_HANDLE( type + 1, 0, err );
00864 return err ? end() : lower_bound( first, end(), handle );
00865 }
00866
00867 std::pair< Range::const_iterator, Range::const_iterator > Range::equal_range( EntityType type ) const
00868 {
00869 std::pair< Range::const_iterator, Range::const_iterator > result;
00870 int err;
00871 EntityHandle handle = CREATE_HANDLE( type, 0, err );
00872 result.first = err ? end() : lower_bound( begin(), end(), handle );
00873 // if (type+1) overflows, err will be true and we return end().
00874 handle = CREATE_HANDLE( type + 1, 0, err );
00875 result.second = err ? end() : lower_bound( result.first, end(), handle );
00876 return result;
00877 }
00878
00879 bool Range::all_of_type( EntityType type ) const
00880 {
00881 return empty() || ( TYPE_FROM_HANDLE( front() ) == type && TYPE_FROM_HANDLE( back() ) == type );
00882 }
00883
00884 bool Range::all_of_dimension( int dimension ) const
00885 {
00886 return empty() || ( CN::Dimension( TYPE_FROM_HANDLE( front() ) ) == dimension &&
00887 CN::Dimension( TYPE_FROM_HANDLE( back() ) ) == dimension );
00888 }
00889
00890 unsigned Range::num_of_type( EntityType type ) const
00891 {
00892 const_pair_iterator iter = const_pair_begin();
00893 while( iter != const_pair_end() && TYPE_FROM_HANDLE( ( *iter ).second ) < type )
00894 ++iter;
00895
00896 unsigned count = 0;
00897 for( ; iter != const_pair_end(); ++iter )
00898 {
00899 EntityType start_type = TYPE_FROM_HANDLE( ( *iter ).first );
00900 EntityType end_type = TYPE_FROM_HANDLE( ( *iter ).second );
00901 if( start_type > type ) break;
00902
00903 EntityID sid = start_type < type ? 1 : ID_FROM_HANDLE( ( *iter ).first );
00904 EntityID eid = end_type > type ? MB_END_ID : ID_FROM_HANDLE( ( *iter ).second );
00905 count += eid - sid + 1;
00906 }
00907
00908 return count;
00909 }
00910
00911 unsigned Range::num_of_dimension( int dim ) const
00912 {
00913 const_pair_iterator iter = const_pair_begin();
00914 while( iter != const_pair_end() && CN::Dimension( TYPE_FROM_HANDLE( ( *iter ).second ) ) < dim )
00915 ++iter;
00916
00917 int junk;
00918 unsigned count = 0;
00919 for( ; iter != const_pair_end(); ++iter )
00920 {
00921 int start_dim = CN::Dimension( TYPE_FROM_HANDLE( ( *iter ).first ) );
00922 int end_dim = CN::Dimension( TYPE_FROM_HANDLE( ( *iter ).second ) );
00923 if( start_dim > dim ) break;
00924
00925 EntityHandle sh = start_dim < dim ? CREATE_HANDLE( CN::TypeDimensionMap[dim].first, 1, junk ) : ( *iter ).first;
00926 EntityHandle eh =
00927 end_dim > dim ? CREATE_HANDLE( CN::TypeDimensionMap[dim].second, MB_END_ID, junk ) : ( *iter ).second;
00928 count += eh - sh + 1;
00929 }
00930
00931 return count;
00932 }
00933
00934 //! swap the contents of this range with another one
00935 //! THIS FUNCTION MUST NOT BE INLINED, THAT WILL ELIMINATE RANGE_EMPTY AND THIS_EMPTY
00936 //! BY SUBSTITUTION AND THE FUNCTION WON'T WORK RIGHT!
00937 void Range::swap( Range& range )
00938 {
00939 // update next/prev nodes of head of both ranges
00940 bool range_empty = ( range.mHead.mNext == &( range.mHead ) );
00941 bool this_empty = ( mHead.mNext == &mHead );
00942
00943 range.mHead.mNext->mPrev = ( range_empty ? &( range.mHead ) : &mHead );
00944 range.mHead.mPrev->mNext = ( range_empty ? &( range.mHead ) : &mHead );
00945 mHead.mNext->mPrev = ( this_empty ? &mHead : &( range.mHead ) );
00946 mHead.mPrev->mNext = ( this_empty ? &mHead : &( range.mHead ) );
00947
00948 // switch data in head nodes of both ranges
00949 PairNode *range_next = range.mHead.mNext, *range_prev = range.mHead.mPrev;
00950 range.mHead.mNext = ( this_empty ? &( range.mHead ) : mHead.mNext );
00951 range.mHead.mPrev = ( this_empty ? &( range.mHead ) : mHead.mPrev );
00952 mHead.mNext = ( range_empty ? &mHead : range_next );
00953 mHead.mPrev = ( range_empty ? &mHead : range_prev );
00954 }
00955
00956 //! return a subset of this range, by type
00957 Range Range::subset_by_type( EntityType t ) const
00958 {
00959 Range result;
00960 std::pair< const_iterator, const_iterator > iters = equal_range( t );
00961 result.insert( iters.first, iters.second );
00962 return result;
00963 }
00964
00965 //! return a subset of this range, by type
00966 Range Range::subset_by_dimension( int d ) const
00967 {
00968 EntityHandle handle1 = CREATE_HANDLE( CN::TypeDimensionMap[d].first, 0 );
00969 iterator st = lower_bound( begin(), end(), handle1 );
00970
00971 iterator en;
00972 if( d < 4 )
00973 { // dimension 4 is MBENTITYSET
00974 EntityHandle handle2 = CREATE_HANDLE( CN::TypeDimensionMap[d + 1].first, 0 );
00975 en = lower_bound( st, end(), handle2 );
00976 }
00977 else
00978 {
00979 en = end();
00980 }
00981
00982 Range result;
00983 result.insert( st, en );
00984 return result;
00985 }
00986
00987 bool operator==( const Range& r1, const Range& r2 )
00988 {
00989 Range::const_pair_iterator i1, i2;
00990 i1 = r1.const_pair_begin();
00991 i2 = r2.const_pair_begin();
00992 for( ; i1 != r1.const_pair_end(); ++i1, ++i2 )
00993 if( i2 == r2.const_pair_end() || i1->first != i2->first || i1->second != i2->second ) return false;
00994 return i2 == r2.const_pair_end();
00995 }
00996
00997 unsigned long Range::get_memory_use() const
00998 {
00999 unsigned long result = 0;
01000 for( const PairNode* n = mHead.mNext; n != &mHead; n = n->mNext )
01001 result += sizeof( PairNode );
01002 return result;
01003 }
01004
01005 bool Range::contains( const Range& othr ) const
01006 {
01007 if( othr.empty() ) return true;
01008 if( empty() ) return false;
01009
01010 // neither range is empty, so both have valid pair nodes
01011 // other than dummy mHead
01012 const PairNode* this_node = mHead.mNext;
01013 const PairNode* othr_node = othr.mHead.mNext;
01014 for( ;; )
01015 {
01016 // Loop while the node in this list is entirely before
01017 // the node in the other list.
01018 while( this_node->second < othr_node->first )
01019 {
01020 this_node = this_node->mNext;
01021 if( this_node == &mHead ) return false;
01022 }
01023 // If other node is not entirely contained in this node
01024 // then other list is not contained in this list
01025 if( this_node->first > othr_node->first ) break;
01026 // Loop while other node is entirely contained in this node.
01027 while( othr_node->second <= this_node->second )
01028 {
01029 othr_node = othr_node->mNext;
01030 if( othr_node == &othr.mHead ) return true;
01031 }
01032 // If other node overlapped end of this node
01033 if( othr_node->first <= this_node->second ) break;
01034 }
01035
01036 // should be unreachable
01037 return false;
01038 }
01039
01040 } // namespace moab