BWAPI
SPAR/AIModule/BWTA/vendors/CGAL/CGAL/Tools/chained_map.h
Go to the documentation of this file.
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 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines