MOAB: Mesh Oriented datABase  (version 5.4.1)
RangeMap.hpp
Go to the documentation of this file.
00001 /*
00002  * MOAB, a Mesh-Oriented datABase, is a software component for creating,
00003  * storing and accessing finite element mesh data.
00004  *
00005  * Copyright 2004 Sandia Corporation.  Under the terms of Contract
00006  * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government
00007  * retains certain rights in this software.
00008  *
00009  * This library is free software; you can redistribute it and/or
00010  * modify it under the terms of the GNU Lesser General Public
00011  * License as published by the Free Software Foundation; either
00012  * version 2.1 of the License, or (at your option) any later version.
00013  *
00014  */
00015 
00016 /**\file RangeMap.hpp
00017  *\author Jason Kraftcheck ([email protected])
00018  *\date 2007-04-25
00019  */
00020 
00021 #ifndef MOAB_RANGE_MAP_HPP
00022 #define MOAB_RANGE_MAP_HPP
00023 
00024 #include <vector>
00025 #include <algorithm>
00026 
00027 namespace moab
00028 {
00029 
00030 /**\brief Map ranges of values
00031  *
00032  * This class provides a map between ranges of values, such as
00033  * a map between file IDs and EntityHandles.  It is intended
00034  * for use in situations where there are relatively few insertions
00035  * of large contiguous ranges of values.
00036  */
00037 template < typename KeyType, typename ValType, ValType NullVal = 0 >
00038 class RangeMap
00039 {
00040   public:
00041     typedef KeyType key_type;
00042     typedef ValType value_type;
00043 
00044     struct Range
00045     {
00046         KeyType begin, count;
00047         ValType value;
00048         bool operator<( const Range& other ) const
00049         {
00050             return begin + count <= other.begin;
00051         }  // equal if overlapping!
00052     };
00053     typedef typename std::vector< Range > RangeList;
00054     typedef typename RangeList::const_iterator iterator;
00055     typedef typename RangeList::const_iterator const_iterator;
00056 
00057     inline bool empty() const
00058     {
00059         return data.empty();
00060     }
00061 
00062     inline const Range& back() const
00063     {
00064         return data.back();
00065     }
00066     inline const Range& front() const
00067     {
00068         return data.front();
00069     }
00070 
00071     /**\brief Insert mapping between range of keys and range of values
00072      *
00073      * Insert mapping from [first_key, first_key+count) to [first_val, first_val+count)
00074      *
00075      * Input range of keys many not overlap any other input range.  If it does overlap
00076      * an existing range, the second value of the pair will be returned as false
00077      * and the iterator will point to (one of) the overlapping ranges.
00078      */
00079     inline std::pair< iterator, bool > insert( KeyType first_key, ValType first_val, KeyType count );
00080 
00081     /**\brief Insert mapping between range of keys and range of values
00082      *
00083      * Insert mapping from [first_key, first_key+count) to [first_val, first_val+count)
00084      *
00085      * Input range of keys many not overlap any other input range.  If it does overlap
00086      * an existing range, the second value of the pair will be returned as false
00087      * and the iterator will point to (one of) the overlapping ranges.
00088      */
00089     inline bool merge( const RangeMap< KeyType, ValType, NullVal >& other );
00090 
00091     /** Find the value corresponding to the specified key.  Returns NullVal if not found */
00092     inline ValType find( KeyType key ) const;
00093 
00094     /** Find the value corresponding to the specified key.  Returns false if not found */
00095     inline bool find( KeyType key, ValType& val_out ) const;
00096 
00097     /** Check if range contains key */
00098     inline bool exists( KeyType key ) const;
00099 
00100     /** Check if range contains key */
00101     inline bool intersects( KeyType start, KeyType count ) const;
00102 
00103     /** Remove a block of values */
00104     inline iterator erase( KeyType beg, KeyType count );
00105 
00106     inline unsigned num_ranges() const
00107     {
00108         return data.size();
00109     }
00110 
00111     inline iterator begin() const
00112     {
00113         return data.begin();
00114     }
00115     inline iterator end() const
00116     {
00117         return data.end();
00118     }
00119     inline iterator lower_bound( KeyType key ) const
00120     {
00121         Range b = { key, 1, NullVal };
00122         return std::lower_bound( begin(), end(), b );
00123     }
00124     static inline iterator lower_bound( iterator s, iterator e, KeyType key )
00125     {
00126         Range b = { key, 1, NullVal };
00127         return std::lower_bound( s, e, b );
00128     }
00129     inline iterator upper_bound( KeyType key ) const
00130     {
00131         Range b = { key, 1, NullVal };
00132         return std::upper_bound( begin(), end(), b );
00133     }
00134     static inline iterator upper_bound( iterator s, iterator e, KeyType key )
00135     {
00136         Range b = { key, 1, NullVal };
00137         return std::upper_bound( s, e, b );
00138     }
00139     inline std::pair< iterator, iterator > equal_range( KeyType key ) const
00140     {
00141         Range b = { key, 1, NullVal };
00142         return std::equal_range( begin(), end(), b );
00143     }
00144 
00145     inline void clear()
00146     {
00147         data.clear();
00148     }
00149 
00150   protected:
00151     RangeList data;
00152 };
00153 
00154 template < typename KeyType, typename ValType, ValType NullVal >
00155 inline std::pair< typename RangeMap< KeyType, ValType, NullVal >::iterator, bool > RangeMap<
00156     KeyType,
00157     ValType,
00158     NullVal >::insert( KeyType first_key, ValType first_val, KeyType count )
00159 {
00160     Range block                    = { first_key, count, first_val };
00161     typename RangeList::iterator i = std::lower_bound( data.begin(), data.end(), block );
00162 
00163     if( i == data.end() )
00164     {
00165         if( i != data.begin() )
00166         {
00167             --i;
00168             if( i->begin + i->count == first_key && i->value + i->count == first_val )
00169             {
00170                 i->count += count;
00171                 return std::pair< iterator, bool >( i, true );
00172             }
00173         }
00174         data.push_back( block );
00175         return std::pair< iterator, bool >( data.end() - 1, true );
00176     }
00177 
00178     if( i->begin < first_key + count ) return std::pair< iterator, bool >( i, false );
00179 
00180     if( i->begin == first_key + count && i->value == first_val + count )
00181     {
00182         i->begin = first_key;
00183         i->value = first_val;
00184         i->count += count;
00185         if( i != data.begin() )
00186         {
00187             count = i->count;
00188             --i;
00189             if( i->begin + i->count == first_key && i->value + i->count == first_val )
00190             {
00191                 i->count += count;
00192                 ++i;
00193                 i = data.erase( i );
00194                 --i;
00195             }
00196         }
00197         return std::pair< iterator, bool >( i, true );
00198     }
00199 
00200     if( i != data.begin() )
00201     {
00202         --i;
00203         if( i->begin + i->count == first_key && i->value + i->count == first_val )
00204         {
00205             i->count += count;
00206             return std::pair< iterator, bool >( i, true );
00207         }
00208         ++i;
00209     }
00210 
00211     return std::pair< iterator, bool >( data.insert( i, block ), true );
00212 }
00213 
00214 template < typename KeyType, typename ValType, ValType NullVal >
00215 inline bool RangeMap< KeyType, ValType, NullVal >::merge( const RangeMap< KeyType, ValType, NullVal >& other )
00216 {
00217     // grow map sufficiently to hold new ranges
00218     RangeList new_data;
00219     new_data.reserve( other.data.size() + data.size() );
00220 
00221     // merge
00222     typename RangeList::const_iterator i = other.data.begin();
00223     typename RangeList::const_iterator j = data.begin();
00224     typename RangeList::const_iterator k;
00225     while( i != other.data.end() || j != data.end() )
00226     {
00227         if( j != data.end() && ( i == other.data.end() || j->begin < i->begin ) )
00228         {
00229             k = j;
00230             ++j;
00231         }
00232         else if( i != other.data.end() )
00233         {
00234             k = i;
00235             ++i;
00236         }
00237 
00238         // check if we need to merge with the end of the previous block
00239         if( new_data.empty() )
00240             new_data.push_back( *k );
00241         else if( new_data.back().begin + new_data.back().count > k->begin )
00242             return false;
00243         else if( new_data.back().begin + new_data.back().count == k->begin &&
00244                  new_data.back().value + new_data.back().count == k->value )
00245             new_data.back().count += k->count;
00246         else
00247             new_data.push_back( *k );
00248     }
00249 
00250     data.swap( new_data );
00251     return true;
00252 }
00253 
00254 template < typename KeyType, typename ValType, ValType NullVal >
00255 inline ValType RangeMap< KeyType, ValType, NullVal >::find( KeyType key ) const
00256 {
00257     Range search                         = { key, 1, NullVal };
00258     typename RangeList::const_iterator i = std::lower_bound( data.begin(), data.end(), search );
00259     if( i == data.end() || i->begin > key ) return NullVal;
00260 
00261     return i->value + key - i->begin;
00262 }
00263 
00264 template < typename KeyType, typename ValType, ValType NullVal >
00265 inline bool RangeMap< KeyType, ValType, NullVal >::find( KeyType key, ValType& val ) const
00266 {
00267     Range search                         = { key, 1, NullVal };
00268     typename RangeList::const_iterator i = std::lower_bound( data.begin(), data.end(), search );
00269     if( i == data.end() || i->begin > key )
00270     {
00271         val = NullVal;
00272         return false;
00273     }
00274 
00275     val = i->value + key - i->begin;
00276     return true;
00277 }
00278 
00279 template < typename KeyType, typename ValType, ValType NullVal >
00280 inline bool RangeMap< KeyType, ValType, NullVal >::exists( KeyType key ) const
00281 {
00282     Range search                         = { key, 1, NullVal };
00283     typename RangeList::const_iterator i = std::lower_bound( data.begin(), data.end(), search );
00284     return i != data.end() && key >= i->begin;
00285 }
00286 
00287 template < typename KeyType, typename ValType, ValType NullVal >
00288 inline bool RangeMap< KeyType, ValType, NullVal >::intersects( KeyType start, KeyType count ) const
00289 {
00290     Range search                         = { start, count, NullVal };
00291     typename RangeList::const_iterator i = std::lower_bound( data.begin(), data.end(), search );
00292     return i != data.end() && start + count > i->begin && i->begin + i->count > start;
00293 }
00294 
00295 template < typename KeyType, typename ValType, ValType NullVal >
00296 inline typename RangeMap< KeyType, ValType, NullVal >::iterator RangeMap< KeyType, ValType, NullVal >::erase(
00297     KeyType key,
00298     KeyType count )
00299 {
00300     Range search = { key, 1, NullVal };
00301     typename RangeList::iterator i, j;
00302     i = std::lower_bound( data.begin(), data.end(), search );
00303 
00304     if( i == data.end() ) return i;
00305 
00306     if( key > i->begin )
00307     {
00308         KeyType offset = key - i->begin;
00309         // special case - split existing entry
00310         if( ( offset + count ) < i->count )
00311         {
00312             Range ins = { i->begin, offset, i->value };
00313             offset += count;
00314             i->begin += offset;
00315             i->value += offset;
00316             i->count -= offset;
00317             return data.insert( i, ins ) + 1;
00318         }
00319         // otherwise remove the latter part of i
00320         i->count = offset;
00321         ++i;
00322     }
00323 
00324     // remove any entries entirely convered by the input range
00325     for( j = i; j != data.end() && ( j->begin + j->count ) <= ( key + count ); ++j )
00326         ;
00327     i = data.erase( i, j );
00328 
00329     // remove beginning of last block
00330     if( i != data.end() && ( key + count ) >= i->begin )
00331     {
00332         KeyType offset = key + count - i->begin;
00333         i->begin += offset;
00334         i->value += offset;
00335         i->count -= offset;
00336     }
00337 
00338     return i;
00339 }
00340 
00341 }  // namespace moab
00342 
00343 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines