BWAPI
|
00001 // Copyright (c) 1997-2000 Utrecht University (The Netherlands), 00002 // ETH Zurich (Switzerland), Freie Universitaet Berlin (Germany), 00003 // INRIA Sophia-Antipolis (France), Martin-Luther-University Halle-Wittenberg 00004 // (Germany), Max-Planck-Institute Saarbruecken (Germany), RISC Linz (Austria), 00005 // and Tel-Aviv University (Israel). All rights reserved. 00006 // 00007 // This file is part of CGAL (www.cgal.org); you can redistribute it and/or 00008 // modify it under the terms of the GNU Lesser General Public License as 00009 // published by the Free Software Foundation; version 2.1 of the License. 00010 // See the file LICENSE.LGPL distributed with CGAL. 00011 // 00012 // Licensees holding a valid commercial license may use this file in 00013 // accordance with the commercial license agreement provided with the software. 00014 // 00015 // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 00016 // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 00017 // 00018 // $URL: svn+ssh://scm.gforge.inria.fr/svn/cgal/branches/CGAL-3.5-branch/Hash_map/include/CGAL/Tools/chained_map.h $ 00019 // $Id: chained_map.h 28567 2006-02-16 14:30:13Z lsaboret $ 00020 // 00021 // 00022 // Author(s) : Courtesy of LEDA 00023 #ifndef CGAL_CHAINED_MAP_H 00024 #define CGAL_CHAINED_MAP_H 00025 00026 CGAL_BEGIN_NAMESPACE 00027 00028 namespace CGALi { 00029 00030 template <typename T> class chained_map; 00031 template <typename T> class chained_map_elem; 00032 00033 template <typename T> 00034 class chained_map_elem 00035 { 00036 friend class chained_map<T>; 00037 unsigned long k; T i; 00038 chained_map_elem<T>* succ; 00039 }; 00040 00041 template <typename T> 00042 class chained_map 00043 { 00044 const unsigned long NULLKEY; 00045 const unsigned long NONNULLKEY; 00046 00047 chained_map_elem<T> STOP; 00048 00049 chained_map_elem<T>* table; 00050 chained_map_elem<T>* table_end; 00051 chained_map_elem<T>* free; 00052 int table_size; 00053 int table_size_1; 00054 00055 chained_map_elem<T>* old_table; 00056 chained_map_elem<T>* old_table_end; 00057 chained_map_elem<T>* old_free; 00058 int old_table_size; 00059 int old_table_size_1; 00060 00061 unsigned long old_index; 00062 00063 public: 00064 T& xdef() { return STOP.i; } 00065 const T& cxdef() const { return STOP.i; } 00066 private: 00067 void init_inf(T& x) const { x = STOP.i; } 00068 00069 00070 chained_map_elem<T>* HASH(unsigned long x) const 00071 { return table + (x & table_size_1); } 00072 00073 void init_table(int t); 00074 void rehash(); 00075 void del_old_table(); 00076 00077 inline void insert(unsigned long x, T y); 00078 00079 public: 00080 typedef chained_map_elem<T>* chained_map_item; 00081 typedef chained_map_item item; 00082 00083 unsigned long index(chained_map_item it) const { return it->k; } 00084 T& inf(chained_map_item it) const { return it->i; } 00085 00086 chained_map(int n = 1); 00087 chained_map(const chained_map<T>& D); 00088 chained_map& operator=(const chained_map<T>& D); 00089 00090 00091 void clear_entries(); 00092 void clear(); 00093 ~chained_map() { if (old_table) delete[] old_table; delete[] table; } 00094 00095 T& access(chained_map_item p, unsigned long x); 00096 T& access(unsigned long x); 00097 chained_map_item lookup(unsigned long x) const; 00098 chained_map_item first_item() const; 00099 chained_map_item next_item(chained_map_item it) const; 00100 void statistics() const; 00101 }; 00102 00103 template <typename T> 00104 inline T& chained_map<T>::access(unsigned long x) 00105 { chained_map_item p = HASH(x); 00106 00107 if (old_table) del_old_table(); 00108 if ( p->k == x ) { 00109 old_index = x; 00110 return p->i; 00111 } 00112 else { 00113 if ( p->k == NULLKEY ) { 00114 p->k = x; 00115 init_inf(p->i); // initializes p->i to xdef 00116 old_index = x; 00117 return p->i; 00118 } else 00119 return access(p,x); 00120 } 00121 } 00122 00123 template <typename T> 00124 void chained_map<T>::init_table(int t) 00125 { 00126 table_size = t; 00127 table_size_1 = t-1; 00128 table = new chained_map_elem<T>[t + t/2]; 00129 free = table + t; 00130 table_end = table + t + t/2; 00131 00132 for (chained_map_item p = table; p < free; p++) 00133 { p->succ = &STOP; 00134 p->k = NULLKEY; 00135 } 00136 table->k = NONNULLKEY; 00137 } 00138 00139 00140 template <typename T> 00141 inline void chained_map<T>::insert(unsigned long x, T y) 00142 { chained_map_item q = HASH(x); 00143 if ( q->k == NULLKEY ) { 00144 q->k = x; 00145 q->i = y; 00146 } else { 00147 free->k = x; 00148 free->i = y; 00149 free->succ = q->succ; 00150 q->succ = free++; 00151 } 00152 } 00153 00154 00155 template <typename T> 00156 void chained_map<T>::rehash() 00157 { 00158 old_table = table; 00159 old_table_end = table_end; 00160 old_table_size = table_size; 00161 old_table_size_1 = table_size_1; 00162 old_free = free; 00163 00164 chained_map_item old_table_mid = table + table_size; 00165 00166 init_table(2*table_size); 00167 00168 chained_map_item p; 00169 00170 for(p = old_table + 1; p < old_table_mid; p++) 00171 { unsigned long x = p->k; 00172 if ( x != NULLKEY ) // list p is non-empty 00173 { chained_map_item q = HASH(x); 00174 q->k = x; 00175 q->i = p->i; 00176 } 00177 } 00178 00179 while (p < old_table_end) 00180 { unsigned long x = p->k; 00181 insert(x,p->i); 00182 p++; 00183 } 00184 } 00185 00186 00187 template <typename T> 00188 void chained_map<T>::del_old_table() 00189 { 00190 chained_map_item save_table = table; 00191 chained_map_item save_table_end = table_end; 00192 chained_map_item save_free = free; 00193 int save_table_size = table_size; 00194 int save_table_size_1 = table_size_1; 00195 00196 table = old_table; 00197 table_end = old_table_end; 00198 table_size = old_table_size; 00199 table_size_1 = old_table_size_1; 00200 free = old_free; 00201 00202 old_table = 0; 00203 00204 T p = access(old_index); 00205 00206 delete[] table; 00207 00208 table = save_table; 00209 table_end = save_table_end; 00210 table_size = save_table_size; 00211 table_size_1 = save_table_size_1; 00212 free = save_free; 00213 access(old_index) = p; 00214 } 00215 00216 template <typename T> 00217 T& chained_map<T>::access(chained_map_item p, unsigned long x) 00218 { 00219 STOP.k = x; 00220 chained_map_item q = p->succ; 00221 while (q->k != x) q = q->succ; 00222 if (q != &STOP) 00223 { old_index = x; 00224 return q->i; 00225 } 00226 00227 // index x not present, insert it 00228 00229 if (free == table_end) // table full: rehash 00230 { rehash(); 00231 p = HASH(x); 00232 } 00233 00234 if (p->k == NULLKEY) 00235 { p->k = x; 00236 init_inf(p->i); // initializes p->i to xdef 00237 return p->i; 00238 } 00239 00240 q = free++; 00241 q->k = x; 00242 init_inf(q->i); // initializes q->i to xdef 00243 q->succ = p->succ; 00244 p->succ = q; 00245 return q->i; 00246 } 00247 00248 00249 template <typename T> 00250 chained_map<T>::chained_map(int n) : 00251 NULLKEY(0), NONNULLKEY(1), old_table(0) 00252 { 00253 if (n < 512) 00254 init_table(512); 00255 else { 00256 int ts = 1; 00257 while (ts < n) ts <<= 1; 00258 init_table(ts); 00259 } 00260 } 00261 00262 00263 template <typename T> 00264 chained_map<T>::chained_map(const chained_map<T>& D) : 00265 NULLKEY(0), NONNULLKEY(1), old_table(0) 00266 { 00267 init_table(D.table_size); 00268 STOP.i = D.STOP.i; // xdef 00269 00270 for(chained_map_item p = D.table + 1; p < D.free; p++) 00271 { if (p->k != NULLKEY || p >= D.table + D.table_size) 00272 { insert(p->k,p->i); 00273 //D.copy_inf(p->i); // see chapter Implementation 00274 } 00275 } 00276 } 00277 00278 template <typename T> 00279 chained_map<T>& chained_map<T>::operator=(const chained_map<T>& D) 00280 { 00281 clear_entries(); 00282 delete[] table; 00283 init_table(D.table_size); 00284 STOP.i = D.STOP.i; // xdef 00285 00286 for(chained_map_item p = D.table + 1; p < D.free; p++) 00287 { if (p->k != NULLKEY || p >= D.table + D.table_size) 00288 { insert(p->k,p->i); 00289 //copy_inf(p->i); // see chapter Implementation 00290 } 00291 } 00292 return *this; 00293 } 00294 00295 template <typename T> 00296 void chained_map<T>::clear_entries() 00297 { for(chained_map_item p = table + 1; p < free; p++) 00298 if (p->k != NULLKEY || p >= table + table_size) 00299 p->i = T(); 00300 } 00301 00302 template <typename T> 00303 void chained_map<T>::clear() 00304 { clear_entries(); 00305 delete[] table; 00306 init_table(512); 00307 } 00308 00309 template <typename T> 00310 typename chained_map<T>::chained_map_item 00311 chained_map<T>::lookup(unsigned long x) const 00312 { chained_map_item p = HASH(x); 00313 ((unsigned long &)STOP.k) = x; // cast away const 00314 while (p->k != x) 00315 { p = p->succ; } 00316 return (p == &STOP) ? 0 : p; 00317 } 00318 00319 00320 template <typename T> 00321 typename chained_map<T>::chained_map_item 00322 chained_map<T>::first_item() const 00323 { return next_item(table); } 00324 00325 template <typename T> 00326 typename chained_map<T>::chained_map_item 00327 chained_map<T>::next_item(chained_map_item it) const 00328 { if (it == 0) return 0; 00329 do it++; while (it < table + table_size && it->k == NULLKEY); 00330 return (it < free ? it : 0); 00331 } 00332 00333 template <typename T> 00334 void chained_map<T>::statistics() const 00335 { std::cout << "table_size: " << table_size <<"\n"; 00336 int n = 0; 00337 for (chained_map_item p = table + 1; p < table + table_size; p++) 00338 if (p ->k != NULLKEY) n++; 00339 int used_in_overflow = free - (table + table_size ); 00340 n += used_in_overflow; 00341 std::cout << "number of entries: " << n << "\n"; 00342 std::cout << "fraction of entries in first position: " << 00343 ((double) (n - used_in_overflow))/n <<"\n"; 00344 std::cout << "fraction of empty lists: " << 00345 ((double) (n - used_in_overflow))/table_size<<"\n"; 00346 } 00347 00348 } // namespace CGALi 00349 CGAL_END_NAMESPACE 00350 00351 #endif // CGAL_CHAINED_MAP_H 00352