## 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] */