Ifpack Package Browser (Single Doxygen Collection)  Development
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Ifpack_HashTable.h
Go to the documentation of this file.
1 /*@HEADER
2 // ***********************************************************************
3 //
4 // Ifpack: Object-Oriented Algebraic Preconditioner Package
5 // Copyright (2002) Sandia Corporation
6 //
7 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
8 // license for use of this work by or on behalf of the U.S. Government.
9 //
10 // Redistribution and use in source and binary forms, with or without
11 // modification, are permitted provided that the following conditions are
12 // met:
13 //
14 // 1. Redistributions of source code must retain the above copyright
15 // notice, this list of conditions and the following disclaimer.
16 //
17 // 2. Redistributions in binary form must reproduce the above copyright
18 // notice, this list of conditions and the following disclaimer in the
19 // documentation and/or other materials provided with the distribution.
20 //
21 // 3. Neither the name of the Corporation nor the names of the
22 // contributors may be used to endorse or promote products derived from
23 // this software without specific prior written permission.
24 //
25 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
26 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
29 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 //
37 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
38 //
39 // ***********************************************************************
40 //@HEADER
41 */
42 
43 /* \file Ifpack_HashTable.h
44  *
45  * \brief HashTable used in Ifpack_ICT and Ifpack_ILUT.
46  *
47  * \author Marzio Sala, ETHZ/D-INFK.
48  *
49  * \date Last modified on 30-Jun-06.
50  */
51 
52 #ifndef IFPACK_HASHTABLE_H
53 #define IFPACK_HASHTABLE_H
54 
55 #if defined(Ifpack_SHOW_DEPRECATED_WARNINGS)
56 #ifdef __GNUC__
57 #warning "The Ifpack package is deprecated"
58 #endif
59 #endif
60 
61 #include "Ifpack_ConfigDefs.h"
62 
63 // ============================================================================
64 // Hash table with good performances and high level of memory reuse.
65 // Given a maximum number of keys n_keys, this class allocates chunks of memory
66 // to store n_keys keys and values.
67 //
68 // Usage:
69 //
70 // 1) Instantiate a object,
71 //
72 // Ifpack_HashTable Hash(n_keys);
73 //
74 // n_keys - maximum number of keys (This will be the n_keys with zero
75 // collisons.)
76 //
77 // 3) use it, then delete it:
78 //
79 // Hash.get(key, value) --> returns the value stored on key, or 0.0
80 // if not found.
81 // Hash.set(key, value) --> sets the value in the hash table, replace
82 // existing values.
83 // Hash.set(key, value, true) --> to sum into an already inserted value
84 // Hash.arrayify(...)
85 //
86 // 4) clean memory:
87 //
88 // Hash.reset();
89 //
90 // \author Marzio Sala, ETHZ/COLAB
91 //
92 // \date 30-Jun-06
93 // ============================================================================
94 template<typename key_type>
96 {
97  public:
99  TIfpack_HashTable(const int n_keys = 1031, const int n_sets = 1)
100  {
101  n_keys_ = getRecommendedHashSize(n_keys) ;
102  n_sets_ = n_sets;
103  seed_ = (2654435761U);
104 
105  keys_.reserve(50);
106  vals_.reserve(50);
107 
108  keys_.resize(n_sets_);
109  vals_.resize(n_sets_);
110 
111  for (int i = 0; i < n_sets_; ++i)
112  {
113  keys_[i].resize(n_keys_);
114  vals_[i].resize(n_keys_);
115  }
116 
117  counter_.resize(n_keys_);
118  for (int i = 0; i < n_keys_; ++i) counter_[i] = 0;
119  }
120 
122  inline double get(const key_type key)
123  {
124  int hashed_key = doHash(key);
125 
126  for (int set_ptr = 0; set_ptr < counter_[hashed_key]; ++set_ptr)
127  {
128  if (keys_[set_ptr][hashed_key] == key)
129  return(vals_[set_ptr][hashed_key]);
130  }
131 
132  return(0.0);
133  }
134 
136  inline void set(const key_type key, const double value,
137  const bool addToValue = false)
138  {
139  int hashed_key = doHash(key);
140  int& hashed_counter = counter_[hashed_key];
141 
142  for (int set_ptr = 0; set_ptr < hashed_counter; ++set_ptr)
143  {
144  if (keys_[set_ptr][hashed_key] == key)
145  {
146  if (addToValue)
147  vals_[set_ptr][hashed_key] += value;
148  else
149  vals_[set_ptr][hashed_key] = value;
150  return;
151  }
152  }
153 
154  if (hashed_counter < n_sets_)
155  {
156  keys_[hashed_counter][hashed_key] = key;
157  vals_[hashed_counter][hashed_key] = value;
158  ++hashed_counter;
159  return;
160  }
161 
162  std::vector<key_type> new_key;
163  std::vector<double> new_val;
164 
165  keys_.push_back(new_key);
166  vals_.push_back(new_val);
167  keys_[n_sets_].resize(n_keys_);
168  vals_[n_sets_].resize(n_keys_);
169 
170  keys_[n_sets_][hashed_key] = key;
171  vals_[n_sets_][hashed_key] = value;
172  ++hashed_counter;
173  ++n_sets_;
174  }
175 
180  inline void reset()
181  {
182  memset(&counter_[0], 0, sizeof(int) * n_keys_);
183  }
184 
186  inline int getNumEntries() const
187  {
188  int n_entries = 0;
189  for (int key = 0; key < n_keys_; ++key)
190  n_entries += counter_[key];
191  return(n_entries);
192  }
193 
195  void arrayify(key_type* key_array, double* val_array)
196  {
197  int count = 0;
198  for (int key = 0; key < n_keys_; ++key)
199  for (int set_ptr = 0; set_ptr < counter_[key]; ++set_ptr)
200  {
201  key_array[count] = keys_[set_ptr][key];
202  val_array[count] = vals_[set_ptr][key];
203  ++count;
204  }
205  }
206 
208  void print()
209  {
210  using std::cout;
211  using std::endl;
212 
213  cout << "n_keys = " << n_keys_ << endl;
214  cout << "n_sets = " << n_sets_ << endl;
215  }
216 
218  {
219  /* Prime number approximately in the middle of the range [2^x..2^(x+1)]
220  * is in primes[x-1]. Every prime number stored is approximately two
221  * times the previous one, so hash table size doubles every time.
222  */
223  int primes[] = {
224  3, 7, 13, 23, 53, 97, 193, 389, 769, 1543, 3079, 6151, 12289, 24593,
225  49157, 98317, 196613, 393241, 786433, 1572869, 3145739, 6291469,
226  12582917, 25165842, 50331653, 100663319, 201326611, 402653189,
227  805306457, 1610612741 } ;
228  int i, hsize ;
229 
230  /* SRSR : err on the side of performance and choose the next largest
231  * prime number. One can also choose primes[i-1] below to cut the
232  * memory by half.
233  */
234  hsize = primes[29] ;
235  for (i = 6 ; i < 30 ; i++)
236  {
237  if (n <= primes[i])
238  {
239  /*hsize = (i == 0 ? n : primes[i-1]) ;*/
240  hsize = primes[i] ;
241  break ;
242  }
243  }
244 
245  return hsize ;
246  }
247 
248  private:
250  inline int doHash(const key_type key)
251  {
252  return (key % n_keys_);
253  //return ((seed_ ^ key) % n_keys_);
254  }
255 
256  int n_keys_;
257  int n_sets_;
258  std::vector<std::vector<double> > vals_;
259  std::vector<std::vector<key_type> > keys_;
260  std::vector<int> counter_;
261  unsigned int seed_;
262 };
263 
265 {
266  public:
267  Ifpack_HashTable(const int n_keys = 1031, const int n_sets = 1)
268  : TIfpack_HashTable<int>(n_keys, n_sets)
269  {
270  }
271 };
272 
273 class Ifpack_HashTable64 : public TIfpack_HashTable<long long>
274 {
275  public:
276  Ifpack_HashTable64(const int n_keys = 1031, const int n_sets = 1)
277  : TIfpack_HashTable<long long>(n_keys, n_sets)
278  {
279  }
280 };
281 
282 #endif
Ifpack_HashTable(const int n_keys=1031, const int n_sets=1)
std::vector< int > counter_
std::vector< std::vector< key_type > > keys_
void print()
Basic printing routine.
std::vector< std::vector< double > > vals_
void set(const key_type key, const double value, const bool addToValue=false)
Sets an element in the hash table.
TIfpack_HashTable(const int n_keys=1031, const int n_sets=1)
constructor.
void arrayify(key_type *key_array, double *val_array)
Converts the contents in array format for both keys and values.
Ifpack_HashTable64(const int n_keys=1031, const int n_sets=1)
int getNumEntries() const
Returns the number of stored entries.
int getRecommendedHashSize(int n)
void reset()
Resets the entries of the already allocated memory. This method can be used to clean an array...
int doHash(const key_type key)
Performs the hashing.