modules/up/src/gnug++/int.int.VHMap.cc
/* [<][>][^][v][top][bottom][index][help] */
FUNCTIONS
This source file includes following functions.
- intintVHMap
- intintVHMap
- doublehashinc
- seek
- del
- clear
- resize
- first
- next
- 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 }