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);
170 iterator
end() {
return iterator(); }
173 const_iterator
cend()
const {
return const_iterator(); }
181 inline int Hash(
int p1,
int p2)
const
182 {
return (984120265*p1 + 125965121*p2) &
mask; }
184 inline int Hash(
int p1,
int p2,
int p3)
const
185 {
return (984120265*p1 + 125965121*p2 + 495698413*p3) &
mask; }
195 int SearchList(
int id,
int p1,
int p2,
int p3)
const;
197 inline void Insert(
int idx,
int id, T &item);
198 void Unlink(
int idx,
int id);
212 mask = init_hash_size-1;
213 MFEM_VERIFY(!(init_hash_size &
mask),
"init_size must be a power of two.");
215 table =
new int[init_hash_size];
216 for (
int i = 0; i < init_hash_size; i++) {
table[i] = -1; }
221 :
Base(other), mask(other.mask)
238 inline void sort3(
int &
a,
int &
b,
int &c)
240 if (a > b) { std::swap(a, b); }
241 if (a > c) { std::swap(a, c); }
242 if (b > c) { std::swap(b, c); }
245 inline void sort4(
int &a,
int &b,
int &c,
int &d)
247 if (a > b) { std::swap(a, b); }
248 if (a > c) { std::swap(a, c); }
249 if (a > d) { std::swap(a, d); }
253 inline void sort4_ext(
int &a,
int &b,
int &c,
int &d)
270 return &(Base::At(GetId(p1, p2)));
276 return &(Base::At(GetId(p1, p2, p3, p4)));
283 if (p1 > p2) { std::swap(p1, p2); }
284 int idx = Hash(p1, p2);
285 int id = SearchList(table[idx], p1, p2);
286 if (
id >= 0) {
return id; }
292 new_id = unused.Last();
297 new_id = Base::Append();
299 T& item = Base::At(new_id);
304 Insert(idx, new_id, item);
314 internal::sort4_ext(p1, p2, p3, p4);
315 int idx = Hash(p1, p2, p3);
316 int id = SearchList(table[idx], p1, p2, p3);
317 if (
id >= 0) {
return id; }
323 new_id = unused.Last();
328 new_id = Base::Append();
330 T& item = Base::At(new_id);
336 Insert(idx, new_id, item);
345 int id = FindId(p1, p2);
346 return (
id >= 0) ? &(Base::At(
id)) : NULL;
352 int id = FindId(p1, p2, p3, p4);
353 return (
id >= 0) ? &(Base::At(
id)) : NULL;
359 int id = FindId(p1, p2);
360 return (
id >= 0) ? &(Base::At(
id)) : NULL;
366 int id = FindId(p1, p2, p3, p4);
367 return (
id >= 0) ? &(Base::At(
id)) : NULL;
373 if (p1 > p2) { std::swap(p1, p2); }
374 return SearchList(table[Hash(p1, p2)], p1, p2);
380 internal::sort4_ext(p1, p2, p3, p4);
381 return SearchList(table[Hash(p1, p2, p3)], p1, p2, p3);
389 const T& item = Base::At(
id);
390 if (item.p1 == p1 && item.p2 == p2) {
return id; }
401 const T& item = Base::At(
id);
402 if (item.p1 == p1 && item.p2 == p2 && item.p3 == p3) {
return id; }
411 const int fill_factor = 2;
414 if (Base::Size() > (mask+1) * fill_factor)
426 int new_table_size = 2*(mask+1);
427 table =
new int[new_table_size];
428 for (
int i = 0; i < new_table_size; i++) { table[i] = -1; }
429 mask = new_table_size-1;
431 #if defined(MFEM_DEBUG) && !defined(MFEM_USE_MPI)
432 mfem::out << _MFEM_FUNC_NAME <<
": rehashing to size " << new_table_size
437 for (
iterator it = begin(); it != end(); ++it)
439 Insert(Hash(*it), it.index(), *it);
447 item.next = table[idx];
455 int* p_id = table + idx;
458 T& item = Base::At(*p_id);
466 MFEM_ABORT(
"HashTable<>::Unlink: item not found!");
472 T& item = Base::At(
id);
473 Unlink(Hash(item),
id);
482 for (
int i = 0; i <= mask; i++) { table[i] = -1; }
489 T& item = Base::At(
id);
490 Unlink(Hash(item),
id);
492 if (new_p1 > new_p2) { std::swap(new_p1, new_p2); }
497 int new_idx = Hash(new_p1, new_p2);
498 Insert(new_idx,
id, item);
503 int new_p1,
int new_p2,
int new_p3,
int new_p4)
505 T& item = Base::At(
id);
506 Unlink(Hash(item),
id);
508 internal::sort4_ext(new_p1, new_p2, new_p3, new_p4);
514 int new_idx = Hash(new_p1, new_p2, new_p3);
515 Insert(new_idx,
id, item);
521 return (mask+1) *
sizeof(int) + Base::MemoryUsage() + unused.MemoryUsage();
527 mfem::out << Base::MemoryUsage() <<
" + " << (mask+1) *
sizeof(
int)
528 <<
" + " << unused.MemoryUsage();
int Size() const
Return the 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 internal array to the provided copy.
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
Write details of the memory usage to the mfem output stream.
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