lilypond-1.1.37
[lilypond.git] / flower / include / hash-table.hh
blob3ce52c944ca2a43e066c95282822aca08ce6d8f6
1 /*
2 hash-table.hh -- declare Hash_table_entry, Hash_table
4 source file of the Flower Library
6 (c) 1999 Han-Wen Nienhuys <hanwen@cs.uu.nl>
8 */
10 #ifndef HASH_TABLE_HH
11 #define HASH_TABLE_HH
13 unsigned int int_hash (int);
14 unsigned long prime_list (int idx);
16 template<class K>
17 unsigned int
18 pointer_hash (K *p)
20 return int_hash ((unsigned int) p);
23 template<class K, class V>
24 struct Hash_table_entry
26 K key_;
27 V value_;
28 bool free_b_;
30 Hash_table_entry() {
31 free_b_ = true;
33 Hash_table_entry (K s, V v)
35 key_ = s;
36 value_ = v;
37 free_b_ = false;
41 /**
42 A hash table of prime size.
44 We use quadratic probing.
46 template<class K, class V>
47 class Fixed_size_hash_table
49 public:
50 Array<Hash_table_entry<K,V> > dict_arr_;
51 int size_idx_;
52 Fixed_size_hash_table (int size_idx)
54 size_idx_ = size_idx;
55 int sz = prime_list(size_idx_);
56 dict_arr_.set_size (sz);
59 /// find #s#, or find first empty entry corresponding to #s#
60 int lookup (K s, unsigned int initial_hash)
62 int sz =dict_arr_.size ();
63 int i = initial_hash % sz;
64 int j = 0;
65 while (j <= sz/2) {
66 if (dict_arr_[i].free_b_)
67 return i;
69 if (dict_arr_[i].key_ == s)
70 return i;
72 j++;
73 i = (i + j*j) % sz;
76 return -1;
79 /// remove #s# from the hash table.
80 V remove (K s, unsigned int initial_hash)
82 int sz =dict_arr_.size ();
83 int i = initial_hash % sz;
84 int j = 0;
85 V retval;
88 duplicate with lookup, but we need value of j
91 while (j <= sz/2 && dict_arr_[i].key_ != s)
93 assert (!dict_arr_[i].free_b_);
95 j ++;
96 i = (i + j*j) % sz;
99 j++;
100 int nexti = (i + j*j) % sz;
102 while (j <= sz/2 && !dict_arr_[i].free_b_)
104 dict_arr_[i] = dict_arr_[nexti];
105 j++;
106 i = nexti;
107 nexti = (nexti + j*j)%sz;
110 return retval;
115 Hash table with sliding sizes.
117 template<class K, class V>
118 class Hash_table
120 Fixed_size_hash_table<K,V> * fixed_p_;
121 /// set size to next prime, and copy contents
122 void enlarge ()
124 Fixed_size_hash_table<K,V> *f = new Fixed_size_hash_table<K,V> (fixed_p_->size_idx_ +1);
126 for (int i=0; i < fixed_p_->dict_arr_.size(); i++)
128 if (fixed_p_->dict_arr_[i].free_b_)
129 continue;
131 K nm (fixed_p_->dict_arr_[i].key_);
132 unsigned int h = (*hash_func_)(nm);
133 int nl = f->lookup (nm, h);
135 f->dict_arr_[nl] = Hash_table_entry<K,V> (nm, fixed_p_->dict_arr_[i].value_);
137 delete fixed_p_;
138 fixed_p_ = f;
140 public:
141 Hash_table ()
143 hash_func_ = 0;
144 fixed_p_ = new Fixed_size_hash_table<K,V> (0);
146 ~Hash_table ()
148 delete fixed_p_;
150 void operator = (Hash_table<K,V> const &src)
152 if (&src == this)
153 return;
155 delete fixed_p_;
156 fixed_p_ = new Fixed_size_hash_table<K,V> (*src.fixed_p_);
157 hash_func_ = src.hash_func_;
159 Hash_table (Hash_table<K,V> const &src)
161 fixed_p_ = new Fixed_size_hash_table<K,V> (*src.fixed_p_);
162 hash_func_ = src.hash_func_;
165 void clear ()
167 int i= fixed_p_->size_idx_;
168 delete fixed_p_;
169 fixed_p_ = new Fixed_size_hash_table<K,V> (i);
171 bool elem_b (K s) const
173 int l = fixed_p_->lookup (s, (*hash_func_)(s));
175 return (l >= 0 && !fixed_p_->dict_arr_[l].free_b_) ;
179 Find and return element. If #s# is not in the table, create an entry in the table, and init
181 V& elem (K s)
183 int l;
184 unsigned int h = (*hash_func_)(s);
185 while ((l= fixed_p_->lookup (s,h)) <0)
187 enlarge ();
190 fixed_p_->dict_arr_[l].free_b_ = false;
191 fixed_p_->dict_arr_[l].key_ = s;
192 return fixed_p_->dict_arr_[l].value_;
194 V elem (K s) const
196 return const_elem (s);
198 V const_elem (K k) const
200 V retval;
201 assert (elem_b (k));
202 retval = ((Hash_table<K,V>*)this)->elem (k);
203 return retval;
205 V& operator [] (K k)
207 return elem (k);
210 V operator [] (K k) const
212 return const_elem (k);
215 V remove (K s)
217 return fixed_p_->remove (s, (*hash_func_)(s));
219 friend class Hash_table_iter<K,V>;
220 public:
221 unsigned int (*hash_func_)(K);
225 #endif /* HASH_TABLE_HH */