1 /**
2  * MOAB, a Mesh-Oriented datABase, is a software component for creating,
3  * storing and accessing finite element mesh data.
4  *
5  * Copyright 2004 Sandia Corporation.  Under the terms of Contract
6  * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government
7  * retains certain rights in this software.
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  */
15 
16 /****************************************************
17  * File     :      Range.cpp
18  *
19  * Purpose  :      Stores contiguous or partially
20  *                 contiguous values in an optimized
21  *                 fashion.  Partially contiguous
22  *                 accessing patterns is also optimized.
23  *
24  * Creator  :      Clinton Stimpson
25  *
26  * Date     :      15 April 2002
27  *
28  *******************************************************/
29 
30 
31 #include <assert.h>
32 #include "moab/Range.hpp"
33 #include "Internals.hpp"
34 #include "moab/CN.hpp"
35 #include <iostream>
36 #include <sstream>
37 #include <string>
38 
39 #ifdef HAVE_BOOST_POOL_SINGLETON_POOL_HPP
40 #  include <boost/pool/singleton_pool.hpp>
41    typedef boost::singleton_pool< moab::Range::PairNode , sizeof(moab::Range::PairNode) >
42     PairAlloc;
43 //   static inline moab::Range::PairNode* alloc_pair()
44 //    { return new (PairAlloc::malloc()) moab::Range::PairNode; }
alloc_pair(moab::Range::PairNode * n,moab::Range::PairNode * p,moab::EntityHandle f,moab::EntityHandle s)45    static inline moab::Range::PairNode* alloc_pair(moab::Range::PairNode* n, moab::Range::PairNode* p, moab::EntityHandle f, moab::EntityHandle s)
46     { return new (PairAlloc::malloc()) moab::Range::PairNode(n,p,f,s); }
free_pair(moab::Range::PairNode * node)47    static inline void free_pair( moab::Range::PairNode* node )
48     { node->~PairNode(); PairAlloc::free( node ); }
49 #else
50 //   static inline moab::Range::PairNode* alloc_pair()
51 //    { return new moab::Range::PairNode; }
alloc_pair(moab::Range::PairNode * n,moab::Range::PairNode * p,moab::EntityHandle f,moab::EntityHandle s)52    static inline moab::Range::PairNode* alloc_pair(moab::Range::PairNode* n, moab::Range::PairNode* p, moab::EntityHandle f, moab::EntityHandle s)
53     { return new moab::Range::PairNode(n,p,f,s); }
free_pair(moab::Range::PairNode * node)54    static inline void free_pair( moab::Range::PairNode* node )
55     { delete node; }
56 #endif
57 
58 namespace moab {
59 
60 /*!
61   returns the number of values this list represents
62  */
size() const63 size_t Range::size() const
64 {
65   // go through each pair and add up the number of values
66   // we have.
67   size_t sz=0;
68   for(PairNode* iter = mHead.mNext; iter != &mHead; iter = iter->mNext)
69   {
70     sz += ((iter->second - iter->first) + 1);
71   }
72   return sz;
73 }
74 
75 /*!
76   advance iterator
77 */
operator +=(EntityID sstep)78 Range::const_iterator& Range::const_iterator::operator+=( EntityID sstep )
79 {
80     // Check negative now to avoid infinite loop below.
81   if (sstep < 0)
82   {
83     return operator-=( -sstep );
84   }
85   EntityHandle step = sstep;
86 
87     // Handle current PairNode.  Either step is within the current
88     // node or need to remove the remainder of the current node
89     // from step.
90   EntityHandle this_node_rem = mNode->second - mValue;
91   if (this_node_rem >= step)
92   {
93     mValue += step;
94     return *this;
95   }
96   step -= this_node_rem + 1;
97 
98     // For each node we are stepping past, decrement step
99     // by the size of the node.
100   PairNode* node = mNode->mNext;
101   EntityHandle node_size = node->second - node->first + 1;
102   while (step >= node_size)
103   {
104     step -= node_size;
105     node = node->mNext;
106     node_size = node->second - node->first + 1;
107   }
108 
109     // Advance into the resulting node by whatever is
110     // left in step.
111   mNode = node;
112   mValue = mNode->first + step;
113   return *this;
114 }
115 
116 
117 
118 /*!
119   regress iterator
120 */
operator -=(EntityID sstep)121 Range::const_iterator& Range::const_iterator::operator-=( EntityID sstep )
122 {
123     // Check negative now to avoid infinite loop below.
124   if (sstep < 0)
125   {
126     return operator+=( -sstep );
127   }
128   EntityHandle step = sstep;
129 
130     // Handle current PairNode.  Either step is within the current
131     // node or need to remove the remainder of the current node
132     // from step.
133   EntityHandle this_node_rem = mValue - mNode->first;
134   if (this_node_rem >= step)
135   {
136     mValue -= step;
137     return *this;
138   }
139   step -= this_node_rem + 1;
140 
141     // For each node we are stepping past, decrement step
142     // by the size of the node.
143   PairNode* node = mNode->mPrev;
144   EntityHandle node_size = node->second - node->first + 1;
145   while (step >= node_size)
146   {
147     step -= node_size;
148     node = node->mPrev;
149     node_size = node->second - node->first + 1;
150   }
151 
152     // Advance into the resulting node by whatever is
153     // left in step.
154   mNode = node;
155   mValue = mNode->second - step;
156   return *this;
157 }
158 
159 
160 
161 
162   //! another constructor that takes an initial range
Range(EntityHandle val1,EntityHandle val2)163 Range::Range( EntityHandle val1, EntityHandle val2 )
164 {
165   mHead.mNext = mHead.mPrev = alloc_pair(&mHead, &mHead, val1, val2);
166   mHead.first = mHead.second = 0;
167 }
168 
169   //! copy constructor
Range(const Range & copy)170 Range::Range(const Range& copy)
171 {
172     // set the head node to point to itself
173   mHead.mNext = mHead.mPrev = &mHead;
174   mHead.first = mHead.second = 0;
175 
176   const PairNode* copy_node = copy.mHead.mNext;
177   PairNode* new_node = &mHead;
178   for(; copy_node != &(copy.mHead); copy_node = copy_node->mNext)
179   {
180     PairNode* tmp_node = alloc_pair(new_node->mNext, new_node, copy_node->first,
181                                       copy_node->second);
182     new_node->mNext->mPrev = tmp_node;
183     new_node->mNext = tmp_node;
184     new_node = tmp_node;
185   }
186 }
187 
188   //! clears the contents of the list
clear()189 void Range::clear()
190 {
191   PairNode* tmp_node = mHead.mNext;
192   while(tmp_node != &mHead)
193   {
194     PairNode* to_delete = tmp_node;
195     tmp_node = tmp_node->mNext;
196     free_pair( to_delete );
197   }
198   mHead.mNext = &mHead;
199   mHead.mPrev = &mHead;
200 }
201 
operator =(const Range & copy)202 Range& Range::operator=(const Range& copy)
203 {
204   clear();
205   const PairNode* copy_node = copy.mHead.mNext;
206   PairNode* new_node = &mHead;
207   for(; copy_node != &(copy.mHead); copy_node = copy_node->mNext)
208   {
209     PairNode* tmp_node = alloc_pair(new_node->mNext, new_node, copy_node->first,
210                                       copy_node->second);
211     new_node->mNext->mPrev = tmp_node;
212     new_node->mNext = tmp_node;
213     new_node = tmp_node;
214   }
215   return *this;
216 }
217 
218 
219 /*!
220   inserts a single value into this range
221 */
222 
insert(Range::iterator hint,EntityHandle val)223 Range::iterator Range::insert( Range::iterator hint, EntityHandle val )
224 {
225   // don't allow zero-valued handles in Range
226   if(val == 0)
227     return end();
228 
229   // if this is empty, just add it and return an iterator to it
230   if(&mHead == mHead.mNext)
231   {
232     mHead.mNext = mHead.mPrev = alloc_pair(&mHead, &mHead, val, val);
233     return iterator(mHead.mNext, val);
234   }
235 
236   // find the location in the list where we can safely insert
237   // new items and keep it ordered
238   PairNode* hter = hint.mNode;
239   PairNode* jter = hter->first <= val ? hter : mHead.mNext;
240   for( ; (jter != &mHead) && (jter->second < val); jter=jter->mNext);
241   PairNode* iter = jter;
242   jter = jter->mPrev;
243 
244   // if this val is already in the list
245   if( (iter->first <= val && iter->second >= val) && (iter != &mHead) )
246   {
247     // return an iterator pointing to this location
248     return iterator( iter, val );
249   }
250 
251   // one of a few things can happen at this point
252   // 1. this range needs to be backwardly extended
253   // 2. the previous range needs to be forwardly extended
254   // 3. a new range needs to be added
255 
256 
257   // extend this range back a bit
258   else if( (iter->first == (val+1)) && (iter != &mHead) )
259   {
260     iter->first = val;
261     // see if we need to merge two ranges
262     if( (iter != mHead.mNext) && (jter->second == (val-1)))
263     {
264       jter->second = iter->second;
265       iter->mPrev->mNext = iter->mNext;
266       iter->mNext->mPrev = iter->mPrev;
267       free_pair( iter );
268       return iterator( jter, val );
269     }
270     else
271     {
272       return iterator( iter, val );
273     }
274 
275   }
276   // extend the previous range forward a bit
277   else if( (jter->second == (val-1)) && (iter != mHead.mNext) )
278   {
279     jter->second = val;
280     return iterator(jter, val);
281   }
282   // make a new range
283   else
284   {
285     PairNode* new_node = alloc_pair(iter, iter->mPrev, val, val);
286     iter->mPrev = new_node->mPrev->mNext = new_node;
287     return iterator(new_node, val);
288   }
289 
290 }
291 
insert(Range::iterator prev,EntityHandle val1,EntityHandle val2)292 Range::iterator Range::insert( Range::iterator prev,
293                                    EntityHandle val1,
294                                    EntityHandle val2 )
295 {
296   if(val1 == 0 || val1 > val2)
297     return end();
298 
299   // Empty
300   if (mHead.mNext == &mHead)
301   {
302     assert( prev == end() );
303     PairNode* new_node = alloc_pair( &mHead, &mHead, val1, val2 );
304     mHead.mNext = mHead.mPrev = new_node;
305     return iterator( mHead.mNext, val1 );
306   }
307 
308   PairNode* iter = prev.mNode;
309     // If iterator is at end, set it to last.
310     // Thus if the hint was to append, we start searching
311     // at the end of the list.
312   if (iter == &mHead)
313     iter = mHead.mPrev;
314     // if hint (prev) is past insert position, reset it to the beginning.
315   if (iter != &mHead && iter->first > val2+1)
316     iter = mHead.mNext;
317 
318     // If hint is bogus then search backwards
319   while (iter != mHead.mNext && iter->mPrev->second >= val1-1)
320     iter = iter->mPrev;
321 
322   // Input range is before beginning?
323   if (iter->mPrev == &mHead && val2 < iter->first - 1)
324   {
325     PairNode* new_node = alloc_pair( iter, &mHead,  val1, val2 );
326     mHead.mNext = iter->mPrev = new_node;
327     return iterator( mHead.mNext, val1 );
328   }
329 
330   // Find first intersecting list entry, or the next entry
331   // if none intersects.
332   while (iter != &mHead && iter->second+1 < val1)
333     iter = iter->mNext;
334 
335   // Need to insert new pair (don't intersect any existing pair)?
336   if (iter == &mHead || iter->first-1 > val2)
337   {
338     PairNode* new_node = alloc_pair( iter, iter->mPrev, val1, val2 );
339     iter->mPrev = iter->mPrev->mNext = new_node;
340     return iterator( iter->mPrev, val1 );
341   }
342 
343   // Make the first intersecting pair the union of itself with [val1,val2]
344   if (iter->first > val1)
345     iter->first = val1;
346   if (iter->second >= val2)
347     return iterator( iter, val1 );
348   iter->second = val2;
349 
350   // Merge any remaining pairs that intersect [val1,val2]
351   while (iter->mNext != &mHead && iter->mNext->first <= val2 + 1)
352   {
353     PairNode* dead = iter->mNext;
354     iter->mNext = dead->mNext;
355     dead->mNext->mPrev = iter;
356 
357     if (dead->second > val2)
358       iter->second = dead->second;
359     free_pair( dead );
360   }
361 
362   return iterator( iter, val1 );
363 }
364 
365 
366 /*!
367   erases an item from this list and returns an iterator to the next item
368 */
369 
erase(iterator iter)370 Range::iterator Range::erase(iterator iter)
371 {
372   // one of a few things could happen
373   // 1. shrink a range
374   // 2. split a range
375   // 3. remove a range
376 
377   if(iter == end())
378     return end();
379 
380   // the iterator most likely to be returned
381   iterator new_iter = iter;
382   ++new_iter;
383 
384   PairNode* kter = iter.mNode;
385 
386   // just remove the range
387   if(kter->first == kter->second)
388   {
389     kter->mNext->mPrev = kter->mPrev;
390     kter->mPrev->mNext = kter->mNext;
391     free_pair( kter );
392     return new_iter;
393   }
394   // shrink it
395   else if(kter->first == iter.mValue)
396   {
397     kter->first++;
398     return new_iter;
399   }
400   // shrink it the other way
401   else if(kter->second == iter.mValue)
402   {
403     kter->second--;
404     return new_iter;
405   }
406   // split the range
407   else
408   {
409     PairNode* new_node = alloc_pair(iter.mNode->mNext, iter.mNode, iter.mValue+1, kter->second);
410     new_node->mPrev->mNext = new_node->mNext->mPrev = new_node;
411     iter.mNode->second = iter.mValue - 1;
412     new_iter = const_iterator(new_node, new_node->first);
413     return new_iter;
414   }
415 
416 }
417 
418 
419   //! remove a range of items from the list
erase(iterator iter1,iterator iter2)420 Range::iterator Range::erase( iterator iter1, iterator iter2)
421 {
422   iterator result;
423 
424   if (iter1.mNode == iter2.mNode) {
425     if (iter2.mValue <= iter1.mValue) {
426         // empty range OK, otherwise invalid input
427       return iter2;
428     }
429 
430       // If both iterators reference the same pair node, then
431       // we're either removing values from the front of the
432       // node or splitting the node.  We can never be removing
433       // the last value in the node in this case because iter2
434       // points *after* the last entry to be removed.
435 
436     PairNode* node = iter1.mNode;
437     if (iter1.mValue == node->first) {
438         node->first = iter2.mValue;
439         result = iter2;
440     }
441     else {
442       PairNode* new_node = alloc_pair( node->mNext, node, iter2.mValue, node->second );
443       new_node->mNext->mPrev = new_node;
444       new_node->mPrev->mNext = new_node;
445       node->second = iter1.mValue - 1;
446       result = iterator( new_node, new_node->first );
447     }
448   }
449   else {
450     if (iter1.mNode == &mHead)
451       return iter1;
452     PairNode* dn = iter1.mNode;
453     if (iter1.mValue > dn->first) {
454       dn->second = iter1.mValue-1;
455       dn = dn->mNext;
456     }
457     if (iter2.mNode != &mHead)
458       iter2.mNode->first = iter2.mValue;
459     while (dn != iter2.mNode) {
460       PairNode* dead = dn;
461       dn = dn->mNext;
462 
463       dead->mPrev->mNext = dead->mNext;
464       dead->mNext->mPrev = dead->mPrev;
465       dead->mPrev = dead->mNext = 0;
466       delete dead;
467     }
468 
469     result = iter2;
470   }
471 
472   return result;
473 }
474 
delete_pair_node(PairNode * node)475 void Range::delete_pair_node( PairNode* node )
476 {
477   if (node != &mHead) { // pop_front() and pop_back() rely on this check
478     node->mPrev->mNext = node->mNext;
479     node->mNext->mPrev = node->mPrev;
480     free_pair( node );
481   }
482 }
483 
484   //! remove first entity from range
pop_front()485 EntityHandle Range::pop_front()
486 {
487   EntityHandle retval = front();
488   if (mHead.mNext->first == mHead.mNext->second) // need to remove pair from range
489     delete_pair_node( mHead.mNext );
490   else
491     ++(mHead.mNext->first); // otherwise just adjust start value of pair
492 
493   return retval;
494 }
495 
496   //! remove last entity from range
pop_back()497 EntityHandle Range::pop_back()
498 {
499   EntityHandle retval = back();
500   if (mHead.mPrev->first == mHead.mPrev->second) // need to remove pair from range
501     delete_pair_node( mHead.mPrev );
502   else
503     --(mHead.mPrev->second); // otherwise just adjust end value of pair
504 
505   return retval;
506 }
507 
508 /*!
509   finds a value in the list.
510   this method is preferred over other algorithms because
511   it can be found faster this way.
512 */
find(EntityHandle val) const513 Range::const_iterator Range::find(EntityHandle val) const
514 {
515   // iterator through the list
516   PairNode* iter = mHead.mNext;
517   for( ; iter != &mHead && (val > iter->second); iter=iter->mNext );
518   return ((iter->second >= val) && (iter->first <= val)) ? const_iterator(iter,val) : end();
519 }
520 
521 /*!
522   merges another Range with this one
523 */
524 
insert(Range::const_iterator begini,Range::const_iterator endi)525 void Range::insert( Range::const_iterator begini,
526                      Range::const_iterator endi )
527 {
528   if (begini == endi)
529     return;
530 
531   PairNode* node = begini.mNode;
532   if (endi.mNode == node)
533   {
534     insert( *begini, (*endi)-1 );
535     return;
536   }
537 
538   Range::iterator hint = insert( *begini, node->second );
539   node = node->mNext;
540   while (node != endi.mNode)
541   {
542     hint = insert( hint, node->first, node->second );
543     node = node->mNext;
544   }
545 
546   if (*endi > node->first)
547   {
548     if (*endi <= node->second)
549       insert( hint, node->first, *(endi) - 1 );
550     else
551       insert( hint, node->first, node->second );
552   }
553 }
554 
555 
556 
557 
558 #include <algorithm>
559 
560 
561 // checks the range to make sure everything is A-Ok.
sanity_check() const562 void Range::sanity_check() const
563 {
564   if(empty())
565     return;
566 
567   const PairNode* node = mHead.mNext;
568   std::vector<const PairNode*> seen_before;
569   bool stop_it = false;
570 
571   for(; stop_it == false; node = node->mNext)
572   {
573     // have we seen this node before?
574     assert(std::find(seen_before.begin(), seen_before.end(), node) == seen_before.end());
575     seen_before.push_back(node);
576 
577     // is the connection correct?
578     assert(node->mNext->mPrev == node);
579 
580     // are the values right?
581     assert(node->first <= node->second);
582     if(node != &mHead && node->mPrev != &mHead)
583       assert(node->mPrev->second < node->first);
584 
585     if(node == &mHead)
586       stop_it = true;
587 
588   }
589 
590 }
591 
str_rep(const char * indent_prefix) const592 const std::string Range::str_rep(const char* indent_prefix) const {
593   std::stringstream str_stream;
594   std::string indent_prefix_str;
595   if (NULL != indent_prefix) {
596     indent_prefix_str += indent_prefix;
597   }
598 
599   if (empty()) {
600     str_stream << indent_prefix_str << "\tempty" << std::endl;
601     return str_stream.str().c_str();
602   }
603 
604   for (const_pair_iterator i = const_pair_begin(); i != const_pair_end(); ++i) {
605     EntityType t1 = TYPE_FROM_HANDLE( i->first );
606     EntityType t2 = TYPE_FROM_HANDLE( i->second );
607 
608     str_stream << indent_prefix_str << "\t" << CN::EntityTypeName( t1 ) << " "
609            << ID_FROM_HANDLE( i->first );
610     if(i->first != i->second) {
611       str_stream << " - ";
612       if (t1 != t2)
613         str_stream << CN::EntityTypeName( t2 ) << " ";
614       str_stream << ID_FROM_HANDLE( i->second );
615     }
616     str_stream << std::endl;
617   }
618 
619   return str_stream.str();
620 }
621 
print(std::ostream & stream,const char * indent_prefix) const622 void Range::print(std::ostream& stream, const char *indent_prefix) const
623 {
624   stream << str_rep(indent_prefix);
625 }
626 
627 // for debugging
print(const char * indent_prefix) const628 void Range::print(const char *indent_prefix) const
629 {
630   print(std::cout, indent_prefix);
631 }
632 
633 
634   // intersect two ranges, placing the results in the return range
635 #define MAX(a,b) (a < b ? b : a)
636 #define MIN(a,b) (a > b ? b : a)
intersect(const Range & range1,const Range & range2)637 Range intersect(const Range &range1, const Range &range2)
638 {
639   Range::const_pair_iterator r_it[2] = { range1.const_pair_begin(),
640                                            range2.const_pair_begin() };
641   EntityHandle low_it, high_it;
642 
643   Range lhs;
644   Range::iterator hint = lhs.begin();
645 
646     // terminate the while loop when at least one "start" iterator is at the
647     // end of the list
648   while (r_it[0] != range1.end() && r_it[1] != range2.end()) {
649 
650     if (r_it[0]->second < r_it[1]->first)
651         // 1st subrange completely below 2nd subrange
652       ++r_it[0];
653     else if (r_it[1]->second < r_it[0]->first)
654         // 2nd subrange completely below 1st subrange
655       ++r_it[1];
656 
657     else {
658         // else ranges overlap; first find greater start and lesser end
659       low_it = MAX(r_it[0]->first, r_it[1]->first);
660       high_it = MIN(r_it[0]->second, r_it[1]->second);
661 
662         // insert into result
663       hint = lhs.insert(hint, low_it, high_it);
664 
665         // now find bounds of this insertion and increment corresponding iterator
666       if (high_it == r_it[0]->second) ++r_it[0];
667       if (high_it == r_it[1]->second) ++r_it[1];
668     }
669   }
670 
671   return lhs;
672 }
673 
subtract(const Range & range1,const Range & range2)674 Range subtract(const Range &range1, const Range &range2)
675 {
676   const bool braindead = false;
677 
678   if (braindead) {
679       // brain-dead implementation right now
680     Range res( range1 );
681     for (Range::const_iterator rit = range2.begin(); rit != range2.end(); ++rit)
682       res.erase(*rit);
683 
684     return res;
685   }
686   else {
687     Range lhs( range1 );
688 
689     Range::pair_iterator r_it0 = lhs.pair_begin();
690     Range::const_pair_iterator r_it1 = range2.const_pair_begin();
691 
692       // terminate the while loop when at least one "start" iterator is at the
693       // end of the list
694     while (r_it0 != lhs.end() && r_it1 != range2.end()) {
695         // case a: pair wholly within subtracted pair
696       if (r_it0->first >= r_it1->first && r_it0->second <= r_it1->second) {
697         Range::PairNode *rtmp = r_it0.node();
698         ++r_it0;
699         lhs.delete_pair_node(rtmp);
700       }
701         // case b: pair overlaps upper part of subtracted pair
702       else if (r_it0->first <= r_it1->second &&
703                r_it0->first >= r_it1->first) {
704         r_it0->first = r_it1->second + 1;
705         ++r_it1;
706       }
707         // case c: pair overlaps lower part of subtracted pair
708       else if (r_it0->second >= r_it1->first &&
709                r_it0->second <= r_it1->second) {
710         r_it0->second = r_it1->first - 1;
711         ++r_it0;
712       }
713         // case d: pair completely surrounds subtracted pair
714       else if (r_it0->first < r_it1->first &&
715                r_it0->second > r_it1->second) {
716         Range::PairNode* new_node = alloc_pair(r_it0.node(), r_it0.node()->mPrev,
717                                         r_it0->first, r_it1->first - 1);
718         new_node->mPrev->mNext = new_node->mNext->mPrev = new_node;
719         r_it0.node()->first = r_it1->second+1;
720         ++r_it1;
721       }
722       else {
723         while (r_it0->second < r_it1->first && r_it0 != lhs.end()) ++r_it0;
724         if (r_it0 == lhs.end()) break;
725         while (r_it1->second < r_it0->first && r_it1 != range2.end()) ++r_it1;
726       }
727     }
728 
729     return lhs;
730   }
731 }
732 
operator -=(const Range & range2)733 Range &Range::operator-=(const Range &range2)
734 {
735   const bool braindead = false;
736 
737   if (braindead) {
738       // brain-dead implementation right now
739     Range res( *this );
740     for (Range::const_iterator rit = range2.begin(); rit != range2.end(); ++rit)
741       res.erase(*rit);
742 
743     return *this;
744   }
745   else {
746     Range::pair_iterator r_it0 = this->pair_begin();
747     Range::const_pair_iterator r_it1 = range2.const_pair_begin();
748 
749       // terminate the while loop when at least one "start" iterator is at the
750       // end of the list
751     while (r_it0 != this->end() && r_it1 != range2.end()) {
752         // case a: pair wholly within subtracted pair
753       if (r_it0->first >= r_it1->first && r_it0->second <= r_it1->second) {
754         Range::PairNode *rtmp = r_it0.node();
755         ++r_it0;
756         this->delete_pair_node(rtmp);
757       }
758         // case b: pair overlaps upper part of subtracted pair
759       else if (r_it0->first <= r_it1->second &&
760                r_it0->first >= r_it1->first) {
761         r_it0->first = r_it1->second + 1;
762         ++r_it1;
763       }
764         // case c: pair overlaps lower part of subtracted pair
765       else if (r_it0->second >= r_it1->first &&
766                r_it0->second <= r_it1->second) {
767         r_it0->second = r_it1->first - 1;
768         ++r_it0;
769       }
770         // case d: pair completely surrounds subtracted pair
771       else if (r_it0->first < r_it1->first &&
772                r_it0->second > r_it1->second) {
773         Range::PairNode* new_node = alloc_pair(r_it0.node(), r_it0.node()->mPrev,
774                                         r_it0->first, r_it1->first - 1);
775         new_node->mPrev->mNext = new_node->mNext->mPrev = new_node;
776         r_it0.node()->first = r_it1->second+1;
777         ++r_it1;
778       }
779       else {
780         while (r_it0->second < r_it1->first && r_it0 != this->end()) ++r_it0;
781         if (r_it0 == this->end()) break;
782         while (r_it1->second < r_it0->first && r_it1 != range2.end()) ++r_it1;
783       }
784     }
785     return *this;
786   }
787 }
788 
789 
790 EntityID
operator -(const Range::const_iterator & it2,const Range::const_iterator & it1)791 operator-( const Range::const_iterator& it2, const Range::const_iterator& it1 )
792 {
793   assert( !it2.mValue || *it2 >= *it1 );
794   if (it2.mNode == it1.mNode) {
795     return *it2 - *it1;
796   }
797 
798   EntityID result = it1.mNode->second - it1.mValue + 1;
799   for (Range::PairNode* n = it1.mNode->mNext; n != it2.mNode; n = n->mNext)
800     result += n->second - n->first + 1;
801   if (it2.mValue) // (it2.mNode != &mHead)
802     result += it2.mValue - it2.mNode->first;
803   return result;
804 }
805 
806 
lower_bound(Range::const_iterator first,Range::const_iterator last,EntityHandle val)807 Range::const_iterator Range::lower_bound(Range::const_iterator first,
808                                              Range::const_iterator last,
809                                              EntityHandle val)
810 {
811     // Find the first pair whose end is >= val
812   PairNode* iter;
813   for (iter = first.mNode; iter != last.mNode; iter = iter->mNext)
814   {
815     if (iter->second >= val)
816     {
817         // This is the correct pair.  Either 'val' is in the range, or
818         // the range starts before 'val' and iter->first IS the lower_bound.
819       if (iter->first > val)
820         return const_iterator(iter, iter->first);
821       return const_iterator(iter, val);
822     }
823   }
824 
825   if (iter->first >= val)
826     return const_iterator( iter, iter->first );
827   else if(*last > val)
828     return const_iterator( iter, val );
829   else
830     return last;
831 }
832 
upper_bound(Range::const_iterator first,Range::const_iterator last,EntityHandle val)833 Range::const_iterator Range::upper_bound(Range::const_iterator first,
834                                              Range::const_iterator last,
835                                              EntityHandle val)
836 {
837   Range::const_iterator result = lower_bound( first, last, val );
838   if (result != last && *result == val)
839     ++result;
840   return result;
841 }
842 
lower_bound(EntityType type) const843 Range::const_iterator Range::lower_bound( EntityType type ) const
844 {
845   int err;
846   EntityHandle handle = CREATE_HANDLE( type, 0, err );
847   return err ? end() : lower_bound( begin(), end(), handle );
848 }
lower_bound(EntityType type,const_iterator first) const849 Range::const_iterator Range::lower_bound( EntityType type,
850                                               const_iterator first ) const
851 {
852   int err;
853   EntityHandle handle = CREATE_HANDLE( type, 0, err );
854   return err ? end() : lower_bound( first, end(), handle );
855 }
856 
upper_bound(EntityType type) const857 Range::const_iterator Range::upper_bound( EntityType type ) const
858 {
859     // if (type+1) overflows, err will be true and we return end().
860   int err;
861   EntityHandle handle = CREATE_HANDLE( type + 1, 0, err );
862   return err ? end() : lower_bound( begin(), end(), handle );
863 }
upper_bound(EntityType type,const_iterator first) const864 Range::const_iterator Range::upper_bound( EntityType type,
865                                               const_iterator first ) const
866 {
867     // if (type+1) overflows, err will be true and we return end().
868   int err;
869   EntityHandle handle = CREATE_HANDLE( type + 1, 0, err );
870   return err ? end() : lower_bound( first, end(), handle );
871 }
872 
873 std::pair<Range::const_iterator, Range::const_iterator>
equal_range(EntityType type) const874 Range::equal_range( EntityType type ) const
875 {
876   std::pair<Range::const_iterator, Range::const_iterator> result;
877   int err;
878   EntityHandle handle = CREATE_HANDLE( type, 0, err );
879   result.first = err ? end() : lower_bound( begin(), end(), handle );
880     // if (type+1) overflows, err will be true and we return end().
881   handle = CREATE_HANDLE( type+1, 0, err );
882   result.second = err ? end() : lower_bound( result.first, end(), handle );
883   return result;
884 }
885 
all_of_type(EntityType type) const886 bool Range::all_of_type( EntityType type ) const
887 {
888   return empty()
889       || (TYPE_FROM_HANDLE(front()) == type
890        && TYPE_FROM_HANDLE(back()) == type);
891 }
892 
all_of_dimension(int dimension) const893 bool Range::all_of_dimension( int dimension ) const
894 {
895   return empty()
896       || (CN::Dimension(TYPE_FROM_HANDLE(front())) == dimension
897        && CN::Dimension(TYPE_FROM_HANDLE(back())) == dimension);
898 }
899 
num_of_type(EntityType type) const900 unsigned Range::num_of_type( EntityType type ) const
901 {
902   const_pair_iterator iter = const_pair_begin();
903   while(iter != const_pair_end() && TYPE_FROM_HANDLE((*iter).second) < type)
904     ++iter;
905 
906   unsigned count = 0;
907   for ( ; iter != const_pair_end(); ++iter)
908   {
909     EntityType start_type = TYPE_FROM_HANDLE((*iter).first);
910     EntityType end_type = TYPE_FROM_HANDLE((*iter).second);
911     if (start_type > type)
912       break;
913 
914     EntityID sid = start_type < type ? 1 : ID_FROM_HANDLE((*iter).first);
915     EntityID eid = end_type > type ? MB_END_ID : ID_FROM_HANDLE((*iter).second);
916     count += eid - sid + 1;
917   }
918 
919   return count;
920 }
921 
num_of_dimension(int dim) const922 unsigned Range::num_of_dimension( int dim ) const
923 {
924   const_pair_iterator iter = const_pair_begin();
925   while(iter != const_pair_end() && CN::Dimension(TYPE_FROM_HANDLE((*iter).second)) < dim)
926     ++iter;
927 
928   int junk;
929   unsigned count = 0;
930   for ( ; iter != const_pair_end(); ++iter)
931   {
932     int start_dim = CN::Dimension(TYPE_FROM_HANDLE((*iter).first));
933     int end_dim = CN::Dimension(TYPE_FROM_HANDLE((*iter).second));
934     if (start_dim > dim)
935       break;
936 
937     EntityHandle sh = start_dim < dim ?
938                         CREATE_HANDLE( CN::TypeDimensionMap[dim].first, 1, junk ) :
939                         (*iter).first;
940     EntityHandle eh = end_dim > dim ?
941                         CREATE_HANDLE( CN::TypeDimensionMap[dim].second, MB_END_ID, junk ) :
942                         (*iter).second;
943     count += eh - sh + 1;
944   }
945 
946   return count;
947 }
948 
949 
950 
951 
952 //! swap the contents of this range with another one
953 //! THIS FUNCTION MUST NOT BE INLINED, THAT WILL ELIMINATE RANGE_EMPTY AND THIS_EMPTY
954 //! BY SUBSTITUTION AND THE FUNCTION WON'T WORK RIGHT!
swap(Range & range)955 void Range::swap( Range &range )
956 {
957     // update next/prev nodes of head of both ranges
958   bool range_empty = (range.mHead.mNext == &(range.mHead));
959   bool this_empty = (mHead.mNext == &mHead);
960 
961   range.mHead.mNext->mPrev = (range_empty ? &(range.mHead) : &mHead);
962   range.mHead.mPrev->mNext = (range_empty ? &(range.mHead) : &mHead);
963   mHead.mNext->mPrev = (this_empty ? &mHead : &(range.mHead));
964   mHead.mPrev->mNext = (this_empty ? &mHead : &(range.mHead));
965 
966     // switch data in head nodes of both ranges
967   PairNode *range_next = range.mHead.mNext, *range_prev = range.mHead.mPrev;
968   range.mHead.mNext = (this_empty ? &(range.mHead) : mHead.mNext);
969   range.mHead.mPrev = (this_empty ? &(range.mHead) : mHead.mPrev);
970   mHead.mNext = (range_empty ? &mHead : range_next);
971   mHead.mPrev = (range_empty ? &mHead : range_prev);
972 
973 }
974 
975     //! return a subset of this range, by type
subset_by_type(EntityType t) const976 Range Range::subset_by_type(EntityType t) const
977 {
978   Range result;
979   std::pair<const_iterator, const_iterator> iters = equal_range(t);
980   result.insert( iters.first, iters.second );
981   return result;
982 }
983 
984     //! return a subset of this range, by type
subset_by_dimension(int d) const985 Range Range::subset_by_dimension( int d ) const
986 {
987   EntityHandle handle1 = CREATE_HANDLE( CN::TypeDimensionMap[d].first, 0 );
988   iterator st = lower_bound( begin(), end(), handle1 );
989 
990   iterator en;
991   if (d < 4) { // dimension 4 is MBENTITYSET
992     EntityHandle handle2 = CREATE_HANDLE( CN::TypeDimensionMap[d+1].first, 0 );
993     en = lower_bound( st, end(), handle2 );
994   }
995   else {
996     en = end();
997   }
998 
999   Range result;
1000   result.insert( st, en );
1001   return result;
1002 }
1003 
operator ==(const Range & r1,const Range & r2)1004 bool operator==( const Range& r1, const Range& r2 )
1005 {
1006   Range::const_pair_iterator i1, i2;
1007   i1 = r1.const_pair_begin();
1008   i2 = r2.const_pair_begin();
1009   for ( ; i1 != r1.const_pair_end(); ++i1, ++i2)
1010     if (i2 == r2.const_pair_end() ||
1011         i1->first != i2->first ||
1012         i1->second != i2->second)
1013       return false;
1014   return i2 == r2.const_pair_end();
1015 }
1016 
get_memory_use() const1017 unsigned long Range::get_memory_use() const
1018 {
1019   unsigned long result = 0;
1020   for (const PairNode* n = mHead.mNext; n != &mHead; n = n->mNext)
1021     result += sizeof(PairNode);
1022   return result;
1023 }
1024 
contains(const Range & othr) const1025 bool Range::contains( const Range& othr ) const
1026 {
1027   if (othr.empty())
1028     return true;
1029   if (empty())
1030     return false;
1031 
1032     // neither range is empty, so both have valid pair nodes
1033     // other than dummy mHead
1034   const PairNode* this_node = mHead.mNext;
1035   const PairNode* othr_node = othr.mHead.mNext;
1036   for(;;) {
1037       // Loop while the node in this list is entirely before
1038       // the node in the other list.
1039     while (this_node->second < othr_node->first) {
1040       this_node = this_node->mNext;
1041       if (this_node == &mHead)
1042         return false;
1043     }
1044       // If other node is not entirely contained in this node
1045       // then other list is not contained in this list
1046     if (this_node->first > othr_node->first)
1047       break;
1048       // Loop while other node is entirely contained in this node.
1049     while (othr_node->second <= this_node->second) {
1050       othr_node = othr_node->mNext;
1051       if (othr_node == &othr.mHead)
1052         return true;
1053     }
1054       // If other node overlapped end of this node
1055     if (othr_node->first <= this_node->second)
1056       break;
1057   }
1058 
1059     // should be unreachable
1060   return false;
1061 }
1062 
1063 } // namespace moab
1064