15 #include "../config/config.hpp"
76 HashTable(
int block_size = 16*1024,
int init_hash_size = 32*1024);
81 T*
Get(
int p1,
int p2);
82 T*
Get(
int p1,
int p2,
int p3,
int p4 = -1 );
85 int GetId(
int p1,
int p2);
86 int GetId(
int p1,
int p2,
int p3,
int p4 = -1);
89 T*
Find(
int p1,
int p2);
90 T*
Find(
int p1,
int p2,
int p3,
int p4 = -1);
92 const T*
Find(
int p1,
int p2)
const;
93 const T*
Find(
int p1,
int p2,
int p3,
int p4 = -1)
const;
96 int FindId(
int p1,
int p2)
const;
97 int FindId(
int p1,
int p2,
int p3,
int p4 = -1)
const;
120 void Reparent(
int id,
int new_p1,
int new_p2);
121 void Reparent(
int id,
int new_p1,
int new_p2,
int new_p3,
int new_p4 = -1);
169 iterator
end() {
return iterator(); }
172 const_iterator
cend()
const {
return const_iterator(); }
180 inline int Hash(
int p1,
int p2)
const
181 {
return (984120265*p1 + 125965121*p2) &
mask; }
183 inline int Hash(
int p1,
int p2,
int p3)
const
184 {
return (984120265*p1 + 125965121*p2 + 495698413*p3) &
mask; }
194 int SearchList(
int id,
int p1,
int p2,
int p3)
const;
196 inline void Insert(
int idx,
int id, T &item);
197 void Unlink(
int idx,
int id);
211 mask = init_hash_size-1;
212 MFEM_VERIFY(!(init_hash_size &
mask),
"init_size must be a power of two.");
214 table =
new int[init_hash_size];
215 for (
int i = 0; i < init_hash_size; i++) {
table[i] = -1; }
220 :
Base(other), mask(other.mask)
237 inline void sort3(
int &
a,
int &
b,
int &c)
239 if (a > b) { std::swap(a, b); }
240 if (a > c) { std::swap(a, c); }
241 if (b > c) { std::swap(b, c); }
244 inline void sort4(
int &a,
int &b,
int &c,
int &d)
246 if (a > b) { std::swap(a, b); }
247 if (a > c) { std::swap(a, c); }
248 if (a > d) { std::swap(a, d); }
252 inline void sort4_ext(
int &a,
int &b,
int &c,
int &d)
269 return &(Base::At(GetId(p1, p2)));
275 return &(Base::At(GetId(p1, p2, p3, p4)));
282 if (p1 > p2) { std::swap(p1, p2); }
283 int idx = Hash(p1, p2);
284 int id = SearchList(table[idx], p1, p2);
285 if (
id >= 0) {
return id; }
291 new_id = unused.Last();
296 new_id = Base::Append();
298 T& item = Base::At(new_id);
303 Insert(idx, new_id, item);
313 internal::sort4_ext(p1, p2, p3, p4);
314 int idx = Hash(p1, p2, p3);
315 int id = SearchList(table[idx], p1, p2, p3);
316 if (
id >= 0) {
return id; }
322 new_id = unused.Last();
327 new_id = Base::Append();
329 T& item = Base::At(new_id);
335 Insert(idx, new_id, item);
344 int id = FindId(p1, p2);
345 return (
id >= 0) ? &(Base::At(
id)) : NULL;
351 int id = FindId(p1, p2, p3, p4);
352 return (
id >= 0) ? &(Base::At(
id)) : NULL;
358 int id = FindId(p1, p2);
359 return (
id >= 0) ? &(Base::At(
id)) : NULL;
365 int id = FindId(p1, p2, p3, p4);
366 return (
id >= 0) ? &(Base::At(
id)) : NULL;
372 if (p1 > p2) { std::swap(p1, p2); }
373 return SearchList(table[Hash(p1, p2)], p1, p2);
379 internal::sort4_ext(p1, p2, p3, p4);
380 return SearchList(table[Hash(p1, p2, p3)], p1, p2, p3);
388 const T& item = Base::At(
id);
389 if (item.p1 == p1 && item.p2 == p2) {
return id; }
400 const T& item = Base::At(
id);
401 if (item.p1 == p1 && item.p2 == p2 && item.p3 == p3) {
return id; }
410 const int fill_factor = 2;
413 if (Base::Size() > (mask+1) * fill_factor)
425 int new_table_size = 2*(mask+1);
426 table =
new int[new_table_size];
427 for (
int i = 0; i < new_table_size; i++) { table[i] = -1; }
428 mask = new_table_size-1;
430 #if defined(MFEM_DEBUG) && !defined(MFEM_USE_MPI)
431 mfem::out << _MFEM_FUNC_NAME <<
": rehashing to size " << new_table_size
436 for (
iterator it = begin(); it != end(); ++it)
438 Insert(Hash(*it), it.index(), *it);
446 item.next = table[idx];
454 int* p_id = table + idx;
457 T& item = Base::At(*p_id);
465 MFEM_ABORT(
"HashTable<>::Unlink: item not found!");
471 T& item = Base::At(
id);
472 Unlink(Hash(item),
id);
481 for (
int i = 0; i <= mask; i++) { table[i] = -1; }
488 T& item = Base::At(
id);
489 Unlink(Hash(item),
id);
491 if (new_p1 > new_p2) { std::swap(new_p1, new_p2); }
496 int new_idx = Hash(new_p1, new_p2);
497 Insert(new_idx,
id, item);
502 int new_p1,
int new_p2,
int new_p3,
int new_p4)
504 T& item = Base::At(
id);
505 Unlink(Hash(item),
id);
507 internal::sort4_ext(new_p1, new_p2, new_p3, new_p4);
513 int new_idx = Hash(new_p1, new_p2, new_p3);
514 Insert(new_idx,
id, item);
520 return (mask+1) *
sizeof(int) + Base::MemoryUsage() + unused.MemoryUsage();
526 mfem::out << Base::MemoryUsage() <<
" + " << (mask+1) *
sizeof(
int)
527 <<
" + " << unused.MemoryUsage();
int Size() const
Logical size of the array.
int Hash(int p1, int p2, int p3) const
int Hash(const Hashed4 &item) const
const_iterator cbegin() const
void Unlink(int idx, int id)
void Delete(int id)
Remove an item from the hash table.
bool IdExists(int id) const
Return true if item 'id' exists in (is used by) the container.
HashTable(int block_size=16 *1024, int init_hash_size=32 *1024)
int Size() const
Return the number of items actually stored.
int SearchList(int id, int p1, int p2) const
void Copy(Array ©) const
Create a copy of the current array.
T * Get(int p1, int p2)
Get item whose parents are p1, p2... Create it if it doesn't exist.
const_iterator(const base &it)
void PrintMemoryDetail() const
int Hash(int p1, int p2) const
int Size() const
Return the number of elements currently stored in the HashTable.
void DeleteAll()
Remove all items.
void CheckRehash()
Check table load factor and resize if necessary.
const_iterator & operator++()
void Reparent(int id, int new_p1, int new_p2)
Make an item hashed under different parent IDs.
T * Find(int p1, int p2)
Find item whose parents are p1, p2... Return NULL if it doesn't exist.
int NumIds() const
Return the total number of ids (used and unused) in the HashTable.
int Hash(const Hashed2 &item) const
int NumFreeIds() const
Return the number of free/unused ids in the HashTable.
long MemoryUsage() const
Return total size of allocated memory (tables plus items), in bytes.
const_iterator cbegin() const
int GetId(int p1, int p2)
Get id of item whose parents are p1, p2... Create it if it doesn't exist.
Base::const_iterator base
OutStream out(std::cout)
Global stream used by the library for standard output. Initially it uses the same std::streambuf as s...
int FindId(int p1, int p2) const
Find id of item whose parents are p1, p2... Return -1 if it doesn't exist.
T & At(int index)
Access item of the array.
void Insert(int idx, int id, T &item)
const_iterator cend() const