LCOV - code coverage report
Current view: top level - src/moab - Range.hpp (source / functions) Hit Total Coverage
Test: coverage_sk.info Lines: 180 193 93.3 %
Date: 2020-12-16 07:07:30 Functions: 69 77 89.6 %
Branches: 78 134 58.2 %

           Branch data     Line data    Source code
       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 "moab/Types.hpp"
     171                 :            : 
     172                 :            : namespace moab
     173                 :            : {
     174                 :            : 
     175                 :            : struct range_iter_tag : public std::bidirectional_iterator_tag
     176                 :            : {
     177                 :            : };
     178                 :            : 
     179                 :   65212405 : struct range_base_iter
     180                 :            : {
     181                 :            :     typedef range_iter_tag iterator_category;
     182                 :            :     typedef EntityID difference_type;
     183                 :            :     typedef EntityHandle value_type;
     184                 :            :     typedef EntityHandle* pointer;
     185                 :            :     typedef EntityHandle& reference;
     186                 :            : };
     187                 :            : 
     188                 :            : //! the class Range
     189                 :            : class Range
     190                 :            : {
     191                 :            :   public:
     192                 :            :     // forward declare the iterators
     193                 :            :     class const_iterator;
     194                 :            :     class const_reverse_iterator;
     195                 :            :     typedef const_iterator iterator;
     196                 :            :     typedef const_reverse_iterator reverse_iterator;
     197                 :            : 
     198                 :            :     friend Range intersect( const Range&, const Range& );
     199                 :            :     friend Range subtract( const Range&, const Range& );
     200                 :            : 
     201                 :            :     //! just like subtract, but as an operator
     202                 :            :     Range& operator-=( const Range& rhs );
     203                 :            : 
     204                 :            :     //! for short hand notation, lets typedef the
     205                 :            :     //! container class that holds the ranges
     206                 :            :     typedef EntityHandle value_type;
     207                 :            : 
     208                 :            :     //! default constructor
     209                 :            :     Range();
     210                 :            : 
     211                 :            :     //! copy constructor
     212                 :            :     Range( const Range& copy );
     213                 :            : 
     214                 :            :     //! another constructor that takes an initial range
     215                 :            :     Range( EntityHandle val1, EntityHandle val2 );
     216                 :            : 
     217                 :            :     //! operator=
     218                 :            :     Range& operator=( const Range& copy );
     219                 :            : 
     220                 :            :     //! destructor
     221                 :            :     inline ~Range();
     222                 :            : 
     223                 :            :     //! return the beginning const iterator of this range
     224                 :            :     inline const_iterator begin() const;
     225                 :            : 
     226                 :            :     //! return the beginning const reverse iterator of this range
     227                 :            :     inline const_reverse_iterator rbegin() const;
     228                 :            : 
     229                 :            :     //! return the ending const iterator for this range
     230                 :            :     inline const_iterator end() const;
     231                 :            : 
     232                 :            :     //! return the ending const reverse iterator for this range
     233                 :            :     inline const_reverse_iterator rend() const;
     234                 :            : 
     235                 :            :     //! return the number of values this Ranges represents
     236                 :            :     size_t size() const;
     237                 :            : 
     238                 :            :     //! return the number of range pairs in the list
     239                 :            :     size_t psize() const;
     240                 :            : 
     241                 :            :     //! return whether empty or not
     242                 :            :     //! always use "if(!Ranges::empty())" instead of "if(Ranges::size())"
     243                 :            :     inline bool empty() const;
     244                 :            : 
     245                 :            :     iterator insert( iterator hint, EntityHandle val );
     246                 :            : 
     247                 :            :     //! insert an item into the list and return the iterator for the inserted item
     248                 :    6853769 :     iterator insert( EntityHandle val )
     249                 :            :     {
     250                 :    6853769 :         return insert( begin(), val );
     251                 :            :     }
     252                 :            : 
     253                 :            :     //! insert a range of items into this list and return the iterator for the first
     254                 :            :     //! inserted item
     255                 :            :     iterator insert( iterator hint, EntityHandle first, EntityHandle last );
     256                 :            : 
     257                 :            :     //! insert a range of items into this list and return the iterator for the first
     258                 :            :     //! inserted item
     259                 :     276310 :     iterator insert( EntityHandle val1, EntityHandle val2 )
     260                 :            :     {
     261                 :     276310 :         return insert( begin(), val1, val2 );
     262                 :            :     }
     263                 :            : 
     264                 :            :     template < typename T >
     265                 :            :     iterator insert_list( T begin_iter, T end_iter );
     266                 :            : 
     267                 :            :     template < class T >
     268                 :          0 :     iterator insert( typename T::const_iterator begin_iter, typename T::const_iterator end_iter )
     269                 :            :     {
     270                 :          0 :         return insert_list( begin_iter, end_iter );
     271                 :            :     }
     272                 :            : 
     273                 :            :     template < typename T >
     274                 :          0 :     iterator insert( const T* begin_iter, const T* end_iter )
     275                 :            :     {
     276                 :          0 :         return insert_list( begin_iter, end_iter );
     277                 :            :     }
     278                 :            : 
     279                 :            :     //! remove an item from this list and return an iterator to the next item
     280                 :            :     iterator erase( iterator iter );
     281                 :            : 
     282                 :            :     //! remove a range of items from the list
     283                 :            :     iterator erase( iterator iter1, iterator iter2 );
     284                 :            : 
     285                 :            :     //! erases a value from this container
     286                 :            :     inline iterator erase( EntityHandle val );
     287                 :            : 
     288                 :            :     //! get first entity in range
     289                 :            :     inline const EntityHandle& front() const;
     290                 :            :     //! get last entity in range
     291                 :            :     inline const EntityHandle& back() const;
     292                 :            :     //! remove first entity from range
     293                 :            :     EntityHandle pop_front();
     294                 :            :     //! remove last entity from range
     295                 :            :     EntityHandle pop_back();
     296                 :            : 
     297                 :            :     //! find an item int the list and return an iterator at that value
     298                 :            :     const_iterator find( EntityHandle val ) const;
     299                 :            : 
     300                 :            :     //! return an iterator to the first value >= val
     301                 :            :     static const_iterator lower_bound( const_iterator first, const_iterator last, EntityHandle val );
     302                 :            :     static const_iterator upper_bound( const_iterator first, const_iterator last, EntityHandle val );
     303                 :            : 
     304                 :          0 :     const_iterator lower_bound( EntityHandle val ) const
     305                 :            :     {
     306                 :          0 :         return lower_bound( begin(), end(), val );
     307                 :            :     }
     308                 :          0 :     const_iterator upper_bound( EntityHandle val ) const
     309                 :            :     {
     310                 :          0 :         return upper_bound( begin(), end(), val );
     311                 :            :     }
     312                 :            :     const_iterator lower_bound( EntityType type ) const;
     313                 :            :     const_iterator upper_bound( EntityType type ) const;
     314                 :            :     std::pair< const_iterator, const_iterator > equal_range( EntityType type ) const;
     315                 :            :     const_iterator lower_bound( EntityType type, const_iterator first ) const;
     316                 :            :     const_iterator upper_bound( EntityType type, const_iterator first ) const;
     317                 :            : 
     318                 :            :     //! True if all entities in range are of passed type
     319                 :            :     //! (also true if range is empty)
     320                 :            :     bool all_of_type( EntityType type ) const;
     321                 :            :     //! True if all entities in range are of passed dimension
     322                 :            :     //! (also true if range is empty)
     323                 :            :     bool all_of_dimension( int dimension ) const;
     324                 :            : 
     325                 :            :     unsigned num_of_type( EntityType type ) const;
     326                 :            :     unsigned num_of_dimension( int dim ) const;
     327                 :            : 
     328                 :            :     //! clears the contents of the list
     329                 :            :     void clear();
     330                 :            : 
     331                 :            :     //! for debugging
     332                 :            :     const std::string str_rep( const char* indent_prefix = NULL ) const;
     333                 :            : 
     334                 :            :     void print( const char* indent_prefix = NULL ) const;
     335                 :            :     void print( std::ostream& s, const char* indent_prefix = NULL ) const;
     336                 :            : 
     337                 :            :     unsigned long get_memory_use() const;
     338                 :            : 
     339                 :            :     double compactness() const;
     340                 :            : 
     341                 :            :     void insert( Range::const_iterator begin, Range::const_iterator end );
     342                 :            : 
     343                 :            :     //! merges this Range with another range
     344                 :     274325 :     void merge( const Range& range )
     345                 :            :     {
     346                 :     274325 :         insert( range.begin(), range.end() );
     347                 :     274325 :     }
     348                 :            : 
     349                 :            :     //! merge a subset of some other range
     350                 :      28293 :     void merge( Range::const_iterator beginr, Range::const_iterator endr )
     351                 :            :     {
     352                 :      28293 :         insert( beginr, endr );
     353                 :      28293 :     }
     354                 :            : 
     355                 :            :     //! swap the contents of this range with another one
     356                 :            :     void swap( Range& range );
     357                 :            : 
     358                 :            :     //! check for internal consistency
     359                 :            :     void sanity_check() const;
     360                 :            : 
     361                 :            :     //! Check if this range is a non-strict superset of some other range
     362                 :            :     bool contains( const Range& other ) const;
     363                 :            : 
     364                 :            :     //! return a subset of this range, by type
     365                 :            :     Range subset_by_type( EntityType t ) const;
     366                 :            : 
     367                 :            :     //! return a subset of this range, by dimension
     368                 :            :     Range subset_by_dimension( int dim ) const;
     369                 :            : 
     370                 :            :     struct PairNode : public std::pair< EntityHandle, EntityHandle >
     371                 :            :     {
     372                 :            : 
     373         [ +  - ]:     890216 :         PairNode() : std::pair< EntityHandle, EntityHandle >( 0, 0 ), mNext( NULL ), mPrev( NULL ) {}
     374                 :    4597395 :         PairNode( PairNode* next, PairNode* prev, EntityHandle _first, EntityHandle _second )
     375                 :    4597395 :             : std::pair< EntityHandle, EntityHandle >( _first, _second ), mNext( next ), mPrev( prev )
     376                 :            :         {
     377                 :    4597395 :         }
     378                 :            : 
     379                 :            :         PairNode* mNext;
     380                 :            :         PairNode* mPrev;
     381                 :            :     };
     382                 :            : 
     383                 :            :     EntityHandle operator[]( EntityID index ) const;
     384                 :            : 
     385                 :            :     int index( EntityHandle handle ) const;
     386                 :            : 
     387                 :            :   protected:
     388                 :            :     //! the head of the list that contains pairs that represent the ranges
     389                 :            :     //! this list is sorted and unique at all times
     390                 :            :     PairNode mHead;
     391                 :            : 
     392                 :            :     //! if dead_node is not mHead, remove it from the list and free it's memory.
     393                 :            :     void delete_pair_node( PairNode* dead_node );
     394                 :            : 
     395                 :            :   public:
     396                 :            :     //! used to iterate over sub-ranges of a range
     397                 :            :     class pair_iterator : public range_base_iter
     398                 :            :     {
     399                 :            :         friend class Range;
     400                 :            : 
     401                 :            :       public:
     402                 :            :         pair_iterator() : mNode( NULL ) {}
     403                 :     208324 :         pair_iterator( PairNode* nodep ) : mNode( nodep ) {}
     404                 :            :         pair_iterator( const pair_iterator& copy ) : mNode( copy.mNode ) {}
     405                 :    2383454 :         pair_iterator( const const_iterator& copy ) : mNode( copy.mNode ) {}
     406                 :            : 
     407                 :    3831468 :         std::pair< EntityHandle, EntityHandle >* operator->()
     408                 :            :         {
     409                 :    3831468 :             return mNode;
     410                 :            :         }
     411                 :            : 
     412                 :     431774 :         pair_iterator& operator++()
     413                 :            :         {
     414                 :     431774 :             mNode = mNode->mNext;
     415                 :     431774 :             return *this;
     416                 :            :         }
     417                 :            :         pair_iterator operator++( int )
     418                 :            :         {
     419                 :            :             pair_iterator tmp( *this );
     420                 :            :             this->operator++();
     421                 :            :             return tmp;
     422                 :            :         }
     423                 :            : 
     424                 :            :         pair_iterator& operator--()
     425                 :            :         {
     426                 :            :             mNode = mNode->mPrev;
     427                 :            :             return *this;
     428                 :            :         }
     429                 :            :         pair_iterator operator--( int )
     430                 :            :         {
     431                 :            :             pair_iterator tmp( *this );
     432                 :            :             this->operator--();
     433                 :            :             return tmp;
     434                 :            :         }
     435                 :     325167 :         bool operator==( const pair_iterator& other ) const
     436                 :            :         {
     437                 :     325167 :             return mNode == other.mNode;
     438                 :            :         }
     439                 :            : 
     440                 :     863719 :         bool operator!=( const pair_iterator& other ) const
     441                 :            :         {
     442                 :     863719 :             return mNode != other.mNode;
     443                 :            :         }
     444                 :            : 
     445                 :     436930 :         PairNode* node()
     446                 :            :         {
     447                 :     436930 :             return mNode;
     448                 :            :         }
     449                 :            : 
     450                 :            :       private:
     451                 :            :         PairNode* mNode;
     452                 :            :     };
     453                 :            : 
     454                 :            :     class const_pair_iterator;
     455                 :            : 
     456                 :            :     //! a const iterator which iterates over an Range
     457                 :            :     class const_iterator : public range_base_iter
     458                 :            :     {
     459                 :            :         friend class Range;
     460                 :            :         friend class pair_iterator;
     461                 :            :         friend class const_pair_iterator;
     462                 :            :         friend EntityID operator-( const const_iterator&, const const_iterator& );
     463                 :            : 
     464                 :            :       public:
     465                 :            :         //! default constructor - intialize base default constructor
     466                 :     534036 :         const_iterator() : mNode( NULL ), mValue( 0 ) {}
     467                 :            : 
     468                 :            :         //! constructor used by Range
     469                 :   58987704 :         const_iterator( const PairNode* iter, const EntityHandle val )
     470                 :   58987704 :             : mNode( const_cast< PairNode* >( iter ) ), mValue( val )
     471                 :            :         {
     472                 :   58987704 :         }
     473                 :            : 
     474                 :            :         //! dereference that value this iterator points to
     475                 :            :         //! returns a const reference
     476                 :   30925589 :         const EntityHandle& operator*() const
     477                 :            :         {
     478                 :   30925589 :             return mValue;
     479                 :            :         }
     480                 :            : 
     481                 :            :         //! prefix incrementer
     482                 :   12014193 :         const_iterator& operator++()
     483                 :            :         {
     484                 :            :             // see if we need to increment the base iterator
     485         [ +  + ]:   12014193 :             if( mValue == mNode->second )
     486                 :            :             {
     487                 :    2463939 :                 mNode  = mNode->mNext;
     488                 :    2463939 :                 mValue = mNode->first;
     489                 :            :             }
     490                 :            :             // if not, just increment the value in the range
     491                 :            :             else
     492                 :    9550254 :                 ++mValue;
     493                 :   12014193 :             return *this;
     494                 :            :         }
     495                 :            : 
     496                 :            :         //! postfix incrementer
     497                 :      95240 :         const_iterator operator++( int )
     498                 :            :         {
     499                 :            :             // make a temporary copy
     500                 :      95240 :             const_iterator tmp( *this );
     501                 :            :             // increment self
     502         [ +  - ]:      95240 :             this->operator++();
     503                 :            :             // return the copy
     504                 :      95240 :             return tmp;
     505                 :            :         }
     506                 :            : 
     507                 :            :         //! prefix decrementer
     508                 :     914556 :         const_iterator& operator--()
     509                 :            :         {
     510                 :            :             // see if we need to decrement the base iterator
     511         [ +  + ]:     914556 :             if( mValue == mNode->first )
     512                 :            :             {
     513                 :     300993 :                 mNode = mNode->mPrev;
     514                 :            :                 ;
     515                 :     300993 :                 mValue = mNode->second;
     516                 :            :             }
     517                 :            :             // if not, just decrement the value
     518                 :            :             else
     519                 :     613563 :                 --mValue;
     520                 :     914556 :             return *this;
     521                 :            :         }
     522                 :            : 
     523                 :            :         //! postfix decrementer
     524                 :         12 :         const_iterator operator--( int )
     525                 :            :         {
     526                 :            :             // make a copy of this
     527                 :         12 :             const_iterator tmp( *this );
     528                 :            :             // decrement self
     529         [ +  - ]:         12 :             this->operator--();
     530                 :            :             // return the copy
     531                 :         12 :             return tmp;
     532                 :            :         }
     533                 :            : 
     534                 :            :         //! Advance iterator specified amount.
     535                 :            :         //! Potentially O(n), but typically better.  Always
     536                 :            :         //! more efficient than calling operator++ step times.
     537                 :            :         const_iterator& operator+=( EntityID step );
     538                 :            : 
     539                 :            :         //! Regress iterator specified amount.
     540                 :            :         //! Potentially O(n), but typically better.  Always
     541                 :            :         //! more efficient than calling operator-- step times.
     542                 :            :         const_iterator& operator-=( EntityID step );
     543                 :            : 
     544                 :            :         //! equals operator
     545                 :   12311747 :         bool operator==( const const_iterator& other ) const
     546                 :            :         {
     547                 :            :             // see if the base iterator is the same and the
     548                 :            :             // value of this iterator is the same
     549 [ +  + ][ +  + ]:   12311747 :             return ( mNode == other.mNode ) && ( mValue == other.mValue );
     550                 :            :         }
     551                 :            : 
     552                 :            :         //! not equals operator
     553                 :   12339846 :         bool operator!=( const const_iterator& other ) const
     554                 :            :         {
     555                 :            :             // call == operator and not it.
     556 [ +  + ][ +  + ]:   12339846 :             return ( mNode != other.mNode ) || ( mValue != other.mValue );
     557                 :            :         }
     558                 :            : 
     559                 :            :         /**\brief get an iterator at the end of the block
     560                 :            :          *
     561                 :            :          * Get an iterator at the end of the block of consecutive
     562                 :            :          * handles that this iterator is currently contained in.
     563                 :            :          * That is, if the range contains blocks of consecutive
     564                 :            :          * handles of the form { [1,5], [7,100], ... } and this
     565                 :            :          * iterator is at any handle in the range [7,100], return
     566                 :            :          * an iterator at the '100' handle.
     567                 :            :          *
     568                 :            :          * Never returns begin() or end() unless this iterator is
     569                 :            :          * at begin() or end().  May return the same location as
     570                 :            :          * this iterator.
     571                 :            :          */
     572                 :            :         inline const_iterator end_of_block() const;
     573                 :            : 
     574                 :            :         /**\brief get an iterator at the start of the block
     575                 :            :          *
     576                 :            :          * Get an iterator at the start of the block of consecutive
     577                 :            :          * handles that this iterator is currently contained in.
     578                 :            :          * That is, if the range contains blocks of consecutive
     579                 :            :          * handles of the form { [1,5], [7,100], ... } and this
     580                 :            :          * iterator is at any handle in the range [7,100], return
     581                 :            :          * an iterator at the '7' handle.
     582                 :            :          *
     583                 :            :          * Never returns end() unless this iterator is
     584                 :            :          * at end().  May return the same location as
     585                 :            :          * this iterator.
     586                 :            :          */
     587                 :            :         inline const_iterator start_of_block() const;
     588                 :            : 
     589                 :            :       protected:
     590                 :            :         //! the node we are pointing at
     591                 :            :         PairNode* mNode;
     592                 :            :         //! the value in the range
     593                 :            :         EntityHandle mValue;
     594                 :            :     };
     595                 :            : 
     596                 :            :     //! a const reverse iterator which iterates over an Range
     597                 :            :     class const_reverse_iterator : public range_base_iter
     598                 :            :     {
     599                 :            :         friend class Range;
     600                 :            :         friend class pair_iterator;
     601                 :            : 
     602                 :            :       public:
     603                 :            :         //! default constructor - intialize base default constructor
     604                 :          2 :         const_reverse_iterator() {}
     605                 :            : 
     606                 :         24 :         const_reverse_iterator( const_iterator fwd_iter ) : myIter( fwd_iter ) {}
     607                 :            : 
     608                 :            :         //! constructor used by Range
     609                 :    9323562 :         const_reverse_iterator( const PairNode* iter, const EntityHandle val ) : myIter( iter, val ) {}
     610                 :            : 
     611                 :            :         //! dereference that value this iterator points to
     612                 :            :         //! returns a const reference
     613                 :    5513144 :         const EntityHandle& operator*() const
     614                 :            :         {
     615                 :    5513144 :             return *myIter;
     616                 :            :         }
     617                 :            : 
     618                 :            :         //! prefix incrementer
     619                 :     910522 :         const_reverse_iterator& operator++()
     620                 :            :         {
     621                 :     910522 :             --myIter;
     622                 :     910522 :             return *this;
     623                 :            :         }
     624                 :            : 
     625                 :            :         //! postfix incrementer
     626                 :         12 :         const_reverse_iterator operator++( int )
     627                 :            :         {
     628                 :         12 :             return const_reverse_iterator( myIter-- );
     629                 :            :         }
     630                 :            : 
     631                 :            :         //! prefix decrementer
     632                 :            :         const_reverse_iterator& operator--()
     633                 :            :         {
     634                 :            :             ++myIter;
     635                 :            :             return *this;
     636                 :            :         }
     637                 :            : 
     638                 :            :         //! postfix decrementer
     639                 :            :         const_reverse_iterator operator--( int )
     640                 :            :         {
     641                 :            :             return const_reverse_iterator( myIter++ );
     642                 :            :         }
     643                 :            : 
     644                 :            :         //! Advance iterator specified amount.
     645                 :            :         //! Potentially O(n), but typically better.  Always
     646                 :            :         //! more efficient than calling operator++ step times.
     647                 :            :         const_reverse_iterator& operator+=( EntityID step )
     648                 :            :         {
     649                 :            :             myIter -= step;
     650                 :            :             return *this;
     651                 :            :         }
     652                 :            : 
     653                 :            :         //! Regress iterator specified amount.
     654                 :            :         //! Potentially O(n), but typically better.  Always
     655                 :            :         //! more efficient than calling operator-- step times.
     656                 :            :         const_reverse_iterator& operator-=( EntityID step )
     657                 :            :         {
     658                 :            :             myIter += step;
     659                 :            :             return *this;
     660                 :            :         }
     661                 :            : 
     662                 :            :         //! equals operator
     663                 :            :         bool operator==( const const_reverse_iterator& other ) const
     664                 :            :         {
     665                 :            :             return myIter == other.myIter;
     666                 :            :         }
     667                 :            : 
     668                 :            :         //! not equals operator
     669                 :     925856 :         bool operator!=( const const_reverse_iterator& other ) const
     670                 :            :         {
     671                 :     925856 :             return myIter != other.myIter;
     672                 :            :         }
     673                 :            : 
     674                 :            :       protected:
     675                 :            :         //! the node we are pointing at
     676                 :            :         const_iterator myIter;
     677                 :            :     };
     678                 :            : 
     679                 :            :   public:
     680                 :            :     class const_pair_iterator
     681                 :            :     {
     682                 :            :       public:
     683                 :       2795 :         const_pair_iterator() : myNode( NULL ) {}
     684                 :   10972321 :         const_pair_iterator( const PairNode* node ) : myNode( node ) {}
     685                 :    1236301 :         const_pair_iterator( const const_iterator& i ) : myNode( i.mNode ) {}
     686                 :            : 
     687                 :   13122528 :         const PairNode& operator*() const
     688                 :            :         {
     689                 :   13122528 :             return *myNode;
     690                 :            :         }
     691                 :            : 
     692                 :   10498146 :         const PairNode* operator->() const
     693                 :            :         {
     694                 :   10498146 :             return myNode;
     695                 :            :         }
     696                 :            : 
     697                 :      88050 :         const_pair_iterator& operator--()
     698                 :            :         {
     699                 :      88050 :             myNode = myNode->mPrev;
     700                 :      88050 :             return *this;
     701                 :            :         }
     702                 :            : 
     703                 :    2498431 :         const_pair_iterator& operator++()
     704                 :            :         {
     705                 :    2498431 :             myNode = myNode->mNext;
     706                 :    2498431 :             return *this;
     707                 :            :         }
     708                 :            : 
     709                 :            :         const_pair_iterator operator--( int )
     710                 :            :         {
     711                 :            :             const_pair_iterator rval( *this );
     712                 :            :             this->operator--();
     713                 :            :             return rval;
     714                 :            :         }
     715                 :            : 
     716                 :            :         const_pair_iterator operator++( int )
     717                 :            :         {
     718                 :            :             const_pair_iterator rval( *this );
     719                 :            :             this->operator++();
     720                 :            :             return rval;
     721                 :            :         }
     722                 :            : 
     723                 :    3723863 :         bool operator==( const const_pair_iterator& other ) const
     724                 :            :         {
     725                 :    3723863 :             return other.myNode == myNode;
     726                 :            :         }
     727                 :            : 
     728                 :    4708711 :         bool operator!=( const const_pair_iterator& other ) const
     729                 :            :         {
     730                 :    4708711 :             return other.myNode != myNode;
     731                 :            :         }
     732                 :            : 
     733                 :            :       private:
     734                 :            :         const PairNode* myNode;
     735                 :            :     };
     736                 :            : 
     737                 :     104162 :     pair_iterator pair_begin()
     738                 :            :     {
     739                 :     104162 :         return pair_iterator( mHead.mNext );
     740                 :            :     }
     741                 :          0 :     pair_iterator pair_end()
     742                 :            :     {
     743                 :          0 :         return pair_iterator( &mHead );
     744                 :            :     }
     745                 :            : 
     746                 :    3927323 :     const_pair_iterator const_pair_begin() const
     747                 :            :     {
     748                 :    3927323 :         return const_pair_iterator( mHead.mNext );
     749                 :            :     }
     750                 :    7044854 :     const_pair_iterator const_pair_end() const
     751                 :            :     {
     752                 :    7044854 :         return const_pair_iterator( &mHead );
     753                 :            :     }
     754                 :         48 :     const_pair_iterator pair_begin() const
     755                 :            :     {
     756                 :         48 :         return const_pair_iterator( mHead.mNext );
     757                 :            :     }
     758                 :         96 :     const_pair_iterator pair_end() const
     759                 :            :     {
     760                 :         96 :         return const_pair_iterator( &mHead );
     761                 :            :     }
     762                 :            : };
     763                 :            : 
     764                 :            : //! intersect two ranges, placing the results in the return range
     765                 :            : Range intersect( const Range&, const Range& );
     766                 :            : 
     767                 :            : //! subtract range2 from this, placing the results in the return range
     768                 :            : Range subtract( const Range& from, const Range& );
     769                 :            : 
     770                 :            : //! unite two ranges, placing the results in the return range
     771                 :          9 : inline Range unite( const Range& r1, const Range& r2 )
     772                 :            : {
     773                 :          9 :     Range r( r1 );
     774 [ +  - ][ +  - ]:          9 :     r.insert( r2.begin(), r2.end() );
                 [ +  - ]
     775                 :          9 :     return r;
     776                 :            : }
     777                 :            : 
     778                 :     121541 : inline Range::const_iterator operator+( const Range::const_iterator& it, EntityID step )
     779                 :            : {
     780                 :     121541 :     Range::const_iterator tmp( it );
     781         [ +  - ]:     121541 :     return tmp += step;
     782                 :            : }
     783                 :            : 
     784                 :            : inline Range::const_iterator operator+( EntityID step, const Range::const_iterator& it )
     785                 :            : {
     786                 :            :     Range::const_iterator tmp( it );
     787                 :            :     return tmp += step;
     788                 :            : }
     789                 :            : 
     790                 :        178 : inline Range::const_iterator operator-( const Range::const_iterator& it, EntityID step )
     791                 :            : {
     792                 :        178 :     Range::const_iterator tmp( it );
     793         [ +  - ]:        178 :     return tmp -= step;
     794                 :            : }
     795                 :            : 
     796                 :            : inline Range::const_iterator operator-( EntityID step, const Range::const_iterator& it )
     797                 :            : {
     798                 :            :     Range::const_iterator tmp( it );
     799                 :            :     return tmp -= step;
     800                 :            : }
     801                 :            : 
     802                 :            : EntityID operator-( const Range::const_iterator& it1, const Range::const_iterator& it2 );
     803                 :            : 
     804                 :            : //! Use as you would an STL back_inserter
     805                 :            : /**
     806                 :            :  *  e.g. std::copy(list.begin(), list.end(), range_inserter(my_range);
     807                 :            :  * Also, see comments/instructions at the top of this class declaration
     808                 :            :  */
     809                 :            : class range_inserter
     810                 :            : {
     811                 :            : 
     812                 :            :   protected:
     813                 :            :     Range* container;
     814                 :            : 
     815                 :            :   public:
     816                 :            :     // constructor
     817                 :     416753 :     explicit range_inserter( Range& x ) : container( &x ) {}
     818                 :    1472345 :     range_inserter& operator=( const Range::value_type& value )
     819                 :            :     {
     820                 :    1472345 :         container->insert( value );
     821                 :    1472345 :         return *this;
     822                 :            :     }
     823                 :            : 
     824                 :    1472345 :     range_inserter& operator*()
     825                 :            :     {
     826                 :    1472345 :         return *this;
     827                 :            :     }
     828                 :    1472345 :     range_inserter& operator++()
     829                 :            :     {
     830                 :    1472345 :         return *this;
     831                 :            :     }
     832                 :            :     range_inserter& operator++( int )
     833                 :            :     {
     834                 :            :         return *this;
     835                 :            :     }
     836                 :            : 
     837                 :            :     typedef EntityHandle value_type;
     838                 :            :     typedef EntityID difference_type;
     839                 :            :     typedef std::output_iterator_tag iterator_category;
     840                 :            :     typedef EntityHandle* pointer;
     841                 :            :     typedef EntityHandle& reference;
     842                 :            : };
     843                 :            : 
     844                 :    1362632 : inline Range::Range()
     845                 :            : {
     846                 :            :     // set the head node to point to itself
     847                 :     681316 :     mHead.mNext = mHead.mPrev = &mHead;
     848                 :     681316 :     mHead.first = mHead.second = 0;
     849                 :     681316 : }
     850                 :            : 
     851                 :            : //! destructor
     852                 :     890196 : inline Range::~Range()
     853                 :            : {
     854                 :     890196 :     clear();
     855                 :     890196 : }
     856                 :            : 
     857                 :            : //! return the beginning const iterator of this range
     858                 :   13718600 : inline Range::const_iterator Range::begin() const
     859                 :            : {
     860                 :   13718600 :     return const_iterator( mHead.mNext, mHead.mNext->first );
     861                 :            : }
     862                 :            : 
     863                 :            : //! return the beginning const reverse iterator of this range
     864                 :    3735925 : inline Range::const_reverse_iterator Range::rbegin() const
     865                 :            : {
     866                 :    3735925 :     return const_reverse_iterator( mHead.mPrev, mHead.mPrev->second );
     867                 :            : }
     868                 :            : 
     869                 :            : //! return the ending const iterator for this range
     870                 :   22206910 : inline Range::const_iterator Range::end() const
     871                 :            : {
     872                 :   22206910 :     return const_iterator( &mHead, mHead.first );
     873                 :            : }
     874                 :            : 
     875                 :            : //! return the ending const reverse iterator for this range
     876                 :     925856 : inline Range::const_reverse_iterator Range::rend() const
     877                 :            : {
     878                 :     925856 :     return const_reverse_iterator( &mHead, mHead.second );
     879                 :            : }
     880                 :            : 
     881                 :            : //! return whether empty or not
     882                 :            : //! always use "if(!Ranges::empty())" instead of "if(Ranges::size())"
     883                 :     438188 : inline bool Range::empty() const
     884                 :            : {
     885                 :     438188 :     return ( mHead.mNext == &mHead );
     886                 :            : }
     887                 :            : 
     888                 :            : //! erases a value from this container
     889                 :      61481 : inline Range::iterator Range::erase( EntityHandle val )
     890                 :            : {
     891                 :      61481 :     return erase( find( val ) );
     892                 :            : }
     893                 :            : 
     894                 :       2194 : inline Range::const_iterator Range::const_iterator::end_of_block() const
     895                 :            : {
     896                 :       2194 :     return Range::const_iterator( mNode, mNode->second );
     897                 :            : }
     898                 :            : 
     899                 :        661 : inline Range::const_iterator Range::const_iterator::start_of_block() const
     900                 :            : {
     901                 :        661 :     return Range::const_iterator( mNode, mNode->first );
     902                 :            : }
     903                 :            : 
     904                 :            : //! get first entity in range
     905                 :      31354 : inline const EntityHandle& Range::front() const
     906                 :            : {
     907                 :      31354 :     return mHead.mNext->first;
     908                 :            : }
     909                 :            : //! get last entity in range
     910                 :      30635 : inline const EntityHandle& Range::back() const
     911                 :            : {
     912                 :      30635 :     return mHead.mPrev->second;
     913                 :            : }
     914                 :            : 
     915                 :          0 : inline std::ostream& operator<<( std::ostream& s, const Range& r )
     916                 :            : {
     917                 :          0 :     r.print( s );
     918                 :          0 :     return s;
     919                 :            : }
     920                 :            : 
     921                 :            : bool operator==( const Range& r1, const Range& r2 );
     922                 :        236 : inline bool operator!=( const Range& r1, const Range& r2 )
     923                 :            : {
     924                 :        236 :     return !( r1 == r2 );
     925                 :            : }
     926                 :            : 
     927                 :     101145 : inline EntityHandle Range::operator[]( EntityID indexp ) const
     928                 :            : {
     929         [ +  - ]:     101145 :     Range::const_iterator i = begin();
     930         [ +  - ]:     101145 :     i += indexp;
     931         [ +  - ]:     101145 :     return *i;
     932                 :            : }
     933                 :            : 
     934                 :    3720595 : inline int Range::index( EntityHandle handle ) const
     935                 :            : {
     936 [ +  - ][ +  - ]:    3720595 :     if( handle < *begin() || handle > *rbegin() ) return -1;
         [ +  - ][ +  - ]
         [ +  - ][ +  + ]
         [ +  - ][ +  - ]
                 [ +  + ]
           [ #  #  #  # ]
     937                 :            : 
     938                 :    3720576 :     unsigned int i                 = 0;
     939         [ +  - ]:    3720576 :     Range::const_pair_iterator pit = const_pair_begin();
     940 [ +  - ][ +  + ]:    4347344 :     while( handle > ( *pit ).second && pit != const_pair_end() )
         [ +  - ][ +  - ]
         [ +  - ][ +  + ]
           [ +  +  #  # ]
     941                 :            :     {
     942 [ +  - ][ +  - ]:     626768 :         i += ( *pit ).second - ( *pit ).first + 1;
     943         [ +  - ]:     626768 :         ++pit;
     944                 :            :     }
     945 [ +  - ][ +  - ]:    3720576 :     if( handle < ( *pit ).first || pit == const_pair_end() ) return -1;
         [ +  - ][ +  - ]
         [ -  + ][ +  - ]
         [ -  + ][ #  # ]
     946                 :            : 
     947         [ +  - ]:    3720595 :     return i + handle - ( *pit ).first;
     948                 :            : }
     949                 :            : 
     950                 :          5 : inline double Range::compactness() const
     951                 :            : {
     952                 :          5 :     unsigned int num_ents = size();
     953         [ -  + ]:          5 :     return ( num_ents ? ( (double)get_memory_use() / (double)( num_ents * sizeof( EntityHandle ) ) ) : -1 );
     954                 :            : }
     955                 :            : 
     956                 :            : template < typename Iterator >
     957                 :         15 : Range::iterator Range::insert_list( Iterator begin_iter, Iterator end_iter )
     958                 :            : {
     959         [ +  - ]:         15 :     size_t n             = std::distance( begin_iter, end_iter );
     960 [ +  - ][ +  - ]:         15 :     EntityHandle* sorted = new EntityHandle[n];
     961         [ +  - ]:         15 :     std::copy( begin_iter, end_iter, sorted );
     962         [ +  - ]:         15 :     std::sort( sorted, sorted + n );
     963         [ +  - ]:         15 :     iterator hint = begin();
     964                 :         15 :     size_t i      = 0;
     965         [ +  + ]:         34 :     while( i < n )
     966                 :            :     {
     967                 :         19 :         size_t j = i + 1;
     968 [ +  + ][ +  + ]:         56 :         while( j < n && sorted[j] == 1 + sorted[j - 1] )
     969                 :         37 :             ++j;
     970         [ +  - ]:         19 :         hint = insert( hint, sorted[i], sorted[i] + ( ( j - i ) - 1 ) );
     971                 :         19 :         i    = j;
     972                 :            :     }
     973         [ +  - ]:         15 :     delete[] sorted;
     974                 :         15 :     return hint;
     975                 :            : }
     976                 :            : 
     977                 :        107 : inline size_t Range::psize() const
     978                 :            : {
     979                 :        107 :     size_t i = 0;
     980         [ +  - ]:        107 :     Range::const_pair_iterator pit;
     981 [ +  - ][ +  - ]:        214 :     for( pit = const_pair_begin(), i = 0; pit != const_pair_end(); ++pit, i++ )
         [ +  - ][ +  - ]
                 [ +  + ]
     982                 :            :         ;
     983                 :            : 
     984                 :        107 :     return i;
     985                 :            : }
     986                 :            : 
     987                 :            : }  // namespace moab
     988                 :            : 
     989                 :            : #endif  // MOAB_RANGE_HPP

Generated by: LCOV version 1.11