home *** CD-ROM | disk | FTP | other *** search
/ ARM Club 3 / TheARMClub_PDCD3.iso / hensa / programming / libg_ / libgpp / !libgpp / gen / ccp / VHMap < prev    next >
Text File  |  1996-03-30  |  5KB  |  211 lines

  1. // This may look like C code, but it is really -*- C++ -*-
  2. /* 
  3. Copyright (C) 1988 Free Software Foundation
  4.     written by Doug Lea (dl@rocky.oswego.edu)
  5.  
  6. This file is part of the GNU C++ Library.  This library is free
  7. software; you can redistribute it and/or modify it under the terms of
  8. the GNU Library General Public License as published by the Free
  9. Software Foundation; either version 2 of the License, or (at your
  10. option) any later version.  This library is distributed in the hope
  11. that it will be useful, but WITHOUT ANY WARRANTY; without even the
  12. implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  13. PURPOSE.  See the GNU Library General Public License for more details.
  14. You should have received a copy of the GNU Library General Public
  15. License along with this library; if not, write to the Free Software
  16. Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  17. */
  18.  
  19. #ifdef __GNUG__
  20. #pragma implementation
  21. #endif
  22. #include "<T>.<C>.VHMap.h"
  23.  
  24. /* codes for status fields */
  25.  
  26. #define EMPTYCELL   0
  27. #define VALIDCELL   1
  28. #define DELETEDCELL 2
  29.  
  30.  
  31. <T><C>VHMap::<T><C>VHMap(<C&> dflt, unsigned int sz)
  32.      :<T><C>Map(dflt)
  33. {
  34.   tab = new <T>[size = sz];
  35.   cont = new <C>[size];
  36.   status = new char[size];
  37.   for (unsigned int i = 0; i < size; ++i) status[i] = EMPTYCELL;
  38. }
  39.  
  40. <T><C>VHMap::<T><C>VHMap(<T><C>VHMap& a) : <T><C>Map(a.def)
  41. {
  42.   tab = new <T>[size = a.size];
  43.   cont = new <C>[size];
  44.   status = new char[size];
  45.   for (unsigned int i = 0; i < size; ++i) status[i] = EMPTYCELL;
  46.   count = 0;
  47.   for (Pix p = a.first(); p; a.next(p)) (*this)[a.key(p)] = a.contents(p);
  48. }
  49.  
  50.  
  51. /* 
  52.  * hashing method: double hash based on high bits of hash fct,
  53.  * followed by linear probe. Can't do too much better if table
  54.  * sizes not constrained to be prime.
  55. */
  56.  
  57.  
  58. static inline unsigned int doublehashinc(unsigned int h, unsigned int s)
  59. {
  60.   unsigned int dh =  ((h / s) % s);
  61.   return (dh > 1)? dh : 1;
  62. }
  63.  
  64. Pix <T><C>VHMap::seek(<T&> key)
  65. {
  66.   unsigned int hashval = <T>HASH(key);
  67.   unsigned int h = hashval % size;
  68.   for (unsigned int i = 0; i <= size; ++i)
  69.   {
  70.     if (status[h] == EMPTYCELL)
  71.       return 0;
  72.     else if (status[h] == VALIDCELL && <T>EQ(key, tab[h]))
  73.       return Pix(&tab[h]);
  74.     if (i == 0)
  75.       h = (h + doublehashinc(hashval, size)) % size;
  76.     else if (++h >= size)
  77.       h -= size;
  78.   }
  79.   return 0;
  80. }
  81.  
  82.  
  83. <C>& <T><C>VHMap::operator [](<T&> item)
  84. {
  85.   if (HASHTABLE_TOO_CROWDED(count, size))
  86.     resize();
  87.  
  88.   unsigned int bestspot = size;
  89.   unsigned int hashval = <T>HASH(item);
  90.   unsigned int h = hashval % size;
  91.   for (unsigned int i = 0; i <= size; ++i)
  92.   {
  93.     if (status[h] == EMPTYCELL)
  94.     {
  95.       ++count;
  96.       if (bestspot >= size) bestspot = h;
  97.       tab[bestspot] = item;
  98.       status[bestspot] = VALIDCELL;
  99.       cont[bestspot] = def;
  100.       return cont[bestspot];
  101.     }
  102.     else if (status[h] == DELETEDCELL)
  103.     {
  104.       if (bestspot >= size) bestspot = h;
  105.     }
  106.     else if (<T>EQ(tab[h],item))
  107.       return cont[h];
  108.  
  109.     if (i == 0)
  110.       h = (h + doublehashinc(hashval, size)) % size;
  111.     else if (++h >= size)
  112.       h -= size;
  113.   }
  114.  
  115.   ++count;
  116.   status[bestspot] = VALIDCELL;
  117.   tab[bestspot] = item;
  118.   cont[bestspot] = def;
  119.   return cont[bestspot];
  120. }
  121.  
  122.  
  123. void <T><C>VHMap::del(<T&> key)
  124. {
  125.   unsigned int hashval = <T>HASH(key);
  126.   unsigned int h = hashval % size;
  127.   for (unsigned int i = 0; i <= size; ++i)
  128.   {
  129.     if (status[h] == EMPTYCELL)
  130.       return;
  131.     else if (status[h] == VALIDCELL && <T>EQ(key, tab[h]))
  132.     {
  133.       status[h] = DELETEDCELL;
  134.       --count;
  135.       return;
  136.     }
  137.     if (i == 0)
  138.       h = (h + doublehashinc(hashval, size)) % size;
  139.     else if (++h >= size)
  140.       h -= size;
  141.   }
  142. }
  143.  
  144.  
  145. void <T><C>VHMap::clear()
  146. {
  147.   for (unsigned int i = 0; i < size; ++i) status[i] = EMPTYCELL;
  148.   count = 0;
  149. }
  150.  
  151. void <T><C>VHMap::resize(unsigned int newsize)
  152. {
  153.   if (newsize <= count)
  154.   {
  155.     newsize = DEFAULT_INITIAL_CAPACITY;
  156.     while (HASHTABLE_TOO_CROWDED(count, newsize)) newsize <<= 1;
  157.   }
  158.   <T>* oldtab = tab;
  159.   <C>* oldcont = cont;
  160.   char* oldstatus = status;
  161.   unsigned int oldsize = size;
  162.   tab = new <T>[size = newsize];
  163.   cont = new <C>[size];
  164.   status = new char[size];
  165.   for (unsigned int i = 0; i < size; ++i) status[i] = EMPTYCELL;
  166.   count = 0;
  167.   for (unsigned int i = 0; i < oldsize; ++i) 
  168.     if (oldstatus[i] == VALIDCELL) 
  169.       (*this)[oldtab[i]] = oldcont[i];
  170.   delete [] oldtab;
  171.   delete [] oldcont;
  172.   delete [] oldstatus;
  173. }
  174.  
  175. Pix <T><C>VHMap::first()
  176. {
  177.   for (unsigned int pos = 0; pos < size; ++pos)
  178.     if (status[pos] == VALIDCELL) return Pix(&tab[pos]);
  179.   return 0;
  180. }
  181.  
  182. void <T><C>VHMap::next(Pix& i)
  183. {
  184.   if (i == 0) return;
  185.   unsigned int pos = ((unsigned)i - (unsigned)tab) / sizeof(<T>) + 1;
  186.   for (; pos < size; ++pos)
  187.     if (status[pos] == VALIDCELL)
  188.     {
  189.       i = Pix(&tab[pos]);
  190.       return;
  191.     }
  192.   i = 0;
  193. }
  194.   
  195.  
  196. int <T><C>VHMap::OK()
  197. {
  198.   int v = tab != 0;
  199.   v &= status != 0;
  200.   int n = 0;
  201.   for (unsigned int i = 0; i < size; ++i) 
  202.   {
  203.     if (status[i] == VALIDCELL) ++n;
  204.     else if (status[i] != DELETEDCELL && status[i] != EMPTYCELL)
  205.       v = 0;
  206.   }
  207.   v &= n == count;
  208.   if (!v) error("invariant failure");
  209.   return v;
  210. }
  211.