MOAB: Mesh Oriented datABase
(version 5.4.1)
|
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