Arcane  4.1.12.0
User documentation
Loading...
Searching...
No Matches
HashTable.h
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2026 CEA (www.cea.fr) IFPEN (www.ifpenergiesnouvelles.com)
4// See the top-level COPYRIGHT file for details.
5// SPDX-License-Identifier: Apache-2.0
6//-----------------------------------------------------------------------------
7/*---------------------------------------------------------------------------*/
8/* HashTable.h (C) 2000-2023 */
9/* */
10/* Hash Table. */
11/*---------------------------------------------------------------------------*/
12#ifndef ARCANE_UTILS_HASHTABLE_H
13#define ARCANE_UTILS_HASHTABLE_H
14/*---------------------------------------------------------------------------*/
15/*---------------------------------------------------------------------------*/
16
17#include "arcane/utils/MultiBuffer.h"
18#include "arcane/utils/Array.h"
19#include "arcane/utils/HashFunction.h"
20
21/*---------------------------------------------------------------------------*/
22/*---------------------------------------------------------------------------*/
23
24namespace Arcane
25{
26
27/*---------------------------------------------------------------------------*/
28/*---------------------------------------------------------------------------*/
29
30/*!
31 * \internal
32 * \brief Base class for a simple hash table for entities
33
34 \todo Add iterators for this collection and derived classes
35 */
36class ARCANE_UTILS_EXPORT HashTableBase
37{
38 public:
39
40 /*!
41 * \brief Creates a table of size \a table_size
42 *
43 * If \a use_prime is true, uses the nearestPrimeNumber() function
44 * to have a size that is a prime number.
45 */
46 HashTableBase(Integer table_size, bool use_prime)
47 : m_count(0)
48 , m_nb_bucket(use_prime ? nearestPrimeNumber(table_size) : table_size)
49 {
50 }
51 virtual ~HashTableBase() {}
52
53 public:
54
55 /*!
56 * \brief Returns the nearest prime number greater than \a n.
57 * The nearest prime number greater than \a n is returned using a
58 * pre-determined prime number table.
59 */
60 Integer nearestPrimeNumber(Integer n);
61
62 public:
63
64 //! Number of elements in the table
65 Integer count() const
66 {
67 return m_count;
68 }
69
70 protected:
71
72 void _throwNotFound ARCANE_NORETURN() const;
73
74 protected:
75
76 Integer m_count; //!< Number of elements
77 Integer m_nb_bucket; //!< Number of buckets
78};
79
80/*---------------------------------------------------------------------------*/
81/*---------------------------------------------------------------------------*/
82/*!
83 * \internal
84 * \brief Base class for a hash table for associative arrays
85
86 This table allows storing a value based on a key. The
87 value type is managed by the derived class HashTableMapT.
88
89 The hash table is managed as an array whose number
90 of elements is given by the table size (m_nb_bucket).
91 The elements are then stored in a linked list.
92
93 This table only allows adding values.
94
95 For performance reasons, it is preferable that the table size
96 (buckets) is a prime number.
97 */
98template <typename KeyType, typename TraitsType>
100: public HashTableBase
101{
102 public:
103
104 typedef typename TraitsType::KeyTypeConstRef KeyTypeConstRef;
105 typedef typename TraitsType::KeyTypeValue KeyTypeValue;
106
107 public:
108
109 struct HashData
110 {
111 public:
112
113 friend class HashTableBaseT<KeyType, TraitsType>;
114
115 public:
116
117 HashData()
118 : m_key(KeyType())
119 , m_next(0)
120 {}
121
122 public:
123
124 /*!
125 * \brief Changes the key value.
126 *
127 * After changing the value of one or more keys, a rehash must be performed().
128 */
129 void changeKey(const KeyType& new_key)
130 {
131 m_key = new_key;
132 }
133
134 protected:
135
136 KeyTypeValue m_key; //!< Search key
137 HashData* m_next; //! Next element in the hash table
138 };
139
140 public:
141
142 /*!
143 * \brief Creates a table of size \a table_size
144 *
145 * If \a use_prime is true, uses the nearestPrimeNumber() function
146 * to have a size that is a prime number.
147 */
148 HashTableBaseT(Integer table_size, bool use_prime)
149 : HashTableBase(table_size, use_prime)
150 , m_buckets(m_nb_bucket)
151 {
152 m_buckets.fill(0);
153 }
154
155 public:
156
157 //! \a true if a value with the key \a id is present
158 bool hasKey(KeyTypeConstRef id) const
159 {
160 KeyType hf = _hash(id);
161 for (HashData* i = m_buckets[hf]; i; i = i->m_next) {
162 if (i->m_key == id)
163 return true;
164 }
165 return false;
166 }
167
168 //! Clears all elements from the table
169 void clear()
170 {
171 m_buckets.fill(0);
172 m_count = 0;
173 }
174
175 //! Resizes the hash table
176 void resize(Integer new_table_size, bool use_prime = false)
177 {
178 m_nb_bucket = new_table_size;
179 if (new_table_size == 0) {
180 clear();
181 return;
182 }
183 if (use_prime)
184 new_table_size = nearestPrimeNumber(new_table_size);
185 //todo: remove the allocation of this array
186 UniqueArray<HashData*> old_buckets(m_buckets.clone());
187 m_buckets.resize(new_table_size);
188 m_buckets.fill(0);
189 for (Integer z = 0, zs = old_buckets.size(); z < zs; ++z) {
190 for (HashData* i = old_buckets[z]; i; i = i->m_next) {
191 _baseAdd(_hash(i->m_key), i->m_key, i);
192 }
193 }
194 }
195
196 //! Repositions data after key value change
197 void rehash()
198 {
199 //todo: remove the allocation of this array
200 UniqueArray<HashData*> old_buckets(m_buckets.clone());
201 m_buckets.fill(0);
202
203 for (Integer z = 0, zs = old_buckets.size(); z < zs; ++z) {
204 for (HashData* i = old_buckets[z]; i;) {
205 HashData* current = i;
206 i = i->m_next; // Must be done here, because i->m_next changes with _baseAdd
207 _baseAdd(_hash(current->m_key), current->m_key, current);
208 }
209 }
210 }
211
212 protected:
213
214 inline Integer _hash(KeyTypeConstRef id) const
215 {
216 return TraitsType::hashFunction(id) % m_nb_bucket;
217 }
218 inline HashData* _baseLookupBucket(Integer bucket, KeyTypeConstRef id) const
219 {
220 for (HashData* i = m_buckets[bucket]; i; i = i->m_next) {
221 if (i->m_key == id)
222 return i;
223 }
224 return 0;
225 }
226 inline HashData* _baseRemoveBucket(Integer bucket, KeyTypeConstRef id)
227 {
228 HashData* i = m_buckets[bucket];
229 if (i) {
230 if (i->m_key == id) {
231 m_buckets[bucket] = i->m_next;
232 --m_count;
233 return i;
234 }
235 for (; i->m_next; i = i->m_next) {
236 if (i->m_next->m_key == id) {
237 HashData* r = i->m_next;
238 i->m_next = i->m_next->m_next;
239 --m_count;
240 return r;
241 }
242 }
243 }
244 _throwNotFound();
245 }
246 inline HashData* _baseLookup(KeyTypeConstRef id) const
247 {
248 return _baseLookupBucket(_hash(id), id);
249 }
250 inline HashData* _baseRemove(KeyTypeConstRef id)
251 {
252 return _baseRemoveBucket(_hash(id), id);
253 }
254 inline void _baseAdd(Integer bucket, KeyTypeConstRef id, HashData* hd)
255 {
256 HashData* buck = m_buckets[bucket];
257 hd->m_key = id;
258 hd->m_next = buck;
259 m_buckets[bucket] = hd;
260 ++m_count;
261 }
262
263 protected:
264
265 UniqueArray<HashData*> m_buckets; //! Array of buckets
266};
267
268/*---------------------------------------------------------------------------*/
269/*---------------------------------------------------------------------------*/
270
271} // namespace Arcane
272
273/*---------------------------------------------------------------------------*/
274/*---------------------------------------------------------------------------*/
275
276#endif
Integer size() const
Number of elements in the vector.
void rehash()
Repositions data after key value change.
Definition HashTable.h:197
HashTableBaseT(Integer table_size, bool use_prime)
Creates a table of size table_size.
Definition HashTable.h:148
void resize(Integer new_table_size, bool use_prime=false)
Resizes the hash table.
Definition HashTable.h:176
bool hasKey(KeyTypeConstRef id) const
true if a value with the key id is present
Definition HashTable.h:158
void clear()
Clears all elements from the table.
Definition HashTable.h:169
HashTableBase(Integer table_size, bool use_prime)
Creates a table of size table_size.
Definition HashTable.h:46
Integer m_nb_bucket
Number of buckets.
Definition HashTable.h:77
Integer nearestPrimeNumber(Integer n)
Returns the nearest prime number greater than n. The nearest prime number greater than n is returned ...
Definition HashTable.cc:57
Integer m_count
Number of elements.
Definition HashTable.h:76
Integer count() const
Number of elements in the table.
Definition HashTable.h:65
1D data vector with value semantics (STL style).
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
Int32 Integer
Type representing an integer.
void changeKey(const KeyType &new_key)
Changes the key value.
Definition HashTable.h:129
KeyTypeValue m_key
Search key.
Definition HashTable.h:136