MFEM  v4.3.0
Finite element discretization library
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Pages
hash.hpp
Go to the documentation of this file.
1 // Copyright (c) 2010-2021, Lawrence Livermore National Security, LLC. Produced
2 // at the Lawrence Livermore National Laboratory. All Rights reserved. See files
3 // LICENSE and NOTICE for details. LLNL-CODE-806117.
4 //
5 // This file is part of the MFEM library. For more information and source code
6 // availability visit https://mfem.org.
7 //
8 // MFEM is free software; you can redistribute it and/or modify it under the
9 // terms of the BSD-3 license. We welcome feedback and contributions, see file
10 // CONTRIBUTING.md for details.
11 
12 #ifndef MFEM_HASH
13 #define MFEM_HASH
14 
15 #include "../config/config.hpp"
16 #include "array.hpp"
17 #include "globals.hpp"
18 #include <type_traits>
19 
20 namespace mfem
21 {
22 
23 /** A concept for items that should be used in HashTable and be accessible by
24  * hashing two IDs.
25  */
26 struct Hashed2
27 {
28  int p1, p2;
29  int next;
30 };
31 
32 /** A concept for items that should be used in HashTable and be accessible by
33  * hashing four IDs.
34  */
35 struct Hashed4
36 {
37  int p1, p2, p3; // NOTE: p4 is neither hashed nor stored
38  int next;
39 };
40 
41 
42 /** HashTable is a container for items that require associative access through
43  * pairs (or quadruples) of indices:
44  *
45  * (p1, p2) -> item
46  * (p1, p2, p3, p4) -> item
47  *
48  * An example of this are edges and faces in a mesh. Each edge is uniquely
49  * identified by two parent vertices and so can be easily accessed from
50  * different elements using this class. Similarly for faces.
51  *
52  * The order of the p1, p2, ... indices is not relevant as they are sorted
53  * each time this class is invoked.
54  *
55  * There are two main methods this class provides. The Get(...) methods always
56  * return an item given the two or four indices. If the item didn't previously
57  * exist, the methods creates a new one. The Find(...) methods, on the other
58  * hand, just return NULL or -1 if the item doesn't exist.
59  *
60  * Each new item is automatically assigned a unique ID - the index of the item
61  * inside the BlockArray. The IDs may (but need not) be used as p1, p2, ... of
62  * other items.
63  *
64  * The item type (T) needs to follow either the Hashed2 or the Hashed4
65  * concept. It is easiest to just inherit from these structs.
66  *
67  * All items in the container can also be accessed sequentially using the
68  * provided iterator.
69  */
70 template<typename T>
71 class HashTable : public BlockArray<T>
72 {
73 protected:
75 
76 public:
77  HashTable(int block_size = 16*1024, int init_hash_size = 32*1024);
78  HashTable(const HashTable& other); // deep copy
79  ~HashTable();
80 
81  /// Get item whose parents are 'p1', 'p2'... Create it if it doesn't exist.
82  T* Get(int p1, int p2);
83  T* Get(int p1, int p2, int p3, int p4 = -1 /* p4 optional */);
84 
85  /// Get id of item whose parents are p1, p2... Create it if it doesn't exist.
86  int GetId(int p1, int p2);
87  int GetId(int p1, int p2, int p3, int p4 = -1);
88 
89  /// Find item whose parents are p1, p2... Return NULL if it doesn't exist.
90  T* Find(int p1, int p2);
91  T* Find(int p1, int p2, int p3, int p4 = -1);
92 
93  const T* Find(int p1, int p2) const;
94  const T* Find(int p1, int p2, int p3, int p4 = -1) const;
95 
96  /// Find id of item whose parents are p1, p2... Return -1 if it doesn't exist.
97  int FindId(int p1, int p2) const;
98  int FindId(int p1, int p2, int p3, int p4 = -1) const;
99 
100  /// Return the number of elements currently stored in the HashTable.
101  int Size() const { return Base::Size() - unused.Size(); }
102 
103  /// Return the total number of ids (used and unused) in the HashTable.
104  int NumIds() const { return Base::Size(); }
105 
106  /// Return the number of free/unused ids in the HashTable.
107  int NumFreeIds() const { return unused.Size(); }
108 
109  /// Return true if item 'id' exists in (is used by) the container.
110  /** It is assumed that 0 <= id < NumIds(). */
111  bool IdExists(int id) const { return (Base::At(id).next != -2); }
112 
113  /// Remove an item from the hash table.
114  /** Its id will be reused by newly added items. */
115  void Delete(int id);
116 
117  /// Remove all items.
118  void DeleteAll();
119 
120  /// Allocate an item at 'id'. Enlarge the underlying BlockArray if necessary.
121  /** This is a special purpose method used when loading data from a file.
122  Does nothing if the slot 'id' has already been allocated. */
123  void Alloc(int id, int p1, int p2);
124 
125  /// Reinitialize the internal list of unallocated items.
126  /** This is a special purpose method used when loading data from a file. */
127  void UpdateUnused();
128 
129  /// Make an item hashed under different parent IDs.
130  void Reparent(int id, int new_p1, int new_p2);
131  void Reparent(int id, int new_p1, int new_p2, int new_p3, int new_p4 = -1);
132 
133  /// Return total size of allocated memory (tables plus items), in bytes.
134  long MemoryUsage() const;
135 
136  /// Write details of the memory usage to the mfem output stream.
137  void PrintMemoryDetail() const;
138 
139  class iterator : public Base::iterator
140  {
141  protected:
142  friend class HashTable;
143  typedef typename Base::iterator base;
144 
145  iterator() { }
146  iterator(const base &it) : base(it)
147  {
148  while (base::good() && (*this)->next == -2) { base::next(); }
149  }
150 
151  public:
153  {
154  while (base::next(), base::good() && (*this)->next == -2) { }
155  return *this;
156  }
157  };
158 
160  {
161  protected:
162  friend class HashTable;
163  typedef typename Base::const_iterator base;
164 
166  const_iterator(const base &it) : base(it)
167  {
168  while (base::good() && (*this)->next == -2) { base::next(); }
169  }
170 
171  public:
173  {
174  while (base::next(), base::good() && (*this)->next == -2) { }
175  return *this;
176  }
177  };
178 
179  iterator begin() { return iterator(Base::begin()); }
180  iterator end() { return iterator(); }
181 
182  const_iterator cbegin() const { return const_iterator(Base::cbegin()); }
183  const_iterator cend() const { return const_iterator(); }
184 
185 protected:
186  int* table;
187  int mask;
189 
190  // hash functions (NOTE: the constants are arbitrary)
191  inline int Hash(int p1, int p2) const
192  { return (984120265*p1 + 125965121*p2) & mask; }
193 
194  inline int Hash(int p1, int p2, int p3) const
195  { return (984120265*p1 + 125965121*p2 + 495698413*p3) & mask; }
196 
197  // Delete() and Reparent() use one of these:
198  inline int Hash(const Hashed2& item) const
199  { return Hash(item.p1, item.p2); }
200 
201  inline int Hash(const Hashed4& item) const
202  { return Hash(item.p1, item.p2, item.p3); }
203 
204  int SearchList(int id, int p1, int p2) const;
205  int SearchList(int id, int p1, int p2, int p3) const;
206 
207  inline void Insert(int idx, int id, T &item);
208  void Unlink(int idx, int id);
209 
210  /// Check table load factor and resize if necessary
211  inline void CheckRehash();
212  void DoRehash();
213 };
214 
215 
216 /// Hash function for data sequences.
217 /** Depends on GnuTLS for SHA-256 hashing. */
219 {
220 protected:
221  void *hash_data;
222 
223  /// Add a sequence of bytes for hashing
224  void HashBuffer(const void *buffer, size_t num_bytes);
225 
226  /// Integer encoding method; result is independent of endianness and type
227  template <typename int_type_const_iter>
228  HashFunction &EncodeAndHashInts(int_type_const_iter begin,
229  int_type_const_iter end);
230 
231  /// Double encoding method: encode in little-endian byte-order
232  template <typename double_const_iter>
233  HashFunction &EncodeAndHashDoubles(double_const_iter begin,
234  double_const_iter end);
235 
236 public:
237  /// Default constructor: initialize the hash function
238  HashFunction();
239 
240  /// Destructor
241  ~HashFunction();
242 
243  /// Add a sequence of bytes for hashing
244  HashFunction &AppendBytes(const void *seq, size_t num_bytes)
245  { HashBuffer(seq, num_bytes); return *this; }
246 
247  /// Add a sequence of integers for hashing, given as a c-array.
248  /** Before hashing the sequence is encoded so that the result is independent
249  of endianness and type: int, long, unsigned, etc. */
250  template <typename int_type>
251  HashFunction &AppendInts(const int_type *ints, size_t num_ints)
252  { return EncodeAndHashInts(ints, ints + num_ints); }
253 
254  /// Add a sequence of integers for hashing, given as a fixed-size c-array.
255  /** Before hashing the sequence is encoded so that the result is independent
256  of endianness and type: int, long, unsigned, etc. */
257  template <typename int_type, size_t num_ints>
258  HashFunction &AppendInts(const int_type (&ints)[num_ints])
259  { return EncodeAndHashInts(ints, ints + num_ints); }
260 
261  /// Add a sequence of integers for hashing, given as a container.
262  /** Before hashing the sequence is encoded so that the result is independent
263  of endianness and type: int, long, unsigned, etc. */
264  template <typename int_type_container>
265  HashFunction &AppendInts(const int_type_container &ints)
266  { return EncodeAndHashInts(ints.begin(), ints.end()); }
267 
268  /// Add a sequence of doubles for hashing, given as a c-array.
269  /** Before hashing the sequence is encoded so that the result is independent
270  of endianness. */
271  HashFunction &AppendDoubles(const double *doubles, size_t num_doubles)
272  { return EncodeAndHashDoubles(doubles, doubles + num_doubles); }
273 
274  /// Add a sequence of doubles for hashing, given as a fixed-size c-array.
275  /** Before hashing the sequence is encoded so that the result is independent
276  of endianness. */
277  template <size_t num_doubles>
278  HashFunction &AppendDoubles(const double (&doubles)[num_doubles])
279  { return EncodeAndHashDoubles(doubles, doubles + num_doubles); }
280 
281  /// Add a sequence of doubles for hashing, given as a container.
282  /** Before hashing the sequence is encoded so that the result is independent
283  of endianness. */
284  template <typename double_container>
285  HashFunction &AppendDoubles(const double_container &doubles)
286  { return EncodeAndHashDoubles(doubles.begin(), doubles.end()); }
287 
288  /** @brief Return the hash string for the current sequence and reset (clear)
289  the sequence. */
290  std::string GetHash() const;
291 };
292 
293 
294 // implementation
295 
296 template<typename T>
297 HashTable<T>::HashTable(int block_size, int init_hash_size)
298  : Base(block_size)
299 {
300  mask = init_hash_size-1;
301  MFEM_VERIFY(!(init_hash_size & mask), "init_size must be a power of two.");
302 
303  table = new int[init_hash_size];
304  for (int i = 0; i < init_hash_size; i++)
305  {
306  table[i] = -1;
307  }
308 }
309 
310 template<typename T>
312  : Base(other), mask(other.mask)
313 {
314  int size = mask+1;
315  table = new int[size];
316  memcpy(table, other.table, size*sizeof(int));
317  other.unused.Copy(unused);
318 }
319 
320 template<typename T>
322 {
323  delete [] table;
324 }
325 
326 namespace internal
327 {
328 
329 inline void sort3(int &a, int &b, int &c)
330 {
331  if (a > b) { std::swap(a, b); }
332  if (a > c) { std::swap(a, c); }
333  if (b > c) { std::swap(b, c); }
334 }
335 
336 inline void sort4(int &a, int &b, int &c, int &d)
337 {
338  if (a > b) { std::swap(a, b); }
339  if (a > c) { std::swap(a, c); }
340  if (a > d) { std::swap(a, d); }
341  sort3(b, c, d);
342 }
343 
344 inline void sort4_ext(int &a, int &b, int &c, int &d)
345 {
346  if (d < 0) // support optional last index
347  {
348  sort3(a, b, c);
349  }
350  else
351  {
352  sort4(a, b, c, d);
353  }
354 }
355 
356 } // internal
357 
358 template<typename T>
359 inline T* HashTable<T>::Get(int p1, int p2)
360 {
361  return &(Base::At(GetId(p1, p2)));
362 }
363 
364 template<typename T>
365 inline T* HashTable<T>::Get(int p1, int p2, int p3, int p4)
366 {
367  return &(Base::At(GetId(p1, p2, p3, p4)));
368 }
369 
370 template<typename T>
371 int HashTable<T>::GetId(int p1, int p2)
372 {
373  // search for the item in the hashtable
374  if (p1 > p2) { std::swap(p1, p2); }
375  int idx = Hash(p1, p2);
376  int id = SearchList(table[idx], p1, p2);
377  if (id >= 0) { return id; }
378 
379  // not found - use an unused item or create a new one
380  int new_id;
381  if (unused.Size())
382  {
383  new_id = unused.Last();
384  unused.DeleteLast();
385  }
386  else
387  {
388  new_id = Base::Append();
389  }
390  T& item = Base::At(new_id);
391  item.p1 = p1;
392  item.p2 = p2;
393 
394  // insert into hashtable
395  Insert(idx, new_id, item);
396  CheckRehash();
397 
398  return new_id;
399 }
400 
401 template<typename T>
402 int HashTable<T>::GetId(int p1, int p2, int p3, int p4)
403 {
404  // search for the item in the hashtable
405  internal::sort4_ext(p1, p2, p3, p4);
406  int idx = Hash(p1, p2, p3);
407  int id = SearchList(table[idx], p1, p2, p3);
408  if (id >= 0) { return id; }
409 
410  // not found - use an unused item or create a new one
411  int new_id;
412  if (unused.Size())
413  {
414  new_id = unused.Last();
415  unused.DeleteLast();
416  }
417  else
418  {
419  new_id = Base::Append();
420  }
421  T& item = Base::At(new_id);
422  item.p1 = p1;
423  item.p2 = p2;
424  item.p3 = p3;
425 
426  // insert into hashtable
427  Insert(idx, new_id, item);
428  CheckRehash();
429 
430  return new_id;
431 }
432 
433 template<typename T>
434 inline T* HashTable<T>::Find(int p1, int p2)
435 {
436  int id = FindId(p1, p2);
437  return (id >= 0) ? &(Base::At(id)) : NULL;
438 }
439 
440 template<typename T>
441 inline T* HashTable<T>::Find(int p1, int p2, int p3, int p4)
442 {
443  int id = FindId(p1, p2, p3, p4);
444  return (id >= 0) ? &(Base::At(id)) : NULL;
445 }
446 
447 template<typename T>
448 inline const T* HashTable<T>::Find(int p1, int p2) const
449 {
450  int id = FindId(p1, p2);
451  return (id >= 0) ? &(Base::At(id)) : NULL;
452 }
453 
454 template<typename T>
455 inline const T* HashTable<T>::Find(int p1, int p2, int p3, int p4) const
456 {
457  int id = FindId(p1, p2, p3, p4);
458  return (id >= 0) ? &(Base::At(id)) : NULL;
459 }
460 
461 template<typename T>
462 int HashTable<T>::FindId(int p1, int p2) const
463 {
464  if (p1 > p2) { std::swap(p1, p2); }
465  return SearchList(table[Hash(p1, p2)], p1, p2);
466 }
467 
468 template<typename T>
469 int HashTable<T>::FindId(int p1, int p2, int p3, int p4) const
470 {
471  internal::sort4_ext(p1, p2, p3, p4);
472  return SearchList(table[Hash(p1, p2, p3)], p1, p2, p3);
473 }
474 
475 template<typename T>
476 int HashTable<T>::SearchList(int id, int p1, int p2) const
477 {
478  while (id >= 0)
479  {
480  const T& item = Base::At(id);
481  if (item.p1 == p1 && item.p2 == p2) { return id; }
482  id = item.next;
483  }
484  return -1;
485 }
486 
487 template<typename T>
488 int HashTable<T>::SearchList(int id, int p1, int p2, int p3) const
489 {
490  while (id >= 0)
491  {
492  const T& item = Base::At(id);
493  if (item.p1 == p1 && item.p2 == p2 && item.p3 == p3) { return id; }
494  id = item.next;
495  }
496  return -1;
497 }
498 
499 template<typename T>
501 {
502  const int fill_factor = 2;
503 
504  // is the table overfull?
505  if (Base::Size() > (mask+1) * fill_factor)
506  {
507  DoRehash();
508  }
509 }
510 
511 template<typename T>
513 {
514  delete [] table;
515 
516  // double the table size
517  int new_table_size = 2*(mask+1);
518  table = new int[new_table_size];
519  for (int i = 0; i < new_table_size; i++) { table[i] = -1; }
520  mask = new_table_size-1;
521 
522 #if defined(MFEM_DEBUG) && !defined(MFEM_USE_MPI)
523  mfem::out << _MFEM_FUNC_NAME << ": rehashing to size " << new_table_size
524  << std::endl;
525 #endif
526 
527  // reinsert all items
528  for (iterator it = begin(); it != end(); ++it)
529  {
530  Insert(Hash(*it), it.index(), *it);
531  }
532 }
533 
534 template<typename T>
535 inline void HashTable<T>::Insert(int idx, int id, T &item)
536 {
537  // add item at the beginning of the linked list
538  item.next = table[idx];
539  table[idx] = id;
540 }
541 
542 template<typename T>
543 void HashTable<T>::Unlink(int idx, int id)
544 {
545  // remove item from the linked list
546  int* p_id = table + idx;
547  while (*p_id >= 0)
548  {
549  T& item = Base::At(*p_id);
550  if (*p_id == id)
551  {
552  *p_id = item.next;
553  return;
554  }
555  p_id = &(item.next);
556  }
557  MFEM_ABORT("HashTable<>::Unlink: item not found!");
558 }
559 
560 template<typename T>
562 {
563  T& item = Base::At(id);
564  Unlink(Hash(item), id);
565  item.next = -2; // mark item as unused
566  unused.Append(id); // add its id to the unused ids
567 }
568 
569 template<typename T>
571 {
572  Base::DeleteAll();
573  for (int i = 0; i <= mask; i++) { table[i] = -1; }
574  unused.DeleteAll();
575 }
576 
577 template<typename T>
578 void HashTable<T>::Alloc(int id, int p1, int p2)
579 {
580  // enlarge the BlockArray to hold 'id'
581  while (id >= Base::Size())
582  {
583  Base::At(Base::Append()).next = -2; // append "unused" items
584  }
585 
586  T& item = Base::At(id);
587  if (item.next == -2)
588  {
589  item.next = -1;
590  item.p1 = p1;
591  item.p2 = p2;
592 
593  Insert(Hash(p1, p2), id, item);
594  }
595 }
596 
597 template<typename T>
599 {
600  unused.DeleteAll();
601  for (int i = 0; i < Base::Size(); i++)
602  {
603  if (Base::At(i).next == -2) { unused.Append(i); }
604  }
605 }
606 
607 template<typename T>
608 void HashTable<T>::Reparent(int id, int new_p1, int new_p2)
609 {
610  T& item = Base::At(id);
611  Unlink(Hash(item), id);
612 
613  if (new_p1 > new_p2) { std::swap(new_p1, new_p2); }
614  item.p1 = new_p1;
615  item.p2 = new_p2;
616 
617  // reinsert under new parent IDs
618  int new_idx = Hash(new_p1, new_p2);
619  Insert(new_idx, id, item);
620 }
621 
622 template<typename T>
624  int new_p1, int new_p2, int new_p3, int new_p4)
625 {
626  T& item = Base::At(id);
627  Unlink(Hash(item), id);
628 
629  internal::sort4_ext(new_p1, new_p2, new_p3, new_p4);
630  item.p1 = new_p1;
631  item.p2 = new_p2;
632  item.p3 = new_p3;
633 
634  // reinsert under new parent IDs
635  int new_idx = Hash(new_p1, new_p2, new_p3);
636  Insert(new_idx, id, item);
637 }
638 
639 template<typename T>
641 {
642  return (mask+1) * sizeof(int) + Base::MemoryUsage() + unused.MemoryUsage();
643 }
644 
645 template<typename T>
647 {
648  mfem::out << Base::MemoryUsage() << " + " << (mask+1) * sizeof(int)
649  << " + " << unused.MemoryUsage();
650 }
651 
652 
653 template <typename int_type_const_iter>
655  int_type_const_iter end)
656 {
657  // For hashing, an integer k is encoded as follows:
658  // * 1 byte = sign_bit(k) + num_bytes(k), where
659  // - sign_bit(k) = (k >= 0) ? 0 : 128
660  // - num_bytes(k) = minimum number of bytes needed to represent abs(k)
661  // with the convention that num_bytes(0) = 0.
662  // * num_bytes(k) bytes = the bytes of abs(k), starting with the least
663  // significant byte.
664 
665  static_assert(
666  std::is_integral<
667  /**/ typename std::remove_reference<decltype(*begin)>::type
668  /**/ >::value,
669  "invalid iterator type");
670 
671  // Skip encoding if hashing is not available:
672  if (hash_data == nullptr) { return *this; }
673 
674  constexpr int max_buffer_bytes = 64*1024;
675  unsigned char buffer[max_buffer_bytes];
676  int buffer_counter = 0;
677  while (begin != end)
678  {
679  int byte_counter = 0;
680  auto k = *begin;
681  buffer[buffer_counter] = (k >= 0) ? 0 : (k = -k, 128);
682  while (k != 0)
683  {
684  byte_counter++;
685  buffer[buffer_counter + byte_counter] = (unsigned char)(k % 256);
686  k /= 256; // (k >>= 8) results in error, e.g. for 'char'
687  }
688  buffer[buffer_counter] |= byte_counter;
689  buffer_counter += (byte_counter + 1);
690 
691  ++begin;
692 
693  if (begin == end ||
694  buffer_counter + (1 + sizeof(*begin)) > max_buffer_bytes)
695  {
696  HashBuffer(buffer, buffer_counter);
697  buffer_counter = 0;
698  }
699  }
700  return *this;
701 }
702 
703 template <typename double_const_iter>
705  double_const_iter end)
706 {
707  // For hashing, a double is encoded in little endian byte-order.
708 
709  static_assert(
710  std::is_same<decltype(*begin), const double &>::value,
711  "invalid iterator type");
712 
713  // Skip encoding if hashing is not available:
714  if (hash_data == nullptr) { return *this; }
715 
716  constexpr int max_buffer_bytes = 64*1024;
717  unsigned char buffer[max_buffer_bytes];
718  int buffer_counter = 0;
719  while (begin != end)
720  {
721  auto k = reinterpret_cast<const uint64_t &>(*begin);
722  for (int i = 0; i != 7; i++)
723  {
724  buffer[buffer_counter++] = (unsigned char)(k & 255); k >>= 8;
725  }
726  buffer[buffer_counter++] = (unsigned char)k;
727 
728  ++begin;
729 
730  if (begin == end || buffer_counter + 8 > max_buffer_bytes)
731  {
732  HashBuffer(buffer, buffer_counter);
733  buffer_counter = 0;
734  }
735  }
736  return *this;
737 }
738 
739 } // namespace mfem
740 
741 #endif
Hash function for data sequences.
Definition: hash.hpp:218
HashFunction & AppendInts(const int_type(&ints)[num_ints])
Add a sequence of integers for hashing, given as a fixed-size c-array.
Definition: hash.hpp:258
Array< int > unused
Definition: hash.hpp:188
int Size() const
Return the logical size of the array.
Definition: array.hpp:134
void * hash_data
Definition: hash.hpp:221
void UpdateUnused()
Reinitialize the internal list of unallocated items.
Definition: hash.hpp:598
int Hash(int p1, int p2, int p3) const
Definition: hash.hpp:194
HashFunction & EncodeAndHashDoubles(double_const_iter begin, double_const_iter end)
Double encoding method: encode in little-endian byte-order.
Definition: hash.hpp:704
int Hash(const Hashed4 &item) const
Definition: hash.hpp:201
const_iterator cbegin() const
Definition: array.hpp:594
void Unlink(int idx, int id)
Definition: hash.hpp:543
void Delete(int id)
Remove an item from the hash table.
Definition: hash.hpp:561
bool IdExists(int id) const
Return true if item &#39;id&#39; exists in (is used by) the container.
Definition: hash.hpp:111
HashTable(int block_size=16 *1024, int init_hash_size=32 *1024)
Definition: hash.hpp:297
void HashBuffer(const void *buffer, size_t num_bytes)
Add a sequence of bytes for hashing.
Definition: hash.cpp:45
int Size() const
Return the number of items actually stored.
Definition: array.hpp:497
int SearchList(int id, int p1, int p2) const
Definition: hash.hpp:476
void Copy(Array &copy) const
Create a copy of the internal array to the provided copy.
Definition: array.hpp:851
HashFunction & EncodeAndHashInts(int_type_const_iter begin, int_type_const_iter end)
Integer encoding method; result is independent of endianness and type.
Definition: hash.hpp:654
iterator & operator++()
Definition: hash.hpp:152
T * Get(int p1, int p2)
Get item whose parents are &#39;p1&#39;, &#39;p2&#39;... Create it if it doesn&#39;t exist.
Definition: hash.hpp:359
std::string GetHash() const
Return the hash string for the current sequence and reset (clear) the sequence.
Definition: hash.cpp:60
HashFunction & AppendBytes(const void *seq, size_t num_bytes)
Add a sequence of bytes for hashing.
Definition: hash.hpp:244
const_iterator(const base &it)
Definition: hash.hpp:166
void PrintMemoryDetail() const
Write details of the memory usage to the mfem output stream.
Definition: hash.hpp:646
int Hash(int p1, int p2) const
Definition: hash.hpp:191
int Size() const
Return the number of elements currently stored in the HashTable.
Definition: hash.hpp:101
void DeleteAll()
Remove all items.
Definition: hash.hpp:570
HashFunction & AppendDoubles(const double *doubles, size_t num_doubles)
Add a sequence of doubles for hashing, given as a c-array.
Definition: hash.hpp:271
void CheckRehash()
Check table load factor and resize if necessary.
Definition: hash.hpp:500
iterator begin()
Definition: array.hpp:591
HashFunction()
Default constructor: initialize the hash function.
Definition: hash.cpp:29
const_iterator & operator++()
Definition: hash.hpp:172
double b
Definition: lissajous.cpp:42
void Reparent(int id, int new_p1, int new_p2)
Make an item hashed under different parent IDs.
Definition: hash.hpp:608
T * Find(int p1, int p2)
Find item whose parents are p1, p2... Return NULL if it doesn&#39;t exist.
Definition: hash.hpp:434
iterator(const base &it)
Definition: hash.hpp:146
HashFunction & AppendDoubles(const double(&doubles)[num_doubles])
Add a sequence of doubles for hashing, given as a fixed-size c-array.
Definition: hash.hpp:278
iterator end()
Definition: hash.hpp:180
int * table
Definition: hash.hpp:186
int NumIds() const
Return the total number of ids (used and unused) in the HashTable.
Definition: hash.hpp:104
int Hash(const Hashed2 &item) const
Definition: hash.hpp:198
BlockArray< T > Base
Definition: hash.hpp:74
int NumFreeIds() const
Return the number of free/unused ids in the HashTable.
Definition: hash.hpp:107
int next
Definition: hash.hpp:38
HashFunction & AppendInts(const int_type *ints, size_t num_ints)
Add a sequence of integers for hashing, given as a c-array.
Definition: hash.hpp:251
iterator begin()
Definition: hash.hpp:179
double a
Definition: lissajous.cpp:41
long MemoryUsage() const
Return total size of allocated memory (tables plus items), in bytes.
Definition: hash.hpp:640
const_iterator cbegin() const
Definition: hash.hpp:182
HashFunction & AppendInts(const int_type_container &ints)
Add a sequence of integers for hashing, given as a container.
Definition: hash.hpp:265
~HashFunction()
Destructor.
Definition: hash.cpp:38
int GetId(int p1, int p2)
Get id of item whose parents are p1, p2... Create it if it doesn&#39;t exist.
Definition: hash.hpp:371
HashFunction & AppendDoubles(const double_container &doubles)
Add a sequence of doubles for hashing, given as a container.
Definition: hash.hpp:285
Base::iterator base
Definition: hash.hpp:143
Base::const_iterator base
Definition: hash.hpp:163
OutStream out(std::cout)
Global stream used by the library for standard output. Initially it uses the same std::streambuf as s...
Definition: globals.hpp:66
int FindId(int p1, int p2) const
Find id of item whose parents are p1, p2... Return -1 if it doesn&#39;t exist.
Definition: hash.hpp:462
T & At(int index)
Access item of the array.
Definition: array.hpp:481
int next
Definition: hash.hpp:29
void DoRehash()
Definition: hash.hpp:512
void Insert(int idx, int id, T &item)
Definition: hash.hpp:535
const_iterator cend() const
Definition: hash.hpp:183