modules/up/src/gnug++/int.int.VHMap.cc

/* [<][>]
[^][v][top][bottom][index][help] */

FUNCTIONS

This source file includes following functions.
  1. intintVHMap
  2. intintVHMap
  3. doublehashinc
  4. seek
  5. del
  6. clear
  7. resize
  8. first
  9. next
  10. OK

   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, 675 Mass Ave, Cambridge, MA 02139, USA.
  17 */
  18 
  19 #ifdef __GNUG__
  20 #pragma implementation
  21 #endif
  22 #include "config.h"
  23 #include "int.int.VHMap.h"
  24 
  25 /* codes for status fields */
  26 
  27 #define EMPTYCELL   0
  28 #define VALIDCELL   1
  29 #define DELETEDCELL 2
  30 
  31 
  32 intintVHMap::intintVHMap(int  dflt, unsigned int sz)
     /* [<][>][^][v][top][bottom][index][help] */
  33      :intintMap(dflt)
  34 {
  35   tab = new int[size = sz];
  36   cont = new int[size];
  37   status = new char[size];
  38   for (unsigned int i = 0; i < size; ++i) status[i] = EMPTYCELL;
  39 }
  40 
  41 intintVHMap::intintVHMap(intintVHMap& a) : intintMap(a.def)
     /* [<][>][^][v][top][bottom][index][help] */
  42 {
  43   tab = new int[size = a.size];
  44   cont = new int[size];
  45   status = new char[size];
  46   for (unsigned int i = 0; i < size; ++i) status[i] = EMPTYCELL;
  47   count = 0;
  48   for (Pix p = a.first(); p; a.next(p)) (*this)[a.key(p)] = a.contents(p);
  49 }
  50 
  51 
  52 /* 
  53  * hashing method: double hash based on high bits of hash fct,
  54  * followed by linear probe. Can't do too much better if table
  55  * sizes not constrained to be prime.
  56 */
  57 
  58 
  59 static inline unsigned int doublehashinc(unsigned int h, unsigned int s)
     /* [<][>][^][v][top][bottom][index][help] */
  60 {
  61   unsigned int dh =  ((h / s) % s);
  62   return (dh > 1)? dh : 1;
  63 }
  64 
  65 Pix intintVHMap::seek(int  key)
     /* [<][>][^][v][top][bottom][index][help] */
  66 {
  67   unsigned int hashval = intHASH(key);
  68   unsigned int h = hashval % size;
  69   for (unsigned int i = 0; i <= size; ++i)
  70   {
  71     if (status[h] == EMPTYCELL)
  72       return 0;
  73     else if (status[h] == VALIDCELL && intEQ(key, tab[h]))
  74       return Pix(&tab[h]);
  75     if (i == 0)
  76       h = (h + doublehashinc(hashval, size)) % size;
  77     else if (++h >= size)
  78       h -= size;
  79   }
  80   return 0;
  81 }
  82 
  83 
  84 int& intintVHMap::operator [](int  item)
  85 {
  86   if (HASHTABLE_TOO_CROWDED(count, size))
  87     resize();
  88 
  89   unsigned int bestspot = size;
  90   unsigned int hashval = intHASH(item);
  91   unsigned int h = hashval % size;
  92   for (unsigned int i = 0; i <= size; ++i)
  93   {
  94     if (status[h] == EMPTYCELL)
  95     {
  96       ++count;
  97       if (bestspot >= size) bestspot = h;
  98       tab[bestspot] = item;
  99       status[bestspot] = VALIDCELL;
 100       cont[bestspot] = def;
 101       return cont[bestspot];
 102     }
 103     else if (status[h] == DELETEDCELL)
 104     {
 105       if (bestspot >= size) bestspot = h;
 106     }
 107     else if (intEQ(tab[h],item))
 108       return cont[h];
 109 
 110     if (i == 0)
 111       h = (h + doublehashinc(hashval, size)) % size;
 112     else if (++h >= size)
 113       h -= size;
 114   }
 115 
 116   ++count;
 117   status[bestspot] = VALIDCELL;
 118   tab[bestspot] = item;
 119   cont[bestspot] = def;
 120   return cont[bestspot];
 121 }
 122 
 123 
 124 void intintVHMap::del(int  key)
     /* [<][>][^][v][top][bottom][index][help] */
 125 {
 126   unsigned int hashval = intHASH(key);
 127   unsigned int h = hashval % size;
 128   for (unsigned int i = 0; i <= size; ++i)
 129   {
 130     if (status[h] == EMPTYCELL)
 131       return;
 132     else if (status[h] == VALIDCELL && intEQ(key, tab[h]))
 133     {
 134       status[h] = DELETEDCELL;
 135       --count;
 136       return;
 137     }
 138     if (i == 0)
 139       h = (h + doublehashinc(hashval, size)) % size;
 140     else if (++h >= size)
 141       h -= size;
 142   }
 143 }
 144 
 145 
 146 void intintVHMap::clear()
     /* [<][>][^][v][top][bottom][index][help] */
 147 {
 148   for (unsigned int i = 0; i < size; ++i) status[i] = EMPTYCELL;
 149   count = 0;
 150 }
 151 
 152 void intintVHMap::resize(unsigned int newsize)
     /* [<][>][^][v][top][bottom][index][help] */
 153 {
 154   if (newsize <= count)
 155   {
 156     newsize = DEFAULT_INITIAL_CAPACITY;
 157     while (HASHTABLE_TOO_CROWDED(count, newsize)) newsize <<= 1;
 158   }
 159   int* oldtab = tab;
 160   int* oldcont = cont;
 161   char* oldstatus = status;
 162   unsigned int oldsize = size;
 163   tab = new int[size = newsize];
 164   cont = new int[size];
 165   status = new char[size];
 166   unsigned int i;
 167   for (i = 0; i < size; ++i) status[i] = EMPTYCELL;
 168   count = 0;
 169   for (i = 0; i < oldsize; ++i) 
 170     if (oldstatus[i] == VALIDCELL) 
 171       (*this)[oldtab[i]] = oldcont[i];
 172   delete [] oldtab;
 173   delete [] oldcont;
 174   delete oldstatus;
 175 }
 176 
 177 Pix intintVHMap::first()
     /* [<][>][^][v][top][bottom][index][help] */
 178 {
 179   for (unsigned int pos = 0; pos < size; ++pos)
 180     if (status[pos] == VALIDCELL) return Pix(&tab[pos]);
 181   return 0;
 182 }
 183 
 184 void intintVHMap::next(Pix& i)
     /* [<][>][^][v][top][bottom][index][help] */
 185 {
 186   if (i == 0) return;
 187   unsigned int pos = ((unsigned)i - (unsigned)tab) / sizeof(int) + 1;
 188   for (; pos < size; ++pos)
 189     if (status[pos] == VALIDCELL)
 190     {
 191       i = Pix(&tab[pos]);
 192       return;
 193     }
 194   i = 0;
 195 }
 196   
 197 
 198 int intintVHMap::OK()
     /* [<][>][^][v][top][bottom][index][help] */
 199 {
 200   int v = tab != 0;
 201   v &= status != 0;
 202   int n = 0;
 203   for (unsigned int i = 0; i < size; ++i) 
 204   {
 205     if (status[i] == VALIDCELL) ++n;
 206     else if (status[i] != DELETEDCELL && status[i] != EMPTYCELL)
 207       v = 0;
 208   }
 209   v &= n == count;
 210   if (!v) error("invariant failure");
 211   return v;
 212 }

/* [<][>][^][v][top][bottom][index][help] */