IFPACK Development
Loading...
Searching...
No Matches
Ifpack_HashTable.h
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// ============================================================================
94template<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
217 int getRecommendedHashSize (int n)
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
273class 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
double get(const key_type key)
Returns an element from the hash table, or 0.0 if not found.
void arrayify(key_type *key_array, double *val_array)
Converts the contents in array format for both keys and values.
void print()
Basic printing routine.
void set(const key_type key, const double value, const bool addToValue=false)
Sets an element in the hash table.
void reset()
Resets the entries of the already allocated memory. This method can be used to clean an array,...
int getNumEntries() const
Returns the number of stored entries.
TIfpack_HashTable(const int n_keys=1031, const int n_sets=1)
constructor.