LCOV - code coverage report
Current view: top level - src/moab - RangeMap.hpp (source / functions) Hit Total Coverage
Test: coverage_sk.info Lines: 62 120 51.7 %
Date: 2020-12-16 07:07:30 Functions: 25 35 71.4 %
Branches: 100 380 26.3 %

           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                 :            : /**\file RangeMap.hpp
      17                 :            :  *\author Jason Kraftcheck ([email protected])
      18                 :            :  *\date 2007-04-25
      19                 :            :  */
      20                 :            : 
      21                 :            : #ifndef MOAB_RANGE_MAP_HPP
      22                 :            : #define MOAB_RANGE_MAP_HPP
      23                 :            : 
      24                 :            : #include <vector>
      25                 :            : #include <algorithm>
      26                 :            : 
      27                 :            : namespace moab
      28                 :            : {
      29                 :            : 
      30                 :            : /**\brief Map ranges of values
      31                 :            :  *
      32                 :            :  * This class provides a map between ranges of values, such as
      33                 :            :  * a map between file IDs and EntityHandles.  It is intended
      34                 :            :  * for use in situations where there are relatively few insertions
      35                 :            :  * of large contiguous ranges of values.
      36                 :            :  */
      37                 :            : template < typename KeyType, typename ValType, ValType NullVal = 0 >
      38                 :       1388 : class RangeMap
      39                 :            : {
      40                 :            :   public:
      41                 :            :     typedef KeyType key_type;
      42                 :            :     typedef ValType value_type;
      43                 :            : 
      44                 :            :     struct Range
      45                 :            :     {
      46                 :            :         KeyType begin, count;
      47                 :            :         ValType value;
      48                 :    1352549 :         bool operator<( const Range& other ) const
      49                 :            :         {
      50                 :    1352549 :             return begin + count <= other.begin;
      51                 :            :         }  // equal if overlapping!
      52                 :            :     };
      53                 :            :     typedef typename std::vector< Range > RangeList;
      54                 :            :     typedef typename RangeList::const_iterator iterator;
      55                 :            :     typedef typename RangeList::const_iterator const_iterator;
      56                 :            : 
      57                 :        236 :     inline bool empty() const
      58                 :            :     {
      59                 :        236 :         return data.empty();
      60                 :            :     }
      61                 :            : 
      62                 :        170 :     inline const Range& back() const
      63                 :            :     {
      64                 :        170 :         return data.back();
      65                 :            :     }
      66                 :            :     inline const Range& front() const
      67                 :            :     {
      68                 :            :         return data.front();
      69                 :            :     }
      70                 :            : 
      71                 :            :     /**\brief Insert mapping between range of keys and range of values
      72                 :            :      *
      73                 :            :      * Insert mapping from [first_key, first_key+count) to [first_val, first_val+count)
      74                 :            :      *
      75                 :            :      * Input range of keys many not overlap any other input range.  If it does overlap
      76                 :            :      * an existing range, the second value of the pair will be returned as false
      77                 :            :      * and the iterator will point to (one of) the overlapping ranges.
      78                 :            :      */
      79                 :            :     inline std::pair< iterator, bool > insert( KeyType first_key, ValType first_val, KeyType count );
      80                 :            : 
      81                 :            :     /**\brief Insert mapping between range of keys and range of values
      82                 :            :      *
      83                 :            :      * Insert mapping from [first_key, first_key+count) to [first_val, first_val+count)
      84                 :            :      *
      85                 :            :      * Input range of keys many not overlap any other input range.  If it does overlap
      86                 :            :      * an existing range, the second value of the pair will be returned as false
      87                 :            :      * and the iterator will point to (one of) the overlapping ranges.
      88                 :            :      */
      89                 :            :     inline bool merge( const RangeMap< KeyType, ValType, NullVal >& other );
      90                 :            : 
      91                 :            :     /** Find the value corresponding to the specified key.  Returns NullVal if not found */
      92                 :            :     inline ValType find( KeyType key ) const;
      93                 :            : 
      94                 :            :     /** Find the value corresponding to the specified key.  Returns false if not found */
      95                 :            :     inline bool find( KeyType key, ValType& val_out ) const;
      96                 :            : 
      97                 :            :     /** Check if range contains key */
      98                 :            :     inline bool exists( KeyType key ) const;
      99                 :            : 
     100                 :            :     /** Check if range contains key */
     101                 :            :     inline bool intersects( KeyType start, KeyType count ) const;
     102                 :            : 
     103                 :            :     /** Remove a block of values */
     104                 :            :     inline iterator erase( KeyType beg, KeyType count );
     105                 :            : 
     106                 :            :     inline unsigned num_ranges() const
     107                 :            :     {
     108                 :            :         return data.size();
     109                 :            :     }
     110                 :            : 
     111                 :       9378 :     inline iterator begin() const
     112                 :            :     {
     113                 :       9378 :         return data.begin();
     114                 :            :     }
     115                 :      31720 :     inline iterator end() const
     116                 :            :     {
     117                 :      31720 :         return data.end();
     118                 :            :     }
     119                 :       8396 :     inline iterator lower_bound( KeyType key ) const
     120                 :            :     {
     121                 :       8396 :         Range b = { key, 1, NullVal };
     122 [ +  - ][ +  - ]:       8396 :         return std::lower_bound( begin(), end(), b );
                 [ +  - ]
     123                 :            :     }
     124                 :       7172 :     static inline iterator lower_bound( iterator s, iterator e, KeyType key )
     125                 :            :     {
     126                 :       7172 :         Range b = { key, 1, NullVal };
     127         [ +  - ]:       7172 :         return std::lower_bound( s, e, b );
     128                 :            :     }
     129                 :            :     inline iterator upper_bound( KeyType key ) const
     130                 :            :     {
     131                 :            :         Range b = { key, 1, NullVal };
     132                 :            :         return std::upper_bound( begin(), end(), b );
     133                 :            :     }
     134                 :            :     static inline iterator upper_bound( iterator s, iterator e, KeyType key )
     135                 :            :     {
     136                 :            :         Range b = { key, 1, NullVal };
     137                 :            :         return std::upper_bound( s, e, b );
     138                 :            :     }
     139                 :            :     inline std::pair< iterator, iterator > equal_range( KeyType key ) const
     140                 :            :     {
     141                 :            :         Range b = { key, 1, NullVal };
     142                 :            :         return std::equal_range( begin(), end(), b );
     143                 :            :     }
     144                 :            : 
     145                 :        149 :     inline void clear()
     146                 :            :     {
     147                 :        149 :         data.clear();
     148                 :        149 :     }
     149                 :            : 
     150                 :            :   protected:
     151                 :            :     RangeList data;
     152                 :            : };
     153                 :            : 
     154                 :            : template < typename KeyType, typename ValType, ValType NullVal >
     155                 :       3114 : inline std::pair< typename RangeMap< KeyType, ValType, NullVal >::iterator, bool > RangeMap<
     156                 :            :     KeyType, ValType, NullVal >::insert( KeyType first_key, ValType first_val, KeyType count )
     157                 :            : {
     158                 :       3114 :     Range block                    = { first_key, count, first_val };
     159         [ +  - ]:       3114 :     typename RangeList::iterator i = std::lower_bound( data.begin(), data.end(), block );
     160                 :            : 
     161 [ +  - ][ +  + ]:       3114 :     if( i == data.end() )
     162                 :            :     {
     163 [ +  - ][ +  + ]:       3112 :         if( i != data.begin() )
     164                 :            :         {
     165         [ +  - ]:       3004 :             --i;
     166 [ +  - ][ +  - ]:       3004 :             if( i->begin + i->count == first_key && i->value + i->count == first_val )
         [ +  + ][ +  - ]
         [ +  - ][ -  + ]
                 [ -  + ]
     167                 :            :             {
     168         [ #  # ]:          0 :                 i->count += count;
     169         [ #  # ]:          0 :                 return std::pair< iterator, bool >( i, true );
     170                 :            :             }
     171                 :            :         }
     172         [ +  - ]:       3112 :         data.push_back( block );
     173 [ +  - ][ +  - ]:       3112 :         return std::pair< iterator, bool >( data.end() - 1, true );
     174                 :            :     }
     175                 :            : 
     176 [ +  - ][ -  + ]:          2 :     if( i->begin < first_key + count ) return std::pair< iterator, bool >( i, false );
                 [ #  # ]
     177                 :            : 
     178 [ +  - ][ -  + ]:          2 :     if( i->begin == first_key + count && i->value == first_val + count )
         [ #  # ][ #  # ]
                 [ -  + ]
     179                 :            :     {
     180         [ #  # ]:          0 :         i->begin = first_key;
     181         [ #  # ]:          0 :         i->value = first_val;
     182         [ #  # ]:          0 :         i->count += count;
     183 [ #  # ][ #  # ]:          0 :         if( i != data.begin() )
     184                 :            :         {
     185         [ #  # ]:          0 :             count = i->count;
     186         [ #  # ]:          0 :             --i;
     187 [ #  # ][ #  # ]:          0 :             if( i->begin + i->count == first_key && i->value + i->count == first_val )
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     188                 :            :             {
     189         [ #  # ]:          0 :                 i->count += count;
     190         [ #  # ]:          0 :                 ++i;
     191         [ #  # ]:          0 :                 i = data.erase( i );
     192         [ #  # ]:          0 :                 --i;
     193                 :            :             }
     194                 :            :         }
     195         [ #  # ]:          0 :         return std::pair< iterator, bool >( i, true );
     196                 :            :     }
     197                 :            : 
     198 [ +  - ][ +  - ]:          2 :     if( i != data.begin() )
     199                 :            :     {
     200         [ +  - ]:          2 :         --i;
     201 [ +  - ][ +  - ]:          2 :         if( i->begin + i->count == first_key && i->value + i->count == first_val )
         [ -  + ][ #  # ]
         [ #  # ][ #  # ]
                 [ -  + ]
     202                 :            :         {
     203         [ #  # ]:          0 :             i->count += count;
     204         [ #  # ]:          0 :             return std::pair< iterator, bool >( i, true );
     205                 :            :         }
     206         [ +  - ]:          2 :         ++i;
     207                 :            :     }
     208                 :            : 
     209 [ +  - ][ +  - ]:       3114 :     return std::pair< iterator, bool >( data.insert( i, block ), true );
     210                 :            : }
     211                 :            : 
     212                 :            : template < typename KeyType, typename ValType, ValType NullVal >
     213                 :          3 : inline bool RangeMap< KeyType, ValType, NullVal >::merge( const RangeMap< KeyType, ValType, NullVal >& other )
     214                 :            : {
     215                 :            :     // grow map sufficiently to hold new ranges
     216         [ +  - ]:          3 :     RangeList new_data;
     217         [ +  - ]:          3 :     new_data.reserve( other.data.size() + data.size() );
     218                 :            : 
     219                 :            :     // merge
     220                 :          3 :     typename RangeList::const_iterator i = other.data.begin();
     221         [ +  - ]:          3 :     typename RangeList::const_iterator j = data.begin();
     222                 :          3 :     typename RangeList::const_iterator k;
     223 [ +  - ][ +  + ]:         14 :     while( i != other.data.end() || j != data.end() )
         [ +  - ][ +  + ]
         [ +  + ][ +  - ]
           [ +  +  #  #  
                   #  # ]
     224                 :            :     {
     225 [ +  - ][ +  - ]:         11 :         if( j != data.end() && ( i == other.data.end() || j->begin < i->begin ) )
         [ +  - ][ +  + ]
         [ +  - ][ +  - ]
         [ +  + ][ +  - ]
         [ +  - ][ +  +  
             #  #  #  # ]
     226                 :            :         {
     227                 :          8 :             k = j;
     228         [ +  - ]:          8 :             ++j;
     229                 :            :         }
     230 [ +  - ][ +  - ]:          3 :         else if( i != other.data.end() )
     231                 :            :         {
     232                 :          3 :             k = i;
     233         [ +  - ]:          3 :             ++i;
     234                 :            :         }
     235                 :            : 
     236                 :            :         // check if we need to merge with the end of the previous block
     237         [ +  + ]:         11 :         if( new_data.empty() )
     238 [ +  - ][ +  - ]:          3 :             new_data.push_back( *k );
     239 [ +  - ][ +  - ]:          8 :         else if( new_data.back().begin + new_data.back().count > k->begin )
         [ +  - ][ -  + ]
     240                 :          0 :             return false;
     241 [ +  - ][ +  - ]:         16 :         else if( new_data.back().begin + new_data.back().count == k->begin &&
         [ +  - ][ +  - ]
         [ -  + ][ -  + ]
     242 [ +  - ][ +  - ]:          8 :                  new_data.back().value + new_data.back().count == k->value )
                 [ +  - ]
     243 [ #  # ][ #  # ]:          0 :             new_data.back().count += k->count;
     244                 :            :         else
     245 [ +  - ][ +  - ]:          8 :             new_data.push_back( *k );
     246                 :            :     }
     247                 :            : 
     248                 :          3 :     data.swap( new_data );
     249                 :          3 :     return true;
     250                 :            : }
     251                 :            : 
     252                 :            : template < typename KeyType, typename ValType, ValType NullVal >
     253                 :     306547 : inline ValType RangeMap< KeyType, ValType, NullVal >::find( KeyType key ) const
     254                 :            : {
     255                 :     306547 :     Range search                         = { key, 1, NullVal };
     256         [ +  - ]:     306547 :     typename RangeList::const_iterator i = std::lower_bound( data.begin(), data.end(), search );
     257 [ +  - ][ +  + ]:     306547 :     if( i == data.end() || i->begin > key ) return NullVal;
         [ +  - ][ +  + ]
         [ +  - ][ +  + ]
                 [ #  # ]
     258                 :            : 
     259 [ +  - ][ +  - ]:     306547 :     return i->value + key - i->begin;
     260                 :            : }
     261                 :            : 
     262                 :            : template < typename KeyType, typename ValType, ValType NullVal >
     263                 :          0 : inline bool RangeMap< KeyType, ValType, NullVal >::find( KeyType key, ValType& val ) const
     264                 :            : {
     265                 :          0 :     Range search                         = { key, 1, NullVal };
     266         [ #  # ]:          0 :     typename RangeList::const_iterator i = std::lower_bound( data.begin(), data.end(), search );
     267 [ #  # ][ #  # ]:          0 :     if( i == data.end() || i->begin > key )
         [ #  # ][ #  # ]
                 [ #  # ]
           [ #  #  #  # ]
     268                 :            :     {
     269                 :          0 :         val = NullVal;
     270                 :          0 :         return false;
     271                 :            :     }
     272                 :            : 
     273 [ #  # ][ #  # ]:          0 :     val = i->value + key - i->begin;
     274                 :          0 :     return true;
     275                 :            : }
     276                 :            : 
     277                 :            : template < typename KeyType, typename ValType, ValType NullVal >
     278                 :          0 : inline bool RangeMap< KeyType, ValType, NullVal >::exists( KeyType key ) const
     279                 :            : {
     280                 :          0 :     Range search                         = { key, 1, NullVal };
     281         [ #  # ]:          0 :     typename RangeList::const_iterator i = std::lower_bound( data.begin(), data.end(), search );
     282 [ #  # ][ #  # ]:          0 :     return i != data.end() && key >= i->begin;
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     283                 :            : }
     284                 :            : 
     285                 :            : template < typename KeyType, typename ValType, ValType NullVal >
     286                 :          0 : inline bool RangeMap< KeyType, ValType, NullVal >::intersects( KeyType start, KeyType count ) const
     287                 :            : {
     288                 :          0 :     Range search                         = { start, count, NullVal };
     289         [ #  # ]:          0 :     typename RangeList::const_iterator i = std::lower_bound( data.begin(), data.end(), search );
     290 [ #  # ][ #  # ]:          0 :     return i != data.end() && start + count > i->begin && i->begin + i->count > start;
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     291                 :            : }
     292                 :            : 
     293                 :            : template < typename KeyType, typename ValType, ValType NullVal >
     294                 :          0 : inline typename RangeMap< KeyType, ValType, NullVal >::iterator RangeMap< KeyType, ValType, NullVal >::erase(
     295                 :            :     KeyType key, KeyType count )
     296                 :            : {
     297                 :          0 :     Range search = { key, 1, NullVal };
     298                 :          0 :     typename RangeList::iterator i, j;
     299         [ #  # ]:          0 :     i = std::lower_bound( data.begin(), data.end(), search );
     300                 :            : 
     301 [ #  # ][ #  # ]:          0 :     if( i == data.end() ) return i;
                 [ #  # ]
     302                 :            : 
     303 [ #  # ][ #  # ]:          0 :     if( key > i->begin )
     304                 :            :     {
     305         [ #  # ]:          0 :         KeyType offset = key - i->begin;
     306                 :            :         // special case - split existing entry
     307 [ #  # ][ #  # ]:          0 :         if( ( offset + count ) < i->count )
     308                 :            :         {
     309 [ #  # ][ #  # ]:          0 :             Range ins = { i->begin, offset, i->value };
     310                 :          0 :             offset += count;
     311         [ #  # ]:          0 :             i->begin += offset;
     312         [ #  # ]:          0 :             i->value += offset;
     313         [ #  # ]:          0 :             i->count -= offset;
     314 [ #  # ][ #  # ]:          0 :             return data.insert( i, ins ) + 1;
                 [ #  # ]
     315                 :            :         }
     316                 :            :         // otherwise remove the latter part of i
     317         [ #  # ]:          0 :         i->count = offset;
     318         [ #  # ]:          0 :         ++i;
     319                 :            :     }
     320                 :            : 
     321                 :            :     // remove any entries entirely convered by the input range
     322 [ #  # ][ #  # ]:          0 :     for( j = i; j != data.end() && ( j->begin + j->count ) <= ( key + count ); ++j )
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
           [ #  #  #  # ]
     323                 :            :         ;
     324         [ #  # ]:          0 :     i = data.erase( i, j );
     325                 :            : 
     326                 :            :     // remove beginning of last block
     327 [ #  # ][ #  # ]:          0 :     if( i != data.end() && ( key + count ) >= i->begin )
         [ #  # ][ #  # ]
                 [ #  # ]
           [ #  #  #  # ]
     328                 :            :     {
     329         [ #  # ]:          0 :         KeyType offset = key + count - i->begin;
     330         [ #  # ]:          0 :         i->begin += offset;
     331         [ #  # ]:          0 :         i->value += offset;
     332         [ #  # ]:          0 :         i->count -= offset;
     333                 :            :     }
     334                 :            : 
     335         [ #  # ]:          0 :     return i;
     336                 :            : }
     337                 :            : 
     338                 :            : }  // namespace moab
     339                 :            : 
     340                 :            : #endif

Generated by: LCOV version 1.11