Loading [MathJax]/extensions/tex2jax.js
Mesh Oriented datABase  (version 5.5.1)
An array-based unstructured mesh library
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Range.hpp
Go to the documentation of this file.
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  \brief Stores contiguous or partially contiguous values in an optimized 18  fashion. Partially contiguous accessing patterns is also optimized. 19  20  \author Clinton Stimpson 21  22  \date 15 April 2002 23  24  ************* Range FAQ and tips ******************** 25  26  The purpose of this FAQ is to familiarize a user with 27  the appropriate use of the Range template. 28  29  ******* A few points about Range: ******* 30  1. Range is not the be all of generic containers. 31  2. Range has its strengths and weaknesses as any other 32  STL container has. 33  3. Strengths: 34  a. For contiguous values, storage is extremely minimal. 35  b. Searching through contiguous values, at best, is 36  a constant time operation. 37  b. Fairly compatible with most STL algorithms. 38  c. Insertions of data from high value to low value 39  is a linear operation (constant for each insertion). 40  d. Removal of a value using an iterator is constant time. 41  42  4. Weaknesses: 43  a. For non-contiguous values, storage is not minimal and is 44  on the order of 4x the storage space as using a vector. 45  b. Searching through non-contiguous values is linear 46  time operation. 47  c. Insertions of random data is VERY slow. 48  49  Given the above characteristics of Ranges, you can now 50  decide between Range and another STL container for your 51  particular needs. 52  53  54  ******* Tips ******* 55  1. Be aware of what iterators are available. Currently, there are 56  three. Range<T>::iterator, Range<T>::const_iterator, 57  and Range<T>::RangeListIterator. 58  iterator is derived from const_iterator. const_iterator 59  is derived from RangeListIterator. RangeListIterator is a 60  std::list<std::pair<T,T> >::const_iterator. 61  If a particular algorithm could be more efficient by using 62  RangeListIterator, do so. 63  64  ie. 65  66  Range<char> range1; 67  ... put some stuff in range1 68  Range<char> range2; 69  70  // the SLOW way. 71  std::copy(range1.begin(), range1.end(), range_inserter<...>(range2)); 72  73  // the FAST way. 74  for(Range<char>::RangeListIterator iter = range1.begin(), 75  iter != range1.end(); ++iter) 76  { 77  range2.insert(iter->first, iter->second); 78  } 79  80  2. Prefer insert(val1, val2) over insert(val) where possible. 81  82  3. insert(val) and insert(val1, val2) have to perform searching 83  to find out where to insert an item. Searches are started 84  from the beginning of the values. Inserting larger values 85  before smaller values will increase efficiency. 86  87  ie. 88  std::set<int> my_set; 89  Range<int> my_range; 90  .. perform some operations which set does efficiently. 91  92  // now copy the results from the set into the range. 93  // copy from the end of the set to the beginning of the set 94  std::copy(my_set.rbegin(), my_set.rend(), 95  range_inserter< Range<int> > ( my_range ); 96  97  4. Use empty() instead of size() if you only need to find out 98  if there is anything in the list. 99  100  5. Know what swap() does. Sometimes it is useful. It'll replace 101  the contents of one list with another. 102  103  void compute_and_get_some_set( 104  Range<char> range1, 105  Range<char> range2, 106  Range<char>& results 107  ); 108  { 109  Range<char> tmp_results; 110  .. perform some computation on range1 and range2 111  and put results in tmp_results; 112  .. filter tmp_results out for some special type. 113  .. etc.... 114  // return results 115  results.swap(tmp_results); 116  } 117  118  119  ******* FAQ ******* 120  1. Why won't this code compile? 121  ------------------------ 122  class SomeClass 123  { 124  public: 125  Range<int> range; 126  }; 127  .... 128  void some_function( const SomeClass& some_class ) 129  { 130  Range<int>::iterator = some_class.range.begin(); 131  } 132  --------------------- 133  Solution: you need to use 134  Range<int>::const_iterator instead. 135  136  2. Why doesn't this work right when I try to change the 137  contents of an Range? 138  139  // make a range that has the letters A,B,C in it. 140  Range<char> my_chars('A', 'C'); 141  // make an iterator that points to 'A'. 142  Range<char>::iterator iter = my_chars.begin(); 143  // change A to D 144  *iter = 'D'; 145  // print contents of my_chars to stdout 146  std::copy(my_chars.begin(), my_chars.end(), 147  std::ostream_iterator(std::cout, " ")); 148  149  result is 150  A B C 151  instead of 152  B C D 153  154  When one calls *iter, which returns 'A', the actual storage of the value 'A' 155  which is returned is in the iterator and not in the Range. This allows 156  for multiple iterators on a single Range and the Range does not have 157  to keep track of which iterator is referencing which value. 158  159  160  161 */ 162  163 #ifndef MOAB_RANGE_HPP 164 #define MOAB_RANGE_HPP 165  166 #include <string> 167 #include <iterator> 168 #include <iosfwd> 169 #include <algorithm> 170 #include <string> 171  172 #include "moab/Types.hpp" 173  174 namespace moab 175 { 176  177 struct range_iter_tag : public std::bidirectional_iterator_tag 178 { 179 }; 180  181 struct range_base_iter 182 { 183  typedef range_iter_tag iterator_category; 184  typedef EntityID difference_type; 185  typedef EntityHandle value_type; 186  typedef EntityHandle* pointer; 187  typedef EntityHandle& reference; 188 }; 189  190 //! the class Range 191 class MOAB_EXPORT Range 192 { 193  public: 194  // forward declare the iterators 195  class const_iterator; 196  class const_reverse_iterator; 197  typedef const_iterator iterator; 198  typedef const_reverse_iterator reverse_iterator; 199  200  friend Range intersect( const Range&, const Range& ); 201  friend Range subtract( const Range&, const Range& ); 202  203  //! just like subtract, but as an operator 204  Range& operator-=( const Range& rhs ); 205  206  //! for short hand notation, lets typedef the 207  //! container class that holds the ranges 208  typedef EntityHandle value_type; 209  210  //! default constructor 211  Range(); 212  213  //! copy constructor 214  Range( const Range& copy ); 215  216  //! another constructor that takes an initial range 217  Range( EntityHandle val1, EntityHandle val2 ); 218  219  //! operator= 220  Range& operator=( const Range& copy ); 221  222  //! destructor 223  inline ~Range(); 224  225  //! return the beginning const iterator of this range 226  inline const_iterator begin() const; 227  228  //! return the beginning const reverse iterator of this range 229  inline const_reverse_iterator rbegin() const; 230  231  //! return the ending const iterator for this range 232  inline const_iterator end() const; 233  234  //! return the ending const reverse iterator for this range 235  inline const_reverse_iterator rend() const; 236  237  //! return the number of values this Ranges represents 238  size_t size() const; 239  240  //! return the number of range pairs in the list 241  size_t psize() const; 242  243  //! return whether empty or not 244  //! always use "if(!Ranges::empty())" instead of "if(Ranges::size())" 245  inline bool empty() const; 246  247  iterator insert( iterator hint, EntityHandle val ); 248  249  //! insert an item into the list and return the iterator for the inserted item 250  iterator insert( EntityHandle val ) 251  { 252  return insert( begin(), val ); 253  } 254  255  //! insert a range of items into this list and return the iterator for the first 256  //! inserted item 257  iterator insert( iterator hint, EntityHandle first, EntityHandle last ); 258  259  //! insert a range of items into this list and return the iterator for the first 260  //! inserted item 261  iterator insert( EntityHandle val1, EntityHandle val2 ) 262  { 263  return insert( begin(), val1, val2 ); 264  } 265  266  template < typename T > 267  iterator insert_list( T begin_iter, T end_iter ); 268  269  template < class T > 270  iterator insert( typename T::const_iterator begin_iter, typename T::const_iterator end_iter ) 271  { 272  return insert_list( begin_iter, end_iter ); 273  } 274  275  template < typename T > 276  iterator insert( const T* begin_iter, const T* end_iter ) 277  { 278  return insert_list( begin_iter, end_iter ); 279  } 280  281  //! remove an item from this list and return an iterator to the next item 282  iterator erase( iterator iter ); 283  284  //! remove a range of items from the list 285  iterator erase( iterator iter1, iterator iter2 ); 286  287  //! erases a value from this container 288  inline iterator erase( EntityHandle val ); 289  290  //! get first entity in range 291  inline const EntityHandle& front() const; 292  //! get last entity in range 293  inline const EntityHandle& back() const; 294  //! remove first entity from range 295  EntityHandle pop_front(); 296  //! remove last entity from range 297  EntityHandle pop_back(); 298  299  //! find an item int the list and return an iterator at that value 300  const_iterator find( EntityHandle val ) const; 301  302  //! return an iterator to the first value >= val 303  static const_iterator lower_bound( const_iterator first, const_iterator last, EntityHandle val ); 304  static const_iterator upper_bound( const_iterator first, const_iterator last, EntityHandle val ); 305  306  const_iterator lower_bound( EntityHandle val ) const 307  { 308  return lower_bound( begin(), end(), val ); 309  } 310  const_iterator upper_bound( EntityHandle val ) const 311  { 312  return upper_bound( begin(), end(), val ); 313  } 314  const_iterator lower_bound( EntityType type ) const; 315  const_iterator upper_bound( EntityType type ) const; 316  std::pair< const_iterator, const_iterator > equal_range( EntityType type ) const; 317  const_iterator lower_bound( EntityType type, const_iterator first ) const; 318  const_iterator upper_bound( EntityType type, const_iterator first ) const; 319  320  //! True if all entities in range are of passed type 321  //! (also true if range is empty) 322  bool all_of_type( EntityType type ) const; 323  //! True if all entities in range are of passed dimension 324  //! (also true if range is empty) 325  bool all_of_dimension( int dimension ) const; 326  327  unsigned num_of_type( EntityType type ) const; 328  unsigned num_of_dimension( int dim ) const; 329  330  //! clears the contents of the list 331  void clear(); 332  333  //! for debugging 334  const std::string str_rep( const char* indent_prefix = NULL ) const; 335  336  void print( const char* indent_prefix = NULL ) const; 337  void print( std::ostream& s, const char* indent_prefix = NULL ) const; 338  339  unsigned long get_memory_use() const; 340  341  double compactness() const; 342  343  void insert( Range::const_iterator begin, Range::const_iterator end ); 344  345  //! merges this Range with another range 346  void merge( const Range& range ) 347  { 348  insert( range.begin(), range.end() ); 349  } 350  351  //! merge a subset of some other range 352  void merge( Range::const_iterator beginr, Range::const_iterator endr ) 353  { 354  insert( beginr, endr ); 355  } 356  357  //! swap the contents of this range with another one 358  void swap( Range& range ); 359  360  //! check for internal consistency 361  void sanity_check() const; 362  363  //! Check if this range is a non-strict superset of some other range 364  bool contains( const Range& other ) const; 365  366  //! return a subset of this range, by type 367  Range subset_by_type( EntityType t ) const; 368  369  //! return a subset of this range, by dimension 370  Range subset_by_dimension( int dim ) const; 371  372  struct PairNode : public std::pair< EntityHandle, EntityHandle > 373  { 374  375  PairNode() : std::pair< EntityHandle, EntityHandle >( 0, 0 ), mNext( NULL ), mPrev( NULL ) {} 376  PairNode( PairNode* next, PairNode* prev, EntityHandle _first, EntityHandle _second ) 377  : std::pair< EntityHandle, EntityHandle >( _first, _second ), mNext( next ), mPrev( prev ) 378  { 379  } 380  381  PairNode* mNext; 382  PairNode* mPrev; 383  }; 384  385  EntityHandle operator[]( EntityID index ) const; 386  387  int index( EntityHandle handle ) const; 388  389  protected: 390  //! the head of the list that contains pairs that represent the ranges 391  //! this list is sorted and unique at all times 392  PairNode mHead; 393  394  //! if dead_node is not mHead, remove it from the list and free it's memory. 395  void delete_pair_node( PairNode* dead_node ); 396  397  public: 398  //! used to iterate over sub-ranges of a range 399  class MOAB_EXPORT pair_iterator : public range_base_iter 400  { 401  friend class Range; 402  403  public: 404  pair_iterator() : mNode( NULL ) {} 405  pair_iterator( PairNode* nodep ) : mNode( nodep ) {} 406  pair_iterator( const pair_iterator& copy ) : mNode( copy.mNode ) {} 407  pair_iterator( const const_iterator& copy ) : mNode( copy.mNode ) {} 408  409  std::pair< EntityHandle, EntityHandle >* operator->() 410  { 411  return mNode; 412  } 413  414  pair_iterator& operator++() 415  { 416  mNode = mNode->mNext; 417  return *this; 418  } 419  pair_iterator operator++( int ) 420  { 421  pair_iterator tmp( *this ); 422  this->operator++(); 423  return tmp; 424  } 425  426  pair_iterator& operator--() 427  { 428  mNode = mNode->mPrev; 429  return *this; 430  } 431  pair_iterator operator--( int ) 432  { 433  pair_iterator tmp( *this ); 434  this->operator--(); 435  return tmp; 436  } 437  bool operator==( const pair_iterator& other ) const 438  { 439  return mNode == other.mNode; 440  } 441  442  bool operator!=( const pair_iterator& other ) const 443  { 444  return mNode != other.mNode; 445  } 446  447  PairNode* node() 448  { 449  return mNode; 450  } 451  452  private: 453  PairNode* mNode; 454  }; 455  456  class const_pair_iterator; 457  458  //! a const iterator which iterates over an Range 459  class MOAB_EXPORT const_iterator : public range_base_iter 460  { 461  friend class Range; 462  friend class pair_iterator; 463  friend class const_pair_iterator; 464  friend EntityID operator-( const const_iterator&, const const_iterator& ); 465  466  public: 467  //! default constructor - intialize base default constructor 468  const_iterator() : mNode( NULL ), mValue( 0 ) {} 469  470  //! constructor used by Range 471  const_iterator( const PairNode* iter, const EntityHandle val ) 472  : mNode( const_cast< PairNode* >( iter ) ), mValue( val ) 473  { 474  } 475  476  //! dereference that value this iterator points to 477  //! returns a const reference 478  const EntityHandle& operator*() const 479  { 480  return mValue; 481  } 482  483  //! prefix incrementer 484  const_iterator& operator++() 485  { 486  // see if we need to increment the base iterator 487  if( mValue == mNode->second ) 488  { 489  mNode = mNode->mNext; 490  mValue = mNode->first; 491  } 492  // if not, just increment the value in the range 493  else 494  ++mValue; 495  return *this; 496  } 497  498  //! postfix incrementer 499  const_iterator operator++( int ) 500  { 501  // make a temporary copy 502  const_iterator tmp( *this ); 503  // increment self 504  this->operator++(); 505  // return the copy 506  return tmp; 507  } 508  509  //! prefix decrementer 510  const_iterator& operator--() 511  { 512  // see if we need to decrement the base iterator 513  if( mValue == mNode->first ) 514  { 515  mNode = mNode->mPrev; 516  ; 517  mValue = mNode->second; 518  } 519  // if not, just decrement the value 520  else 521  --mValue; 522  return *this; 523  } 524  525  //! postfix decrementer 526  const_iterator operator--( int ) 527  { 528  // make a copy of this 529  const_iterator tmp( *this ); 530  // decrement self 531  this->operator--(); 532  // return the copy 533  return tmp; 534  } 535  536  //! Advance iterator specified amount. 537  //! Potentially O(n), but typically better. Always 538  //! more efficient than calling operator++ step times. 539  const_iterator& operator+=( EntityID step ); 540  541  //! Regress iterator specified amount. 542  //! Potentially O(n), but typically better. Always 543  //! more efficient than calling operator-- step times. 544  const_iterator& operator-=( EntityID step ); 545  546  //! equals operator 547  bool operator==( const const_iterator& other ) const 548  { 549  // see if the base iterator is the same and the 550  // value of this iterator is the same 551  return ( mNode == other.mNode ) && ( mValue == other.mValue ); 552  } 553  554  //! not equals operator 555  bool operator!=( const const_iterator& other ) const 556  { 557  // call == operator and not it. 558  return ( mNode != other.mNode ) || ( mValue != other.mValue ); 559  } 560  561  /**\brief get an iterator at the end of the block 562  * 563  * Get an iterator at the end of the block of consecutive 564  * handles that this iterator is currently contained in. 565  * That is, if the range contains blocks of consecutive 566  * handles of the form { [1,5], [7,100], ... } and this 567  * iterator is at any handle in the range [7,100], return 568  * an iterator at the '100' handle. 569  * 570  * Never returns begin() or end() unless this iterator is 571  * at begin() or end(). May return the same location as 572  * this iterator. 573  */ 574  inline const_iterator end_of_block() const; 575  576  /**\brief get an iterator at the start of the block 577  * 578  * Get an iterator at the start of the block of consecutive 579  * handles that this iterator is currently contained in. 580  * That is, if the range contains blocks of consecutive 581  * handles of the form { [1,5], [7,100], ... } and this 582  * iterator is at any handle in the range [7,100], return 583  * an iterator at the '7' handle. 584  * 585  * Never returns end() unless this iterator is 586  * at end(). May return the same location as 587  * this iterator. 588  */ 589  inline const_iterator start_of_block() const; 590  591  protected: 592  //! the node we are pointing at 593  PairNode* mNode; 594  //! the value in the range 595  EntityHandle mValue; 596  }; 597  598  //! a const reverse iterator which iterates over an Range 599  class MOAB_EXPORT const_reverse_iterator : public range_base_iter 600  { 601  friend class Range; 602  friend class pair_iterator; 603  604  public: 605  //! default constructor - intialize base default constructor 606  const_reverse_iterator() {} 607  608  const_reverse_iterator( const_iterator fwd_iter ) : myIter( fwd_iter ) {} 609  610  //! constructor used by Range 611  const_reverse_iterator( const PairNode* iter, const EntityHandle val ) : myIter( iter, val ) {} 612  613  //! dereference that value this iterator points to 614  //! returns a const reference 615  const EntityHandle& operator*() const 616  { 617  return *myIter; 618  } 619  620  //! prefix incrementer 621  const_reverse_iterator& operator++() 622  { 623  --myIter; 624  return *this; 625  } 626  627  //! postfix incrementer 628  const_reverse_iterator operator++( int ) 629  { 630  return const_reverse_iterator( myIter-- ); 631  } 632  633  //! prefix decrementer 634  const_reverse_iterator& operator--() 635  { 636  ++myIter; 637  return *this; 638  } 639  640  //! postfix decrementer 641  const_reverse_iterator operator--( int ) 642  { 643  return const_reverse_iterator( myIter++ ); 644  } 645  646  //! Advance iterator specified amount. 647  //! Potentially O(n), but typically better. Always 648  //! more efficient than calling operator++ step times. 649  const_reverse_iterator& operator+=( EntityID step ) 650  { 651  myIter -= step; 652  return *this; 653  } 654  655  //! Regress iterator specified amount. 656  //! Potentially O(n), but typically better. Always 657  //! more efficient than calling operator-- step times. 658  const_reverse_iterator& operator-=( EntityID step ) 659  { 660  myIter += step; 661  return *this; 662  } 663  664  //! equals operator 665  bool operator==( const const_reverse_iterator& other ) const 666  { 667  return myIter == other.myIter; 668  } 669  670  //! not equals operator 671  bool operator!=( const const_reverse_iterator& other ) const 672  { 673  return myIter != other.myIter; 674  } 675  676  protected: 677  //! the node we are pointing at 678  const_iterator myIter; 679  }; 680  681  public: 682  class MOAB_EXPORT const_pair_iterator 683  { 684  public: 685  const_pair_iterator() : myNode( NULL ) {} 686  const_pair_iterator( const PairNode* node ) : myNode( node ) {} 687  const_pair_iterator( const const_iterator& i ) : myNode( i.mNode ) {} 688  689  const PairNode& operator*() const 690  { 691  return *myNode; 692  } 693  694  const PairNode* operator->() const 695  { 696  return myNode; 697  } 698  699  const_pair_iterator& operator--() 700  { 701  myNode = myNode->mPrev; 702  return *this; 703  } 704  705  const_pair_iterator& operator++() 706  { 707  myNode = myNode->mNext; 708  return *this; 709  } 710  711  const_pair_iterator operator--( int ) 712  { 713  const_pair_iterator rval( *this ); 714  this->operator--(); 715  return rval; 716  } 717  718  const_pair_iterator operator++( int ) 719  { 720  const_pair_iterator rval( *this ); 721  this->operator++(); 722  return rval; 723  } 724  725  bool operator==( const const_pair_iterator& other ) const 726  { 727  return other.myNode == myNode; 728  } 729  730  bool operator!=( const const_pair_iterator& other ) const 731  { 732  return other.myNode != myNode; 733  } 734  735  private: 736  const PairNode* myNode; 737  }; 738  739  pair_iterator pair_begin() 740  { 741  return pair_iterator( mHead.mNext ); 742  } 743  pair_iterator pair_end() 744  { 745  return pair_iterator( &mHead ); 746  } 747  748  const_pair_iterator const_pair_begin() const 749  { 750  return const_pair_iterator( mHead.mNext ); 751  } 752  const_pair_iterator const_pair_end() const 753  { 754  return const_pair_iterator( &mHead ); 755  } 756  const_pair_iterator pair_begin() const 757  { 758  return const_pair_iterator( mHead.mNext ); 759  } 760  const_pair_iterator pair_end() const 761  { 762  return const_pair_iterator( &mHead ); 763  } 764 }; 765  766 //! intersect two ranges, placing the results in the return range 767 Range intersect( const Range&, const Range& ); 768  769 //! subtract range2 from this, placing the results in the return range 770 Range subtract( const Range& from, const Range& ); 771  772 //! unite two ranges, placing the results in the return range 773 inline Range unite( const Range& r1, const Range& r2 ) 774 { 775  Range r( r1 ); 776  r.insert( r2.begin(), r2.end() ); 777  return r; 778 } 779  780 inline Range::const_iterator operator+( const Range::const_iterator& it, EntityID step ) 781 { 782  Range::const_iterator tmp( it ); 783  return tmp += step; 784 } 785  786 inline Range::const_iterator operator+( EntityID step, const Range::const_iterator& it ) 787 { 788  Range::const_iterator tmp( it ); 789  return tmp += step; 790 } 791  792 inline Range::const_iterator operator-( const Range::const_iterator& it, EntityID step ) 793 { 794  Range::const_iterator tmp( it ); 795  return tmp -= step; 796 } 797  798 inline Range::const_iterator operator-( EntityID step, const Range::const_iterator& it ) 799 { 800  Range::const_iterator tmp( it ); 801  return tmp -= step; 802 } 803  804 EntityID operator-( const Range::const_iterator& it1, const Range::const_iterator& it2 ); 805  806 //! Use as you would an STL back_inserter 807 /** 808  * e.g. std::copy(list.begin(), list.end(), range_inserter(my_range); 809  * Also, see comments/instructions at the top of this class declaration 810  */ 811 class MOAB_EXPORT range_inserter 812 { 813  814  protected: 815  Range* container; 816  817  public: 818  // constructor 819  explicit range_inserter( Range& x ) : container( &x ) {} 820  range_inserter& operator=( const Range::value_type& value ) 821  { 822  container->insert( value ); 823  return *this; 824  } 825  826  range_inserter& operator*() 827  { 828  return *this; 829  } 830  range_inserter& operator++() 831  { 832  return *this; 833  } 834  range_inserter& operator++( int ) 835  { 836  return *this; 837  } 838  839  typedef EntityHandle value_type; 840  typedef EntityID difference_type; 841  typedef std::output_iterator_tag iterator_category; 842  typedef EntityHandle* pointer; 843  typedef EntityHandle& reference; 844 }; 845  846 inline Range::Range() 847 { 848  // set the head node to point to itself 849  mHead.mNext = mHead.mPrev = &mHead; 850  mHead.first = mHead.second = 0; 851 } 852  853 //! destructor 854 inline Range::~Range() 855 { 856  clear(); 857 } 858  859 //! return the beginning const iterator of this range 860 inline Range::const_iterator Range::begin() const 861 { 862  return const_iterator( mHead.mNext, mHead.mNext->first ); 863 } 864  865 //! return the beginning const reverse iterator of this range 866 inline Range::const_reverse_iterator Range::rbegin() const 867 { 868  return const_reverse_iterator( mHead.mPrev, mHead.mPrev->second ); 869 } 870  871 //! return the ending const iterator for this range 872 inline Range::const_iterator Range::end() const 873 { 874  return const_iterator( &mHead, mHead.first ); 875 } 876  877 //! return the ending const reverse iterator for this range 878 inline Range::const_reverse_iterator Range::rend() const 879 { 880  return const_reverse_iterator( &mHead, mHead.second ); 881 } 882  883 //! return whether empty or not 884 //! always use "if(!Ranges::empty())" instead of "if(Ranges::size())" 885 inline bool Range::empty() const 886 { 887  return ( mHead.mNext == &mHead ); 888 } 889  890 //! erases a value from this container 891 inline Range::iterator Range::erase( EntityHandle val ) 892 { 893  return erase( find( val ) ); 894 } 895  896 inline Range::const_iterator Range::const_iterator::end_of_block() const 897 { 898  return Range::const_iterator( mNode, mNode->second ); 899 } 900  901 inline Range::const_iterator Range::const_iterator::start_of_block() const 902 { 903  return Range::const_iterator( mNode, mNode->first ); 904 } 905  906 //! get first entity in range 907 inline const EntityHandle& Range::front() const 908 { 909  return mHead.mNext->first; 910 } 911 //! get last entity in range 912 inline const EntityHandle& Range::back() const 913 { 914  return mHead.mPrev->second; 915 } 916  917 inline std::ostream& operator<<( std::ostream& s, const Range& r ) 918 { 919  r.print( s ); 920  return s; 921 } 922  923 bool operator==( const Range& r1, const Range& r2 ); 924 inline bool operator!=( const Range& r1, const Range& r2 ) 925 { 926  return !( r1 == r2 ); 927 } 928  929 inline EntityHandle Range::operator[]( EntityID indexp ) const 930 { 931  Range::const_iterator i = begin(); 932  i += indexp; 933  return *i; 934 } 935  936 inline int Range::index( EntityHandle handle ) const 937 { 938  if( handle < *begin() || handle > *rbegin() ) return -1; 939  940  unsigned int i = 0; 941  Range::const_pair_iterator pit = const_pair_begin(); 942  while( handle > ( *pit ).second && pit != const_pair_end() ) 943  { 944  i += ( *pit ).second - ( *pit ).first + 1; 945  ++pit; 946  } 947  if( handle < ( *pit ).first || pit == const_pair_end() ) return -1; 948  949  return i + handle - ( *pit ).first; 950 } 951  952 inline double Range::compactness() const 953 { 954  unsigned int num_ents = size(); 955  return ( num_ents ? ( (double)get_memory_use() / (double)( num_ents * sizeof( EntityHandle ) ) ) : -1 ); 956 } 957  958 template < typename Iterator > 959 Range::iterator Range::insert_list( Iterator begin_iter, Iterator end_iter ) 960 { 961  size_t n = std::distance( begin_iter, end_iter ); 962  EntityHandle* sorted = new EntityHandle[n]; 963  std::copy( begin_iter, end_iter, sorted ); 964  std::sort( sorted, sorted + n ); 965  iterator hint = begin(); 966  size_t i = 0; 967  while( i < n ) 968  { 969  size_t j = i + 1; 970  while( j < n && sorted[j] == 1 + sorted[j - 1] ) 971  ++j; 972  hint = insert( hint, sorted[i], sorted[i] + ( ( j - i ) - 1 ) ); 973  i = j; 974  } 975  delete[] sorted; 976  return hint; 977 } 978  979 inline size_t Range::psize() const 980 { 981  size_t i = 0; 982  Range::const_pair_iterator pit; 983  for( pit = const_pair_begin(), i = 0; pit != const_pair_end(); ++pit, i++ ) 984  ; 985  986  return i; 987 } 988  989 } // namespace moab 990  991 #endif // MOAB_RANGE_HPP