![]() |
Mesh Oriented datABase
(version 5.4.1)
Array-based unstructured mesh datastructure
|
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 (kraftche@cae.wisc.edu)
00018 *\date 2007-04-25
00019 */
00020
00021 #ifndef MOAB_RANGE_MAP_HPP
00022 #define MOAB_RANGE_MAP_HPP
00023
00024 #include
00025 #include
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