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);
85 int GetId(
int p1,
int p2);
86 int GetId(
int p1,
int p2,
int p3,
int p4);
89 T*
Find(
int p1,
int p2);
90 T*
Find(
int p1,
int p2,
int p3,
int p4);
92 const T*
Find(
int p1,
int p2)
const;
93 const T*
Find(
int p1,
int p2,
int p3,
int p4)
const;
96 int FindId(
int p1,
int p2)
const;
97 int FindId(
int p1,
int p2,
int p3,
int p4)
const;
117 void Reparent(
int id,
int new_p1,
int new_p2);
118 void Reparent(
int id,
int new_p1,
int new_p2,
int new_p3,
int new_p4);
166 iterator
end() {
return iterator(); }
169 const_iterator
cend()
const {
return const_iterator(); }
177 inline int Hash(
int p1,
int p2)
const
178 {
return (984120265*p1 + 125965121*p2) &
mask; }
180 inline int Hash(
int p1,
int p2,
int p3)
const
181 {
return (984120265*p1 + 125965121*p2 + 495698413*p3) &
mask; }
191 int SearchList(
int id,
int p1,
int p2,
int p3)
const;
193 inline void Insert(
int idx,
int id, T &item);
194 void Unlink(
int idx,
int id);
208 mask = init_hash_size-1;
209 MFEM_VERIFY(!(init_hash_size &
mask),
"init_size must be a power of two.");
211 table =
new int[init_hash_size];
212 for (
int i = 0; i < init_hash_size; i++) {
table[i] = -1; }
217 :
Base(other), mask(other.mask)
234 inline void sort3(
int &a,
int &b,
int &c)
236 if (a > b) { std::swap(a, b); }
237 if (a > c) { std::swap(a, c); }
238 if (b > c) { std::swap(b, c); }
241 inline void sort4(
int &a,
int &b,
int &c,
int &d)
243 if (a > b) { std::swap(a, b); }
244 if (a > c) { std::swap(a, c); }
245 if (a > d) { std::swap(a, d); }
254 return &(Base::At(GetId(p1, p2)));
260 return &(Base::At(GetId(p1, p2, p3, p4)));
267 if (p1 > p2) { std::swap(p1, p2); }
268 int idx = Hash(p1, p2);
269 int id = SearchList(table[idx], p1, p2);
270 if (
id >= 0) {
return id; }
276 new_id = unused.Last();
281 new_id = Base::Append();
283 T& item = Base::At(new_id);
288 Insert(idx, new_id, item);
298 internal::sort4(p1, p2, p3, p4);
299 int idx = Hash(p1, p2, p3);
300 int id = SearchList(table[idx], p1, p2, p3);
301 if (
id >= 0) {
return id; }
307 new_id = unused.Last();
312 new_id = Base::Append();
314 T& item = Base::At(new_id);
320 Insert(idx, new_id, item);
329 int id = FindId(p1, p2);
330 return (
id >= 0) ? &(Base::At(
id)) : NULL;
336 int id = FindId(p1, p2, p3, p4);
337 return (
id >= 0) ? &(Base::At(
id)) : NULL;
343 int id = FindId(p1, p2);
344 return (
id >= 0) ? &(Base::At(
id)) : NULL;
350 int id = FindId(p1, p2, p3, p4);
351 return (
id >= 0) ? &(Base::At(
id)) : NULL;
357 if (p1 > p2) { std::swap(p1, p2); }
358 return SearchList(table[Hash(p1, p2)], p1, p2);
364 internal::sort4(p1, p2, p3, p4);
365 return SearchList(table[Hash(p1, p2, p3)], p1, p2, p3);
373 const T& item = Base::At(
id);
374 if (item.p1 == p1 && item.p2 == p2) {
return id; }
385 const T& item = Base::At(
id);
386 if (item.p1 == p1 && item.p2 == p2 && item.p3 == p3) {
return id; }
395 const int fill_factor = 2;
398 if (Base::Size() > (mask+1) * fill_factor)
410 int new_table_size = 2*(mask+1);
411 table =
new int[new_table_size];
412 for (
int i = 0; i < new_table_size; i++) { table[i] = -1; }
413 mask = new_table_size-1;
415 #if defined(MFEM_DEBUG) && !defined(MFEM_USE_MPI)
416 mfem::out << _MFEM_FUNC_NAME <<
": rehashing to size " << new_table_size
421 for (
iterator it = begin(); it != end(); ++it)
423 Insert(Hash(*it), it.index(), *it);
431 item.next = table[idx];
439 int* p_id = table + idx;
442 T& item = Base::At(*p_id);
450 MFEM_ABORT(
"HashTable<>::Unlink: item not found!");
456 T& item = Base::At(
id);
457 Unlink(Hash(item),
id);
465 T& item = Base::At(
id);
466 Unlink(Hash(item),
id);
468 if (new_p1 > new_p2) { std::swap(new_p1, new_p2); }
473 int new_idx = Hash(new_p1, new_p2);
474 Insert(new_idx,
id, item);
479 int new_p1,
int new_p2,
int new_p3,
int new_p4)
481 T& item = Base::At(
id);
482 Unlink(Hash(item),
id);
484 internal::sort4(new_p1, new_p2, new_p3, new_p4);
490 int new_idx = Hash(new_p1, new_p2, new_p3);
491 Insert(new_idx,
id, item);
497 return (mask+1) *
sizeof(int) + Base::MemoryUsage() + unused.MemoryUsage();
503 mfem::out << Base::MemoryUsage() <<
" + " << (mask+1) *
sizeof(
int)
504 <<
" + " << 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 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