Files
mlpack/fastlib/trilinos/include/Ifpack_HashTable.h
T

211 lines
5.6 KiB
C++

//@HEADER
/*
************************************************************************
IFPACK: Robust Algebraic Preconditioning Package
Copyright (2001) Sandia Corporation
Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
license for use of this work by or on behalf of the U.S. Government.
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
This library is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
USA
Questions? Contact Michael A. Heroux (maherou@sandia.gov)
************************************************************************
*/
//@HEADER
/* \file Ifpack_HashTable.h
*
* \brief HashTable used in Ifpack_ICT and Ifpack_ILUT.
*
* \author Marzio Sala, ETHZ/D-INFK.
*
* \date Last modified on 30-Jun-06.
*/
#ifndef IFPACK_HASHTABLE_H
#define IFPACK_HASHTABLE_H
#include "Ifpack_ConfigDefs.h"
// ============================================================================
// Hash table with good performances and high level of memory reuse.
// Given a maximum number of keys n_keys, this class allocates chunks of memory
// to store n_keys keys and values.
//
// Usage:
//
// 1) Instantiate a object,
//
// Ifpack_HashTable Hash(size);
//
// size should be a prime number, like 2^k - 1.
//
// 3) use it, then delete it:
//
// Hash.get(key, value) --> returns the value stored on key, or 0.0
// if not found.
// Hash.set(key, value) --> sets the value in the hash table, replace
// existing values.
// Hash.set(key, value, true) --> to sum into an already inserted value
// Hash.arrayify(...)
//
// 4) clean memory:
//
// Hash.reset();
//
// \author Marzio Sala, ETHZ/COLAB
//
// \date 30-Jun-06
// ============================================================================
class Ifpack_HashTable
{
public:
//! constructor.
Ifpack_HashTable(const int n_keys = 1031, const int n_sets = 1)
{
n_keys_ = n_keys;
n_sets_ = n_sets;
seed_ = (2654435761U);
keys_.reserve(50);
vals_.reserve(50);
keys_.resize(n_sets_);
vals_.resize(n_sets_);
for (int i = 0; i < n_sets_; ++i)
{
keys_[i].resize(n_keys_);
vals_[i].resize(n_keys_);
}
counter_.resize(n_keys_);
for (int i = 0; i < n_keys_; ++i) counter_[i] = 0;
}
//! Returns an element from the hash table, or 0.0 if not found.
inline double get(const int key)
{
int hashed_key = doHash(key);
for (int set = 0; set < counter_[hashed_key]; ++set)
{
if (keys_[set][hashed_key] == key)
return(vals_[set][hashed_key]);
}
return(0.0);
}
//! Sets an element in the hash table.
inline void set(const int key, const double value,
const bool addToValue = false)
{
int hashed_key = doHash(key);
int& hashed_counter = counter_[hashed_key];
for (int set = 0; set < hashed_counter; ++set)
{
if (keys_[set][hashed_key] == key)
{
if (addToValue)
vals_[set][hashed_key] += value;
else
vals_[set][hashed_key] = value;
return;
}
}
if (hashed_counter < n_sets_)
{
keys_[hashed_counter][hashed_key] = key;
vals_[hashed_counter][hashed_key] = value;
++hashed_counter;
return;
}
std::vector<int> new_key;
std::vector<double> new_val;
keys_.push_back(new_key);
vals_.push_back(new_val);
keys_[n_sets_].resize(n_keys_);
vals_[n_sets_].resize(n_keys_);
keys_[n_sets_][hashed_key] = key;
vals_[n_sets_][hashed_key] = value;
++hashed_counter;
++n_sets_;
}
/*! \brief Resets the entries of the already allocated memory. This
* method can be used to clean an array, to be reused without additional
* memory allocation/deallocation.
*/
inline void reset()
{
memset(&counter_[0], 0, sizeof(int) * n_keys_);
}
//! Returns the number of stored entries.
inline int getNumEntries() const
{
int n_entries = 0;
for (int key = 0; key < n_keys_; ++key)
n_entries += counter_[key];
return(n_entries);
}
//! Converts the contents in array format for both keys and values.
void arrayify(int* key_array, double* val_array)
{
int count = 0;
for (int key = 0; key < n_keys_; ++key)
for (int set = 0; set < counter_[key]; ++set)
{
key_array[count] = keys_[set][key];
val_array[count] = vals_[set][key];
++count;
}
}
//! Basic printing routine.
void print()
{
cout << "n_keys = " << n_keys_ << endl;
cout << "n_sets = " << n_sets_ << endl;
}
private:
//! Performs the hashing.
inline int doHash(const int key)
{
return (key % n_keys_);
//return ((seed_ ^ key) % n_keys_);
}
int n_keys_;
int n_sets_;
std::vector<std::vector<double> > vals_;
std::vector<std::vector<int> > keys_;
std::vector<int> counter_;
unsigned int seed_;
};
#endif