Rocstar  1.0
Rocstar multiphysics simulation application
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
hash_table.cpp
Go to the documentation of this file.
1 /* *******************************************************************
2  * Illinois Open Source License *
3  * *
4  * University of Illinois/NCSA *
5  * Open Source License *
6  * *
7  * Copyright@2008, University of Illinois. All rights reserved. *
8  * *
9  * Developed by: *
10  * *
11  * Center for Simulation of Advanced Rockets *
12  * *
13  * University of Illinois *
14  * *
15  * www.csar.uiuc.edu *
16  * *
17  * Permission is hereby granted, free of charge, to any person *
18  * obtaining a copy of this software and associated documentation *
19  * files (the "Software"), to deal with the Software without *
20  * restriction, including without limitation the rights to use, *
21  * copy, modify, merge, publish, distribute, sublicense, and/or *
22  * sell copies of the Software, and to permit persons to whom the *
23  * Software is furnished to do so, subject to the following *
24  * conditions: *
25  * *
26  * *
27  * @ Redistributions of source code must retain the above copyright *
28  * notice, this list of conditions and the following disclaimers. *
29  * *
30  * @ Redistributions in binary form must reproduce the above *
31  * copyright notice, this list of conditions and the following *
32  * disclaimers in the documentation and/or other materials *
33  * provided with the distribution. *
34  * *
35  * @ Neither the names of the Center for Simulation of Advanced *
36  * Rockets, the University of Illinois, nor the names of its *
37  * contributors may be used to endorse or promote products derived *
38  * from this Software without specific prior written permission. *
39  * *
40  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, *
41  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES *
42  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND *
43  * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTRIBUTORS OR *
44  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
45  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
46  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE *
47  * USE OR OTHER DEALINGS WITH THE SOFTWARE. *
48  *********************************************************************
49  * Please acknowledge The University of Illinois Center for *
50  * Simulation of Advanced Rockets in works and publications *
51  * resulting from this software or its derivatives. *
52  *********************************************************************/
53 /* Hash Table routines
54 Orion Sky Lawlor, olawlor@acm.org, 11/21/1999
55 
56 This file defines the interface for the C++ Hashtable
57 class. A Hashtable stores pointers to arbitrary Hashable
58 objects so that they can be accessed in constant time.
59 
60 This is a simple Hashtable implementation, with the interface
61 shamelessly stolen from java.util.Hashtable.
62 */
63 #include <stdio.h>
64 #include <stdlib.h>
65 #include <string.h>
66 #include "hash_table.h"
67 
68 void CmiAbort(const char *msg) {
69  fprintf(stderr,"FATAL ERROR> %s\n",msg);
70  abort();
71 }
72 #define DEBUGF(x) /*printf x;*/
73 
74 
76 CkHashCode CkHashFunction_default(const void *keyData,size_t keyLen)
77 {
78  const unsigned char *d=(const unsigned char *)keyData;
79  CkHashCode ret=0;
80  for (unsigned int i=0;i<keyLen;i++) {
81  int shift1=((5*i)%16)+0;
82  int shift2=((6*i)%16)+8;
83  ret+=((0xa5^d[i])<<shift2)+(d[i]<<shift1);
84  }
85  DEBUGF((" hashing %d-byte key to %08x\n",keyLen,ret))
86  return ret;
87 }
88 CkHashCode CkHashFunction_string(const void *keyData,size_t keyLen)
89 {
90  const char *d=*(const char **)keyData;
91  CkHashCode ret=0;
92  for (int i=0;d[i]!=0;i++) {
93  int shift1=((5*i)%16)+0;
94  int shift2=((6*i)%16)+8;
95  ret+=((0xa5^d[i])<<shift2)+(d[i]<<shift1);
96  }
97  DEBUGF((" hashed key '%s' to %08x\n",d,ret))
98  return ret;
99 }
100 
101 //Function to indicate when two keys are equal
102 int CkHashCompare_default(const void *key1,const void *key2,size_t keyLen)
103 {
104  DEBUGF((" comparing %d-byte keys--",keyLen))
105  const char *a=(const char *)key1;
106  const char *b=(const char *)key2;
107  for (unsigned int i=0;i<keyLen;i++)
108  if (a[i]!=b[i]) {DEBUGF(("different\n")) return 0;}
109  DEBUGF(("equal\n"))
110  return 1;
111 }
112 int CkHashCompare_string(const void *key1,const void *key2,size_t keyLen)
113 {
114  const char *a=*(const char **)key1;
115  const char *b=*(const char **)key2;
116  DEBUGF((" comparing '%s' and '%s'--",a,b))
117  while (*a && *b)
118  if (*a++!=*b++) {DEBUGF(("different\n")) return 0;}
119  DEBUGF(("equal\n"))
120  return 1;
121 }
122 
123 
125 static unsigned int primeLargerThan(unsigned int x);
126 #define copyKey(dest,src) memcpy(dest,src,layout.keySize())
127 #define copyObj(dest,src) memcpy(dest,src,layout.objectSize())
128 #define copyEntry(dest,src) memcpy(dest,src,layout.entrySize())
129 
131 
132 //Find the given key in the table. If it's not there, return NULL
133 char *CkHashtable::findKey(const void *key) const
134 {
135  DEBUGF((" Finding key in table of %d--\n",len))
136  int i=hash(key,layout.keySize())%len;
137  int startSpot=i;
138  do {
139  char *cur=entry(i);
140  if (layout.isEmpty(cur)) return NULL;
141  char *curKey=layout.getKey(cur);
142  if (compare(key,curKey,layout.keySize())) return curKey;
143  DEBUGF((" still looking for key (at %d)\n",i))
144  } while (inc(i)!=startSpot);
145  DEBUGF((" No key found!\n"))
146  return NULL;//We've searched the whole table-- no key.
147 }
148 
149 //Find a spot for the given key in the table. If there's not room, return NULL
150 char *CkHashtable::findEntry(const void *key) const
151 {
152  DEBUGF((" Finding spot in table of %d--\n",len))
153  int i=hash(key,layout.keySize())%len;
154  int startSpot=i;
155  do {
156  char *cur=entry(i);
157  if (layout.isEmpty(cur)) return cur; //Empty spot
158  char *curKey=layout.getKey(cur);
159  if (compare(key,curKey,layout.keySize())) return cur; //Its old spot
160  DEBUGF((" still looking for spot (at %d)\n",i))
161  } while (inc(i)!=startSpot);
162  CmiAbort(" No spot found!\n");
163  return NULL;//We've searched the whole table-- no room!
164 }
165 
166 //Build a new empty table of the given size
167 void CkHashtable::buildTable(int newLen)
168 {
169  len=newLen;
170  resizeAt=(int)(len*loadFactor);
171  DEBUGF(("Building table of %d (resize at %d)\n",len,resizeAt))
172  table=new char[layout.entrySize()*len];
173  for (int i=0;i<len;i++) layout.empty(entry(i));
174 }
175 
176 //Set the table to the given size, re-hashing everything.
177 void CkHashtable::rehash(int newLen)
178 {
179  DEBUGF(("Beginning rehash from %d to %d--\n",len,newLen))
180  char *oldTable=table; //Save the old table
181  int oldLen=len;
182  buildTable(newLen); //Make a new table
183  for (int i=0;i<oldLen;i++) {//Add all the old entries to the new table
184  char *src=oldTable+i*layout.entrySize();
185  if (!layout.isEmpty(src)) {
186  //There was an entry here-- copy it to the new table
187  char *dest=findEntry(layout.getKey(src));
188  copyEntry(dest,src);
189  }
190  }
191  delete[] oldTable;
192  DEBUGF(("Rehash complete\n"))
193 }
194 
196 
197 //Constructor-- create an empty hash table of at least the given size
198 CkHashtable::CkHashtable(const CkHashtableLayout &layout_,
199  int initLen,float NloadFactor,
200  CkHashFunction Nhash, //Maps keys to CkHashCodes
201  CkHashCompare Ncompare)
202  :layout(layout_)
203 {
204  nObj=0;
205  hash=Nhash;
206  compare=Ncompare;
207  loadFactor=NloadFactor;
208  buildTable(initLen); //sets table, len, nObj, resizeAt
209 }
210 
211 //Destructor-- destroy table
212 CkHashtable::~CkHashtable()
213 {
214  DEBUGF(("Deleting table of %d\n",len))
215  delete[] table;
216  len=-1;
217  nObj=-1;
218 }
219 
220 //Remove all keys and objects
221 void CkHashtable::empty(void)
222 {
223  for (int i=0;i<len;i++) {
224  char *dest=entry(i);
225  layout.empty(dest);
226  }
227  nObj = 0;
228 }
229 
230 //Add the given object to this table under the given key
231 // Returns pointer to object storage.
232 // Table will be resized if needed.
233 void *CkHashtable::put(const void *key)
234 {
235  DEBUGF(("Putting key\n"))
236 #if 0
237 /*Check to make sure this table is consistent*/
238  int nActualObj=0;
239  for (int i=0;i<len;i++)
240  if (!layout.isEmpty(entry(i)))
241  nActualObj++;
242  if (nActualObj!=nObj) CmiAbort("Table corruption!\n");
243 #endif
244  if (nObj>=resizeAt) rehash(primeLargerThan(len));
245  char *ent=findEntry(key);
246  if (layout.isEmpty(ent))
247  {//Filling a new entry (*not* just replacing old one)
248  nObj++;
249  copyKey(layout.getKey(ent),key);
250  layout.fill(ent);
251  }
252  return layout.getObject(ent);
253 }
254 
255 //Remove this object from the hashtable (re-hashing if needed)
256 void CkHashtable::remove(const void *key)
257 {
258  DEBUGF(("Asked to remove key\n"))
259  char *doomedKey=findKey(key);
260  if (doomedKey==NULL) return; //It's already gone!
261  nObj--;
262  char *doomed=layout.entryFromKey(doomedKey);
263  layout.empty(doomed);
264  //Figure out where that entry came from in the table:
265 #define e2i(entry) (((entry)-table)/layout.entrySize())
266  int i=e2i(doomed);
267  DEBUGF(("Remove-rehashing later keys\n"))
268  while (1) {
269  inc(i);
270  char *src=entry(i);
271  if (layout.isEmpty(src))
272  {//Stop once we find an empty key
273  DEBUGF(("Remove-rehash complete\n"))
274  return;
275  }
276  //This was a valid entry-- figure out where it goes now
277  char *dest=findEntry(layout.getKey(src));
278  if (src!=dest) {
279  DEBUGF(("Remove-rehashing %d to %d\n",e2i(src),e2i(dest)))
280  copyEntry(dest,src);
281  layout.empty(src);
282  } else {
283  DEBUGF(("Remove-rehashing not needed for %d\n",e2i(src)))
284  }
285  }
286 }
287 
288 //Return an iterator for the objects in this hash table
289 CkHashtableIterator *CkHashtable::iterator(void)
290 {
291  DEBUGF(("Building iterator\n"))
292  return new CkHashtableIterator(table,len,layout);
293 }
294 
296 //A HashtableIterator lets you easily list all the objects
297 // in a hash table (without knowing all the keys).
298 
299 //Seek to start of hash table
300 void CkHashtableIterator::seekStart(void) {curNo=0;}
301 
302 //Seek forward (or back) n hash slots
303 void CkHashtableIterator::seek(int n)
304 {
305  curNo+=n;
306  if (curNo<0) curNo=0;
307  if (curNo>len) curNo=len;
308 }
309 
310 //Return 1 if next will be non-NULL
311 int CkHashtableIterator::hasNext(void)
312 {
313  while (curNo<len) {
314  if (!layout.isEmpty(entry(curNo)))
315  return 1;//We have a next object
316  else
317  curNo++;//This spot is blank-- skip over it
318  }
319  return 0;//We went through the whole table-- no object
320 }
321 
322 //Return the next object, or NULL if none
323 // The corresponding object key will be returned in retKey.
324 void *CkHashtableIterator::next(void **retKey)
325 {
326  while (curNo<len) {
327  char *cur=entry(curNo++);
328  if (!layout.isEmpty(cur)) {
329  //Here's the next object
330  if (retKey) *retKey=layout.getKey(cur);
331  return layout.getObject(cur);
332  }
333  }
334  return NULL;//We went through the whole table-- no object
335 }
336 
337 /************************ Prime List ************************
338 A smattering of prime numbers from 3 to 3 billion-billion.
339 I've chosen each one so it is approximately twice
340 the previous value. Useful for hash table sizes, etc.
341 
342 Orion Sky Lawlor, olawlor@acm.org, 11/18/1999
343 */
344 
345 const static unsigned int doublingPrimes[] = {
346 3,
347 7,
348 17,
349 37,
350 73,
351 157,
352 307,
353 617,
354 1217,
355 2417,
356 4817,
357 9677,
358 20117,
359 40177,
360 80177,
361 160117,
362 320107,
363 640007,
364 1280107,
365 2560171,
366 5120117,
367 10000079,
368 20000077,
369 40000217,
370 80000111,
371 160000177,
372 320000171,
373 640000171,
374 1280000017,
375 2560000217u,
376 4200000071u
377 /* extra primes larger than an unsigned 32-bit integer:
378 51200000077,
379 100000000171,
380 200000000171,
381 400000000171,
382 800000000117,
383 1600000000021,
384 3200000000051,
385 6400000000081,
386 12800000000003,
387 25600000000021,
388 51200000000077,
389 100000000000067,
390 200000000000027,
391 400000000000063,
392 800000000000017,
393 1600000000000007,
394 3200000000000059,
395 6400000000000007,
396 12800000000000009,
397 25600000000000003,
398 51200000000000023,
399 100000000000000003,
400 200000000000000003,
401 400000000000000013,
402 800000000000000119,
403 1600000000000000031,
404 3200000000000000059 //This is a 62-bit number
405 */
406 };
407 
408 //This routine returns an arbitrary prime larger than x
409 static unsigned int primeLargerThan(unsigned int x)
410 {
411  int i=0;
412  while (doublingPrimes[i]<=x)
413  i++;
414  return doublingPrimes[i];
415 }
416 
417 /*************** C Interface routines ****************/
418 #define CDECL extern "C"
419 
420 /*Create hashtable with a single integer as the key*/
421 CDECL CkHashtable_c CkCreateHashtable_int(int objBytes,int initSize)
422 {
423  int objStart=2*sizeof(int);
424  CkHashtableLayout layout(sizeof(int),sizeof(int),
425  objStart,objBytes,objStart+objBytes);
426  return (CkHashtable_c)new CkHashtable(layout,initSize,0.5,
427  CkHashFunction_int,CkHashCompare_int);
428 }
429 /*Create hashtable with a C string pointer as the key*/
430 CDECL CkHashtable_c CkCreateHashtable_string(int objBytes,int initSize)
431 {
432  int objStart=2*sizeof(char *);
433  CkHashtableLayout layout(sizeof(char *),sizeof(char *),
434  objStart,objBytes,objStart+objBytes);
435  return (CkHashtable_c)new CkHashtable(layout,initSize,0.5,
437 }
439 {
440  delete (CkHashtable *)h;
441 }
442 /*Return object storage for this (possibly new) key*/
443 CDECL void *CkHashtablePut(CkHashtable_c h,const void *atKey)
444 {
445  return ((CkHashtable *)h)->put(atKey);
446 }
447 /*Return object storage for this (old) key-- */
448 /* returns NULL if key not found.*/
449 CDECL void *CkHashtableGet(CkHashtable_c h,const void *fromKey)
450 {
451  return ((CkHashtable *)h)->get(fromKey);
452 }
453 /*Remove this key, rehashing as needed */
454 CDECL void CkHashtableRemove(CkHashtable_c h,const void *doomedKey)
455 {
456  ((CkHashtable *)h)->remove(doomedKey);
457 }
458 
459 
if(dy > dx)
void * CkHashtable_c
Definition: hash_table.h:81
const NT & d
CDECL CkHashtable_c CkCreateHashtable_string(int objBytes, int initSize)
Definition: hash_table.cpp:430
CDECL void * CkHashtablePut(CkHashtable_c h, const void *atKey)
Definition: hash_table.cpp:443
CDECL CkHashtable_c CkCreateHashtable_int(int objBytes, int initSize)
Definition: hash_table.cpp:421
boolean empty(T_VertexSet s)
const unsigned int key2
Definition: CImg.h:2686
int CkHashCompare_string(const void *key1, const void *key2, size_t keyLen)
Definition: hash_table.cpp:112
void CmiAbort(const char *msg)
Definition: hash_table.cpp:68
#define copyEntry(dest, src)
Definition: hash_table.cpp:128
CkHashCode CkHashFunction_string(const void *keyData, size_t keyLen)
Definition: hash_table.cpp:88
blockLoc i
Definition: read.cpp:79
static const unsigned int doublingPrimes[]
Definition: hash_table.cpp:345
#define copyKey(dest, src)
Definition: hash_table.cpp:126
void int int REAL * x
Definition: read.cpp:74
const NT & n
#define e2i(entry)
int CkHashCompare_default(const void *key1, const void *key2, size_t keyLen)
Definition: hash_table.cpp:102
#define DEBUGF(x)
Definition: hash_table.cpp:72
#define CDECL
Definition: hash_table.cpp:418
CkHashCode CkHashFunction_default(const void *keyData, size_t keyLen)
Definition: hash_table.cpp:76
CDECL void CkDeleteHashtable(CkHashtable_c h)
Definition: hash_table.cpp:438
CGAL_KERNEL_INLINE Comparison_result compare(const NT &n1, const NT &n2)
Definition: number_utils.h:143
for(;;)
static T_Key key
Definition: vinci_lass.c:76
CDECL void CkHashtableRemove(CkHashtable_c h, const void *doomedKey)
Definition: hash_table.cpp:454
const unsigned int key1
Definition: CImg.h:2685
static unsigned int primeLargerThan(unsigned int x)
Definition: hash_table.cpp:409
CDECL void * CkHashtableGet(CkHashtable_c h, const void *fromKey)
Definition: hash_table.cpp:449