00001 /** @file simplehash.h */ 00002 /* 00003 * Copyright (C) 2002 Laird Breyer 00004 * 00005 * This program is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU General Public License as published by 00007 * the Free Software Foundation; either version 2 of the License, or 00008 * (at your option) any later version. 00009 * 00010 * This program is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 * GNU General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU General Public License 00016 * along with this program; if not, write to the Free Software 00017 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00018 * 00019 * Author: Laird Breyer <laird@lbreyer.com> 00020 */ 00021 00022 #ifndef _SIMPLE_HASH_H_ 00023 #define _SIMPLE_HASH_H_ 00024 00025 #include "basictypes.h" 00026 #include <stddef.h> 00027 #include <string.h> 00028 #include <cassert> 00029 #include <stdexcept> 00030 00031 /// A structure used by SimpleHashTable. 00032 template<class R> 00033 struct SimpleHashPair { 00034 ptrdiff_t key; 00035 R value; 00036 }; 00037 00038 /// A simple "linear probing and insertion" hashtable. 00039 /** 00040 * This simplistic hashtable is designed as a 00041 * replacement for the STL hashtable, which uses too much memory. 00042 * The hashtable implements algorithm L in Knuth, Vol.3, p.526 and 00043 * also uses Knuth's hash function. 00044 */ 00045 template<class R> 00046 class SimpleHashTable 00047 { 00048 00049 public: 00050 SimpleHashTable(uint32 size); 00051 uint32 IntHash(uint32 key); 00052 R Find(ptrdiff_t key); 00053 bool Insert(ptrdiff_t key, R value) throw (overflow_error); 00054 inline uint32 GetCount() { return count; }; 00055 inline uint32 Size() { return size_; }; 00056 void Clear(); 00057 00058 private: 00059 uint32 size_; 00060 uint32 count; 00061 SimpleHashPair<R> *table; 00062 00063 }; 00064 00065 template<class R> 00066 SimpleHashTable<R> :: SimpleHashTable(uint32 size) { 00067 size_ = size; 00068 count = 0; 00069 table = new SimpleHashPair<R>[size_]; 00070 memset(table, 0, sizeof(SimpleHashPair<R>) * size_); 00071 } 00072 00073 template<class R> 00074 void SimpleHashTable<R> :: Clear() { 00075 count = 0; 00076 memset(table, 0, sizeof(SimpleHashPair<R>) * size_); 00077 } 00078 00079 template<class R> 00080 R SimpleHashTable<R> :: Find(ptrdiff_t key) { 00081 uint32 j = IntHash((uint32)key); 00082 uint32 jj = j % size_; 00083 while( table[jj].value != (R)0 ) { 00084 if(table[jj].key == key) { 00085 return table[jj].value; 00086 } 00087 jj = (jj > 0) ? jj - 1 : size_ - 1; 00088 } 00089 return (R)0; 00090 } 00091 00092 /// Inserts a key,value pair into the hash. Returns false if we 00093 /// try to insert a duplicate key, and returns an exception 00094 /// if hash is full 00095 template<class R> 00096 bool SimpleHashTable<R> :: Insert(ptrdiff_t key, R value) throw (overflow_error) { 00097 00098 if( count < size_ ) { 00099 uint32 j = IntHash((uint32)key); 00100 uint32 jj = j % size_; 00101 while( table[jj].value != (R)0 ) { 00102 if(table[jj].key == key) 00103 { return false; } 00104 jj = (jj > 0) ? jj - 1 : size_ - 1; 00105 } 00106 table[jj].key = key; 00107 table[jj].value = value; 00108 count++; 00109 return true; 00110 } else { 00111 cerr << "SimpleHashTable overflow" << endl; 00112 throw overflow_error(""); 00113 } 00114 } 00115 00116 template<class R> 00117 uint32 SimpleHashTable<R> :: IntHash(uint32 key) { 00118 // due to thomas wang, a simplification of bob jenkins' 96 DDJ hash 00119 // key += ~(key << 15); 00120 // key ^= (key >>> 10); 00121 // key += (key << 3); 00122 // key ^= (key >>> 6); 00123 // key += ~(key << 11); 00124 // key ^= (key >>> 16); 00125 00126 // knuth's golden ratio of 2^32 00127 key = (key >> 3) * 2654435761UL; 00128 return key; 00129 } 00130 00131 #endif