mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
HashTable changes
- make table power-of-two, but since it seems to give 1-2% performance improvement, maybe forget it too. - remove two-argument form of hashing classes and do the modulus direclty within HashTable instead. This simplifies things a fair bit. - migrate Hash<void*> from db/dlLibrary to primitives/hashes/Hash
This commit is contained in:
@ -85,15 +85,6 @@ public:
|
||||
{
|
||||
return word::hash()(key.first()) + word::hash()(key.second());
|
||||
}
|
||||
|
||||
label operator()
|
||||
(
|
||||
const interfacePair& key,
|
||||
const label tableSize
|
||||
) const
|
||||
{
|
||||
return mag(operator()(key)) % tableSize;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -30,20 +30,49 @@ License
|
||||
#include "HashTable.H"
|
||||
#include "List.H"
|
||||
|
||||
// * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * //
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
Foam::label Foam::HashTable<T, Key, Hash>::canonicalSize(const label size)
|
||||
{
|
||||
if (size < 1)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// enforce power of two
|
||||
unsigned int goodSize = size;
|
||||
|
||||
if (goodSize & (goodSize - 1))
|
||||
{
|
||||
// brute-force is fast enough
|
||||
goodSize = 1;
|
||||
while (goodSize < unsigned(size))
|
||||
{
|
||||
goodSize <<= 1;
|
||||
}
|
||||
}
|
||||
|
||||
return goodSize;
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
Foam::HashTable<T, Key, Hash>::HashTable(const label size)
|
||||
:
|
||||
tableSize_(size),
|
||||
table_(NULL),
|
||||
HashTableName(),
|
||||
nElmts_(0),
|
||||
tableSize_(canonicalSize(size)),
|
||||
table_(NULL),
|
||||
endIter_(*this, NULL, 0),
|
||||
endConstIter_(*this, NULL, 0)
|
||||
{
|
||||
if (tableSize_)
|
||||
{
|
||||
table_ = new hashedEntry*[tableSize_];
|
||||
|
||||
for (label hashIdx = 0; hashIdx < tableSize_; hashIdx++)
|
||||
{
|
||||
table_[hashIdx] = 0;
|
||||
@ -56,9 +85,9 @@ template<class T, class Key, class Hash>
|
||||
Foam::HashTable<T, Key, Hash>::HashTable(const HashTable<T, Key, Hash>& ht)
|
||||
:
|
||||
HashTableName(),
|
||||
nElmts_(0),
|
||||
tableSize_(ht.tableSize_),
|
||||
table_(NULL),
|
||||
nElmts_(0),
|
||||
endIter_(*this, NULL, 0),
|
||||
endConstIter_(*this, NULL, 0)
|
||||
{
|
||||
@ -85,9 +114,9 @@ Foam::HashTable<T, Key, Hash>::HashTable
|
||||
)
|
||||
:
|
||||
HashTableName(),
|
||||
nElmts_(0),
|
||||
tableSize_(0),
|
||||
table_(NULL),
|
||||
nElmts_(0),
|
||||
endIter_(*this, NULL, 0),
|
||||
endConstIter_(*this, NULL, 0)
|
||||
{
|
||||
@ -115,7 +144,7 @@ bool Foam::HashTable<T, Key, Hash>::found(const Key& key) const
|
||||
{
|
||||
if (nElmts_)
|
||||
{
|
||||
const label hashIdx = Hash()(key, tableSize_);
|
||||
const label hashIdx = hashKeyIndex(key);
|
||||
|
||||
for (hashedEntry* ep = table_[hashIdx]; ep; ep = ep->next_)
|
||||
{
|
||||
@ -147,7 +176,7 @@ Foam::HashTable<T, Key, Hash>::find
|
||||
{
|
||||
if (nElmts_)
|
||||
{
|
||||
const label hashIdx = Hash()(key, tableSize_);
|
||||
const label hashIdx = hashKeyIndex(key);
|
||||
|
||||
for (hashedEntry* ep = table_[hashIdx]; ep; ep = ep->next_)
|
||||
{
|
||||
@ -179,7 +208,7 @@ Foam::HashTable<T, Key, Hash>::find
|
||||
{
|
||||
if (nElmts_)
|
||||
{
|
||||
label hashIdx = Hash()(key, tableSize_);
|
||||
const label hashIdx = hashKeyIndex(key);
|
||||
|
||||
for (hashedEntry* ep = table_[hashIdx]; ep; ep = ep->next_)
|
||||
{
|
||||
@ -231,7 +260,8 @@ bool Foam::HashTable<T, Key, Hash>::set
|
||||
resize(2);
|
||||
}
|
||||
|
||||
label hashIdx = Hash()(key, tableSize_);
|
||||
const label hashIdx = hashKeyIndex(key);
|
||||
|
||||
hashedEntry* existing = 0;
|
||||
hashedEntry* prev = 0;
|
||||
|
||||
@ -449,14 +479,16 @@ Foam::label Foam::HashTable<T, Key, Hash>::erase
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
void Foam::HashTable<T, Key, Hash>::resize(const label newSize)
|
||||
void Foam::HashTable<T, Key, Hash>::resize(const label sz)
|
||||
{
|
||||
label newSize = canonicalSize(sz);
|
||||
|
||||
if (newSize == tableSize_)
|
||||
{
|
||||
# ifdef FULLDEBUG
|
||||
if (debug)
|
||||
{
|
||||
Info<< "HashTable<T, Key, Hash>::resize(const label newSize) : "
|
||||
Info<< "HashTable<T, Key, Hash>::resize(const label) : "
|
||||
<< "new table size == old table size\n";
|
||||
}
|
||||
# endif
|
||||
|
||||
@ -108,18 +108,25 @@ class HashTable
|
||||
|
||||
// Private data: size of table, the table and current number of elements
|
||||
|
||||
//- The current number of elements in table
|
||||
label nElmts_;
|
||||
|
||||
//- Number of primary entries allocated in table (not necessarily used)
|
||||
label tableSize_;
|
||||
|
||||
//- The table of primary entries
|
||||
hashedEntry** table_;
|
||||
|
||||
//- The current number of elements in table
|
||||
label nElmts_;
|
||||
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
//- Return a canonical (power-of-two) size
|
||||
static label canonicalSize(const label);
|
||||
|
||||
//- Return the hash index of the Key within the current table size.
|
||||
// No checks for zero-sized tables.
|
||||
inline label hashKeyIndex(const Key&) const;
|
||||
|
||||
//- Assign a new hashedEntry to a possibly already existing key
|
||||
bool set(const Key&, const T& newElmt, bool protect);
|
||||
|
||||
|
||||
@ -42,6 +42,17 @@ inline Foam::HashTable<T, Key, Hash>::hashedEntry::hashedEntry
|
||||
{}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * //
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
inline Foam::label
|
||||
Foam::HashTable<T, Key, Hash>::hashKeyIndex(const Key& key) const
|
||||
{
|
||||
// size is power of two - this is the modulus
|
||||
return Hash()(key) & (tableSize_ - 1);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
|
||||
@ -33,15 +33,16 @@ License
|
||||
template<class T, class Key, class Hash>
|
||||
Foam::HashTable<T, Key, Hash>::HashTable(Istream& is, const label size)
|
||||
:
|
||||
tableSize_(size),
|
||||
table_(new hashedEntry*[tableSize_]),
|
||||
HashTableName(),
|
||||
nElmts_(0),
|
||||
tableSize_(canonicalSize(size)),
|
||||
table_(new hashedEntry*[tableSize_]),
|
||||
endIter_(*this, NULL, 0),
|
||||
endConstIter_(*this, NULL, 0)
|
||||
{
|
||||
for (label i=0; i < tableSize_; i++)
|
||||
for (label hashIdx = 0; hashIdx < tableSize_; hashIdx++)
|
||||
{
|
||||
table_[i] = 0;
|
||||
table_[hashIdx] = 0;
|
||||
}
|
||||
|
||||
operator>>(is, *this);
|
||||
|
||||
@ -31,6 +31,33 @@ License
|
||||
#include "List.H"
|
||||
#include "IOstreams.H"
|
||||
|
||||
// * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * //
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
Foam::label Foam::StaticHashTable<T, Key, Hash>::canonicalSize(const label size)
|
||||
{
|
||||
if (size < 1)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// enforce power of two
|
||||
unsigned int goodSize = size;
|
||||
|
||||
if (goodSize & (goodSize - 1))
|
||||
{
|
||||
// brute-force is fast enough
|
||||
goodSize = 1;
|
||||
while (goodSize < unsigned(size))
|
||||
{
|
||||
goodSize <<= 1;
|
||||
}
|
||||
}
|
||||
|
||||
return goodSize;
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
// Construct given initial table size
|
||||
@ -38,8 +65,8 @@ template<class T, class Key, class Hash>
|
||||
Foam::StaticHashTable<T, Key, Hash>::StaticHashTable(const label size)
|
||||
:
|
||||
StaticHashTableName(),
|
||||
keys_(size),
|
||||
objects_(size),
|
||||
keys_(canonicalSize(size)),
|
||||
objects_(keys_.size()),
|
||||
nElmts_(0),
|
||||
endIter_(*this, keys_.size(), 0),
|
||||
endConstIter_(*this, keys_.size(), 0)
|
||||
@ -103,7 +130,7 @@ bool Foam::StaticHashTable<T, Key, Hash>::found(const Key& key) const
|
||||
{
|
||||
if (nElmts_)
|
||||
{
|
||||
label hashIdx = Hash()(key, keys_.size());
|
||||
const label hashIdx = hashKeyIndex(key);
|
||||
const List<Key>& localKeys = keys_[hashIdx];
|
||||
|
||||
forAll(localKeys, elemIdx)
|
||||
@ -136,7 +163,7 @@ Foam::StaticHashTable<T, Key, Hash>::find
|
||||
{
|
||||
if (nElmts_)
|
||||
{
|
||||
label hashIdx = Hash()(key, keys_.size());
|
||||
const label hashIdx = hashKeyIndex(key);
|
||||
const List<Key>& localKeys = keys_[hashIdx];
|
||||
|
||||
forAll(localKeys, elemIdx)
|
||||
@ -167,7 +194,9 @@ Foam::StaticHashTable<T, Key, Hash>::find
|
||||
const Key& key
|
||||
) const
|
||||
{
|
||||
label hashIdx = Hash()(key, keys_.size());
|
||||
if (nElmts_)
|
||||
{
|
||||
const label hashIdx = hashKeyIndex(key);
|
||||
const List<Key>& localKeys = keys_[hashIdx];
|
||||
|
||||
forAll(localKeys, elemIdx)
|
||||
@ -177,6 +206,7 @@ Foam::StaticHashTable<T, Key, Hash>::find
|
||||
return const_iterator(*this, hashIdx, elemIdx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# ifdef FULLDEBUG
|
||||
if (debug)
|
||||
@ -186,7 +216,7 @@ Foam::StaticHashTable<T, Key, Hash>::find
|
||||
}
|
||||
# endif
|
||||
|
||||
return end();
|
||||
return cend();
|
||||
}
|
||||
|
||||
|
||||
@ -197,7 +227,7 @@ Foam::List<Key> Foam::StaticHashTable<T, Key, Hash>::toc() const
|
||||
List<Key> tofc(nElmts_);
|
||||
label i = 0;
|
||||
|
||||
for (const_iterator iter = begin(); iter != end(); ++iter)
|
||||
for (const_iterator iter = cbegin(); iter != cend(); ++iter)
|
||||
{
|
||||
tofc[i++] = iter.key();
|
||||
}
|
||||
@ -214,7 +244,7 @@ bool Foam::StaticHashTable<T, Key, Hash>::set
|
||||
const bool protect
|
||||
)
|
||||
{
|
||||
label hashIdx = Hash()(key, keys_.size());
|
||||
const label hashIdx = hashKeyIndex(key);
|
||||
List<Key>& localKeys = keys_[hashIdx];
|
||||
|
||||
label existing = localKeys.size();
|
||||
@ -375,8 +405,10 @@ Foam::label Foam::StaticHashTable<T, Key, Hash>::erase
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
void Foam::StaticHashTable<T, Key, Hash>::resize(const label newSize)
|
||||
void Foam::StaticHashTable<T, Key, Hash>::resize(const label sz)
|
||||
{
|
||||
label newSize = canonicalSize(sz);
|
||||
|
||||
if (newSize == keys_.size())
|
||||
{
|
||||
# ifdef FULLDEBUG
|
||||
@ -394,7 +426,7 @@ void Foam::StaticHashTable<T, Key, Hash>::resize(const label newSize)
|
||||
{
|
||||
FatalErrorIn
|
||||
(
|
||||
"StaticHashTable<T, Key, Hash>::StaticHashTable(const label size)"
|
||||
"StaticHashTable<T, Key, Hash>::resize(const label)"
|
||||
) << "Illegal size " << newSize << " for StaticHashTable."
|
||||
<< " Minimum size is 1" << abort(FatalError);
|
||||
}
|
||||
@ -402,7 +434,7 @@ void Foam::StaticHashTable<T, Key, Hash>::resize(const label newSize)
|
||||
|
||||
StaticHashTable<T, Key, Hash> newTable(newSize);
|
||||
|
||||
for (iterator iter = begin(); iter != end(); ++iter)
|
||||
for (const_iterator iter = cbegin(); iter != cend(); ++iter)
|
||||
{
|
||||
newTable.insert(iter.key(), *iter);
|
||||
}
|
||||
@ -499,7 +531,7 @@ void Foam::StaticHashTable<T, Key, Hash>::operator=
|
||||
}
|
||||
|
||||
|
||||
for (const_iterator iter = rhs.begin(); iter != rhs.end(); ++iter)
|
||||
for (const_iterator iter = rhs.cbegin(); iter != rhs.cend(); ++iter)
|
||||
{
|
||||
insert(iter.key(), *iter);
|
||||
}
|
||||
@ -512,22 +544,22 @@ bool Foam::StaticHashTable<T, Key, Hash>::operator==
|
||||
) const
|
||||
{
|
||||
// Are all my elements in rhs?
|
||||
for (const_iterator iter = begin(); iter != end(); ++iter)
|
||||
for (const_iterator iter = cbegin(); iter != cend(); ++iter)
|
||||
{
|
||||
const_iterator fnd = rhs.find(iter.key());
|
||||
|
||||
if (fnd == rhs.end() || fnd() != iter())
|
||||
if (fnd == rhs.cend() || fnd() != iter())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Are all rhs elements in me?
|
||||
for (const_iterator iter = rhs.begin(); iter != rhs.end(); ++iter)
|
||||
for (const_iterator iter = rhs.cbegin(); iter != rhs.cend(); ++iter)
|
||||
{
|
||||
const_iterator fnd = find(iter.key());
|
||||
|
||||
if (fnd == end() || fnd() != iter())
|
||||
if (fnd == cend() || fnd() != iter())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -99,6 +99,13 @@ class StaticHashTable
|
||||
//- The current number of elements in table
|
||||
label nElmts_;
|
||||
|
||||
//- Return a canonical (power-of-two) size
|
||||
static label canonicalSize(const label);
|
||||
|
||||
//- Return the hash index of the Key within the current table size.
|
||||
// No checks for zero-sized tables.
|
||||
inline label hashKeyIndex(const Key&) const;
|
||||
|
||||
//- Assign a new hashed entry to a possibly already existing key
|
||||
bool set(const Key&, const T& newElmt, bool protect);
|
||||
|
||||
|
||||
@ -29,6 +29,17 @@ License
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Classes * * * * * * * * * * * * //
|
||||
|
||||
// * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * //
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
inline Foam::label
|
||||
Foam::StaticHashTable<T, Key, Hash>::hashKeyIndex(const Key& key) const
|
||||
{
|
||||
// size is power of two - this is the modulus
|
||||
return Hash()(key) & (keys_.size() - 1);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
|
||||
@ -80,17 +80,12 @@ public:
|
||||
// Rotating hash from http://burtleburtle.net/bob/hash/doobs.html
|
||||
template<class HashT=Hash<T> >
|
||||
class Hash
|
||||
:
|
||||
public Foam::Hash<FixedList<T, Size> >
|
||||
{
|
||||
public:
|
||||
inline Hash();
|
||||
Hash()
|
||||
{}
|
||||
|
||||
label operator()(const FixedList<T, Size>&) const;
|
||||
label operator()
|
||||
(
|
||||
const FixedList<T, Size>&,
|
||||
const label tableSize
|
||||
) const;
|
||||
};
|
||||
|
||||
// Static Member Functions
|
||||
|
||||
@ -403,11 +403,6 @@ inline bool Foam::FixedList<T, Size>::empty() const
|
||||
|
||||
|
||||
#ifndef __CINT__
|
||||
template<class T, Foam::label Size>
|
||||
template<class HashT>
|
||||
inline Foam::FixedList<T, Size>::Hash<HashT>::Hash()
|
||||
{}
|
||||
|
||||
|
||||
// Rotating Hash
|
||||
template<class T, Foam::label Size>
|
||||
@ -429,17 +424,6 @@ inline Foam::label Foam::FixedList<T, Size>::Hash<HashT>::operator()
|
||||
return val;
|
||||
}
|
||||
|
||||
template<class T, Foam::label Size>
|
||||
template<class HashT>
|
||||
inline Foam::label Foam::FixedList<T, Size>::Hash<HashT>::operator()
|
||||
(
|
||||
const FixedList<T, Size>& lst,
|
||||
const label tableSize
|
||||
) const
|
||||
{
|
||||
return ::abs(operator()(lst)) % tableSize;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __CINT__
|
||||
|
||||
// ************************************************************************* //
|
||||
|
||||
@ -38,7 +38,7 @@ SourceFiles
|
||||
|
||||
#include "HashTable.H"
|
||||
#include "label.H"
|
||||
#include "pTraits.H"
|
||||
#include "Hash.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
@ -49,28 +49,6 @@ namespace Foam
|
||||
Class dlLibraryTable Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
//- A means of hashing pointer addresses
|
||||
template<>
|
||||
class Hash<void*>
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
Hash()
|
||||
{}
|
||||
|
||||
long operator()(const void* const& p) const
|
||||
{
|
||||
return long(p);
|
||||
}
|
||||
|
||||
label operator()(const void* const& p, const label tableSize) const
|
||||
{
|
||||
return abs(operator()(p)) % tableSize;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class dlLibraryTable
|
||||
:
|
||||
public HashTable<fileName, void*, Hash<void*> >
|
||||
|
||||
@ -133,12 +133,12 @@ public:
|
||||
};
|
||||
|
||||
|
||||
//- Hash<edge> specialisation
|
||||
//- Hash specialization for hashing edges
|
||||
// Simple commutative hash.
|
||||
template<>
|
||||
inline label Hash<edge>::operator()(const edge& e) const
|
||||
{
|
||||
return e[0]*e[1] + e[0]+e[1];
|
||||
return (e[0]*e[1] + e[0]+e[1]);
|
||||
}
|
||||
|
||||
template<>
|
||||
|
||||
@ -164,7 +164,7 @@ public:
|
||||
};
|
||||
|
||||
|
||||
//- Hash<triFace> specialisation
|
||||
//- Hash specialization for hashing triFace
|
||||
// Simple commutative hash.
|
||||
template<>
|
||||
inline label Hash<triFace>::operator()(const triFace& t) const
|
||||
|
||||
@ -27,7 +27,7 @@ Class
|
||||
|
||||
Description
|
||||
Hash function class for primitives. All non-primitives used to hash
|
||||
entries on hash tables need a specialised version of this class.
|
||||
entries on hash tables need a specialized version of this class.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
@ -35,6 +35,7 @@ Description
|
||||
#define Hash_H
|
||||
|
||||
#include "label.H"
|
||||
#include "pTraits.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
@ -59,10 +60,26 @@ public:
|
||||
return label(p);
|
||||
}
|
||||
|
||||
label operator()(const PrimitiveType& p, const label tableSize) const
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
//- Hash specialization for hashing pointer addresses
|
||||
template<>
|
||||
class Hash<void*>
|
||||
{
|
||||
return mag(operator()(p)) % tableSize;
|
||||
|
||||
public:
|
||||
|
||||
Hash()
|
||||
{}
|
||||
|
||||
long operator()(const void* const& p) const
|
||||
{
|
||||
return long(p);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -89,9 +89,10 @@ public:
|
||||
class hash
|
||||
{
|
||||
public:
|
||||
inline hash();
|
||||
hash()
|
||||
{}
|
||||
|
||||
inline size_type operator()(const string&) const;
|
||||
inline size_type operator()(const string&, const size_type) const;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -196,10 +196,6 @@ inline Foam::string Foam::string::operator()(const size_type n) const
|
||||
}
|
||||
|
||||
|
||||
inline Foam::string::hash::hash()
|
||||
{}
|
||||
|
||||
|
||||
inline Foam::string::size_type Foam::string::hash::operator()
|
||||
(
|
||||
const string& key
|
||||
@ -216,14 +212,4 @@ inline Foam::string::size_type Foam::string::hash::operator()
|
||||
}
|
||||
|
||||
|
||||
inline Foam::string::size_type Foam::string::hash::operator()
|
||||
(
|
||||
const string& key,
|
||||
const size_type tableSize
|
||||
) const
|
||||
{
|
||||
return ::abs(operator()(key)) % tableSize;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
|
||||
Reference in New Issue
Block a user