DEFEATURE: remove StaticHashTable

- unused, unmaintained and slower than the regular HashTable
This commit is contained in:
Mark Olesen 2017-10-30 21:35:05 +01:00
parent 930d6dcaf2
commit db552fb751
12 changed files with 0 additions and 1895 deletions

View File

@ -30,7 +30,6 @@ Description
#include "HashTable.H"
#include "HashPtrTable.H"
#include "Map.H"
#include "StaticHashTable.H"
#include "cpuTime.H"
using namespace Foam;
@ -57,7 +56,6 @@ int main(int argc, char *argv[])
// ie, a
// Map<label> map(2 * nSize);
// HashTable<label, label, Hash<label>> map(2 * nSize);
// StaticHashTable<label, label, Hash<label>> map(2 * nSize);
HashTable<label, label, Hash<label>> map(2 * nSize);
Info<< "Constructed map of size: " << nSize;

View File

@ -31,14 +31,12 @@ Description
#include "boolList.H"
#include "PackedBoolList.H"
#include "HashSet.H"
#include "StaticHashTable.H"
#include "cpuTime.H"
#include <vector>
#include <unordered_set>
using namespace Foam;
#undef TEST_STATIC_HASH
#undef TEST_STD_BOOLLIST
#undef TEST_STD_UNORDERED_SET
@ -84,20 +82,6 @@ int main(int argc, char *argv[])
Info<< "populated labelHashSet in "
<< timer.cpuTimeIncrement() << " s\n\n";
#ifdef TEST_STATIC_HASH
// fullStaticHash is really slow
// give it lots of slots to help
StaticHashTable<nil, label, Hash<label>> emptyStaticHash;
StaticHashTable<nil, label, Hash<label>> fullStaticHash(100000);
for (label i = 0; i < n; i++)
{
fullStaticHash.insert(i, nil());
}
Info<< "populated StaticHashTable in "
<< timer.cpuTimeIncrement() << " s\n\n";
#endif
#ifdef TEST_STD_UNORDERED_SET
std::unordered_set<label, Foam::Hash<label>> emptyStdHash;
std::unordered_set<label, Foam::Hash<label>> fullStdHash;
@ -112,10 +96,6 @@ int main(int argc, char *argv[])
emptyHash.printInfo(Info);
fullHash.printInfo(Info);
#ifdef TEST_STATIC_HASH
emptyStaticHash.printInfo(Info);
fullStaticHash.printInfo(Info);
#endif
#ifdef TEST_STD_UNORDERED_SET
printInfo(emptyStdHash);
printInfo(fullStdHash);
@ -305,37 +285,6 @@ int main(int argc, char *argv[])
<< " sum " << sum << nl;
#ifdef TEST_STATIC_HASH
// Read empty StaticHashTable
sum = 0;
for (label iter = 0; iter < nIters; ++iter)
{
forAll(unpacked, i)
{
sum += emptyStaticHash.found(i);
}
}
std::cout
<< "Reading empty StaticHash:" << timer.cpuTimeIncrement()
<< " s" << nl
<< " sum " << sum << nl;
// Read full StaticHashTable
sum = 0;
for (label iter = 0; iter < nIters; ++iter)
{
forAll(unpacked, i)
{
sum += fullStaticHash.found(i);
}
}
std::cout
<< "Reading full StaticHash:" << timer.cpuTimeIncrement()
<< " s" << nl
<< " sum " << sum << nl;
#endif
#ifdef TEST_STD_UNORDERED_SET
// Read empty stl set
sum = 0;

View File

@ -1,3 +0,0 @@
Test-staticHashTable.C
EXE = $(FOAM_USER_APPBIN)/Test-staticHashTable

View File

@ -1,170 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM 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 General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "StaticHashTable.H"
#include "IOstreams.H"
#include "StringStream.H"
using namespace Foam;
// use define so we can easily test other implementations
#define HASHTABLE_CLASS StaticHashTable
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Main program:
int main()
{
HASHTABLE_CLASS<double> table1(13);
table1.insert("aaa", 1.0);
table1.insert("aba", 2.0);
table1.insert("aca", 3.0);
table1.insert("ada", 4.0);
table1.insert("aeq", 5.0);
table1.insert("aaw", 6.0);
table1.insert("abs", 7.0);
table1.insert("acr", 8.0);
table1.insert("adx", 9.0);
table1.insert("aec", 10.0);
table1.erase("aaw");
table1.erase("abs");
Info<< "\ntable1 toc: " << table1.toc() << endl;
table1.printInfo(Info)
<< "table1 [" << table1.size() << "] " << endl;
forAllIter(HASHTABLE_CLASS<double>, table1, iter)
{
Info<< iter.key() << " => " << iter() << nl;
}
table1.set("acr", 108);
table1.set("adx", 109);
table1.set("aec", 100);
table1("aaw") -= 1000;
table1("aeq") += 1000;
Info<< "\noverwrote some values table1: " << table1 << endl;
Info<< "\ntest find:" << endl;
Info<< table1.find("aaa")() << nl
<< table1.find("aba")() << nl
<< table1.find("aca")() << nl
<< table1.find("ada")() << nl
<< table1.find("aeq")() << nl
<< table1.find("acr")() << nl
<< table1.find("adx")() << nl
<< table1.find("aec")() << nl
<< table1["aaa"] << nl;
{
OStringStream os;
os << table1;
HASHTABLE_CLASS<double> readTable(IStringStream(os.str())(), 100);
Info<< "Istream constructor:" << readTable << endl;
}
HASHTABLE_CLASS<double> table2(table1);
HASHTABLE_CLASS<double> table3(table1.xfer());
Info<< "\ncopy table1 -> table2" << nl
<< "transfer table1 -> table3 via the xfer() method" << nl;
Info<< "\ntable1" << table1 << nl
<< "\ntable2" << table2 << nl
<< "\ntable3" << table3 << nl;
Info<< "\nerase table2 by iterator" << nl;
forAllIter(HASHTABLE_CLASS<double>, table2, iter)
{
Info<< "erasing " << iter.key() << " => " << iter() << " ... ";
table2.erase(iter);
Info<< "erased" << endl;
}
Info<< "\ntable1" << table1 << nl
<< "\ntable2" << table2 << nl
<< "\ntable3" << table3 << nl;
table3.resize(1);
Info<< "\nresize(1) table3" << nl;
table3.printInfo(Info)
<< table3 << nl;
table3.resize(10000);
Info<< "\nresize(10000) table3" << nl;
table3.printInfo(Info)
<< table3 << nl;
HASHTABLE_CLASS<double> table4;
table4 = table3;
Info<< "\ncopy table3 -> table4 " << table4 << nl;
Info<< "\nclear table4 ... ";
table4.clear();
Info<< "[" << table4.size() << "] " << table4 << nl;
table1 = table3;
Info<< "\ncopy table3 -> table1 (previously transferred)" << table1 << nl;
Info<< "test table1 == table3 : " << (table1 == table3) << nl;
table1.erase(table1.begin());
Info<< "removed an element - test table1 != table3 : "
<< (table1 != table3) << nl;
// insert a few things into table2
table2.set("ada", 14.0);
table2.set("aeq", 15.0);
table2.set("aaw", 16.0);
table2.set("abs", 17.0);
table2.set("adx", 20.0);
Info<< "\ntable1" << table1 << nl
<< "\ntable2" << table2 << nl;
label nErased = table1.erase(table2);
Info<< "\nerase table2 keys from table1 (removed "
<< nErased << " elements)" << nl
<< "\ntable1" << table1 << nl
<< "\ntable2" << table2 << nl;
Info<< "\ntable3" << table3
<< "\nclearStorage table3 ... ";
table3.clearStorage();
Info<< table3 << nl;
Info<< "\nDone\n";
return 0;
}
// ************************************************************************* //

View File

@ -337,7 +337,6 @@ DebugSwitches
SpalartAllmarasIDDES 0;
SphereDrag 0;
StandardWallInteraction 0;
StaticHashTable 0;
StochasticDispersionRAS 0;
SuperBee 0;
SuperBeeV 0;

View File

@ -147,7 +147,6 @@ primitives/Barycentric/barycentric/barycentric.C
primitives/Barycentric2D/barycentric2D/barycentric2D.C
containers/HashTables/HashTable/HashTableCore.C
containers/HashTables/StaticHashTable/StaticHashTableCore.C
containers/Lists/SortableList/ParSortableListName.C
containers/Lists/PackedList/PackedListCore.C
containers/Lists/PackedList/PackedBoolList.C

View File

@ -1,530 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM 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 General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#ifndef StaticHashTable_C
#define StaticHashTable_C
#include "StaticHashTable.H"
#include "List.H"
#include "IOstreams.H"
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
template<class T, class Key, class Hash>
Foam::StaticHashTable<T, Key, Hash>::StaticHashTable(const label size)
:
StaticHashTableCore(),
keys_(StaticHashTableCore::canonicalSize(size)),
objects_(keys_.size()),
nElmts_(0),
endIter_(*this, keys_.size(), 0),
endConstIter_(*this, keys_.size(), 0)
{
if (size < 1)
{
FatalErrorInFunction
<< "Illegal size " << size << " for StaticHashTable."
<< " Minimum size is 1" << abort(FatalError);
}
}
template<class T, class Key, class Hash>
Foam::StaticHashTable<T, Key, Hash>::StaticHashTable
(
const StaticHashTable<T, Key, Hash>& ht
)
:
StaticHashTableCore(),
keys_(ht.keys_),
objects_(ht.objects_),
nElmts_(ht.nElmts_),
endIter_(*this, keys_.size(), 0),
endConstIter_(*this, keys_.size(), 0)
{}
template<class T, class Key, class Hash>
Foam::StaticHashTable<T, Key, Hash>::StaticHashTable
(
const Xfer<StaticHashTable<T, Key, Hash>>& ht
)
:
StaticHashTableCore(),
keys_(0),
objects_(0),
nElmts_(0),
endIter_(*this, 0, 0),
endConstIter_(*this, 0, 0)
{
transfer(ht());
}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
template<class T, class Key, class Hash>
Foam::StaticHashTable<T, Key, Hash>::~StaticHashTable()
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class T, class Key, class Hash>
bool Foam::StaticHashTable<T, Key, Hash>::found(const Key& key) const
{
if (nElmts_)
{
const label hashIdx = hashKeyIndex(key);
const List<Key>& localKeys = keys_[hashIdx];
forAll(localKeys, elemIdx)
{
if (key == localKeys[elemIdx])
{
return true;
}
}
}
#ifdef FULLDEBUG
if (debug)
{
InfoInFunction << "Entry " << key << " not found in hash table\n";
}
#endif
return false;
}
template<class T, class Key, class Hash>
typename Foam::StaticHashTable<T, Key, Hash>::iterator
Foam::StaticHashTable<T, Key, Hash>::find
(
const Key& key
)
{
if (nElmts_)
{
const label hashIdx = hashKeyIndex(key);
const List<Key>& localKeys = keys_[hashIdx];
forAll(localKeys, elemIdx)
{
if (key == localKeys[elemIdx])
{
return iterator(*this, hashIdx, elemIdx);
}
}
}
#ifdef FULLDEBUG
if (debug)
{
InfoInFunction << "Entry " << key << " not found in hash table\n";
}
#endif
return end();
}
template<class T, class Key, class Hash>
typename Foam::StaticHashTable<T, Key, Hash>::const_iterator
Foam::StaticHashTable<T, Key, Hash>::find
(
const Key& key
) const
{
return this->cfind(key);
}
template<class T, class Key, class Hash>
typename Foam::StaticHashTable<T, Key, Hash>::const_iterator
Foam::StaticHashTable<T, Key, Hash>::cfind
(
const Key& key
) const
{
if (nElmts_)
{
const label hashIdx = hashKeyIndex(key);
const List<Key>& localKeys = keys_[hashIdx];
forAll(localKeys, elemIdx)
{
if (key == localKeys[elemIdx])
{
return const_iterator(*this, hashIdx, elemIdx);
}
}
}
#ifdef FULLDEBUG
if (debug)
{
InfoInFunction << "Entry " << key << " not found in hash table\n";
}
#endif
return cend();
}
template<class T, class Key, class Hash>
Foam::List<Key> Foam::StaticHashTable<T, Key, Hash>::toc() const
{
List<Key> keys(nElmts_);
label keyI = 0;
for (const_iterator iter = cbegin(); iter != cend(); ++iter)
{
keys[keyI++] = iter.key();
}
return keys;
}
template<class T, class Key, class Hash>
bool Foam::StaticHashTable<T, Key, Hash>::set
(
const Key& key,
const T& obj,
const bool protect
)
{
const label hashIdx = hashKeyIndex(key);
List<Key>& localKeys = keys_[hashIdx];
label existing = localKeys.size();
forAll(localKeys, elemIdx)
{
if (key == localKeys[elemIdx])
{
existing = elemIdx;
break;
}
}
if (existing == localKeys.size())
{
// Not found, append
List<T>& localObjects = objects_[hashIdx];
localKeys.setSize(existing+1);
localObjects.setSize(existing+1);
localKeys[existing] = key;
localObjects[existing] = obj;
nElmts_++;
}
else if (protect)
{
// Found - but protected from overwriting
// this corresponds to the STL 'insert' convention
#ifdef FULLDEBUG
if (debug)
{
InfoInFunction
<< "Cannot insert " << key << " already in hash table\n";
}
#endif
return false;
}
else
{
// Found - overwrite existing entry
// this corresponds to the Perl convention
objects_[hashIdx][existing] = obj;
}
return true;
}
template<class T, class Key, class Hash>
bool Foam::StaticHashTable<T, Key, Hash>::erase(const iterator& cit)
{
if (cit != end())
{
List<Key>& localKeys = keys_[cit.hashIndex_];
List<T>& localObjects = objects_[cit.hashIndex_];
// Copy down
for (label i = cit.elemIndex_+1; i < localKeys.size(); i++)
{
localKeys[i-1] = localKeys[i];
localObjects[i-1] = localObjects[i];
}
localKeys.setSize(localKeys.size()-1);
localObjects.setSize(localObjects.size()-1);
// Adjust iterator after erase
iterator& it = const_cast<iterator&>(cit);
it.elemIndex_--;
if (it.elemIndex_ < 0)
{
// No previous element in the local list
// Mark with as special value (see notes in HashTable)
it.hashIndex_ = -it.hashIndex_ - 1;
it.elemIndex_ = 0;
}
nElmts_--;
#ifdef FULLDEBUG
if (debug)
{
InfoInFunction << "hashedEntry removed.\n";
}
#endif
return true;
}
else
{
#ifdef FULLDEBUG
if (debug)
{
InfoInFunction
<< "Cannot remove hashedEntry from hash table\n";
}
#endif
return false;
}
}
template<class T, class Key, class Hash>
bool Foam::StaticHashTable<T, Key, Hash>::erase(const Key& key)
{
iterator it = find(key);
if (it != end())
{
return erase(it);
}
else
{
return false;
}
}
template<class T, class Key, class Hash>
Foam::label Foam::StaticHashTable<T, Key, Hash>::erase
(
const StaticHashTable<T, Key, Hash>& rhs
)
{
label count = 0;
// Remove rhs elements from this table
// NOTE: could optimize depending on which hash is smaller
for (iterator iter = this->begin(); iter != this->end(); ++iter)
{
if (rhs.found(iter.key()) && erase(iter))
{
count++;
}
}
return count;
}
template<class T, class Key, class Hash>
void Foam::StaticHashTable<T, Key, Hash>::resize(const label sz)
{
label newSize = StaticHashTableCore::canonicalSize(sz);
if (newSize == keys_.size())
{
#ifdef FULLDEBUG
if (debug)
{
InfoInFunction << "New table size == old table size\n";
}
#endif
return;
}
if (newSize < 1)
{
FatalErrorInFunction
<< "Illegal size " << newSize << " for StaticHashTable."
<< " Minimum size is 1" << abort(FatalError);
}
StaticHashTable<T, Key, Hash> newTable(newSize);
for (const_iterator iter = cbegin(); iter != cend(); ++iter)
{
newTable.insert(iter.key(), *iter);
}
transfer(newTable);
// Adapt end() iterators
endIter_.hashIndex_ = keys_.size();
endConstIter_.hashIndex_ = keys_.size();
}
template<class T, class Key, class Hash>
void Foam::StaticHashTable<T, Key, Hash>::clear()
{
forAll(keys_, hashIdx)
{
keys_[hashIdx].clear();
objects_[hashIdx].clear();
}
nElmts_ = 0;
}
template<class T, class Key, class Hash>
void Foam::StaticHashTable<T, Key, Hash>::clearStorage()
{
clear();
resize(1);
}
template<class T, class Key, class Hash>
void Foam::StaticHashTable<T, Key, Hash>::transfer
(
StaticHashTable<T, Key, Hash>& ht
)
{
// Remove existing elements
clear();
// Copy data from ht
keys_.transfer(ht.keys_);
objects_.transfer(ht.objects_);
nElmts_ = ht.nElmts_;
ht.nElmts_ = 0;
// Adapt end() iterators
endIter_.hashIndex_ = keys_.size();
endConstIter_.hashIndex_ = keys_.size();
ht.endIter_.hashIndex_ = 0;
ht.endConstIter_.hashIndex_ = 0;
}
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
template<class T, class Key, class Hash>
void Foam::StaticHashTable<T, Key, Hash>::operator=
(
const StaticHashTable<T, Key, Hash>& rhs
)
{
// Check for assignment to self
if (this == &rhs)
{
FatalErrorInFunction
<< "attempted assignment to self"
<< abort(FatalError);
}
// keys could be empty from a previous transfer()
if (keys_.empty())
{
keys_.setSize(rhs.keys_.size());
objects_.setSize(keys_.size());
// Adapt end() iterators
endIter_.hashIndex_ = keys_.size();
endConstIter_.hashIndex_ = keys_.size();
}
else
{
clear();
// keys_.size() does not change so neither does end() iterator.
}
for (const_iterator iter = rhs.cbegin(); iter != rhs.cend(); ++iter)
{
insert(iter.key(), *iter);
}
}
template<class T, class Key, class Hash>
bool Foam::StaticHashTable<T, Key, Hash>::operator==
(
const StaticHashTable<T, Key, Hash>& rhs
) const
{
// Sizes (number of keys) must match
for (const_iterator iter = rhs.cbegin(); iter != rhs.cend(); ++iter)
{
const_iterator fnd = find(iter.key());
if (fnd == cend() || fnd() != iter())
{
return false;
}
}
return true;
}
template<class T, class Key, class Hash>
bool Foam::StaticHashTable<T, Key, Hash>::operator!=
(
const StaticHashTable<T, Key, Hash>& rhs
) const
{
return !(operator==(rhs));
}
// * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * //
#include "StaticHashTableIO.C"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -1,415 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM 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 General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Class
Foam::StaticHashTable
Description
STL conforming hash table.
Note
Uses straight lists as underlying type.
Is slower to insert than the standard HashTable, but should be more
memory efficient and faster to access.
SourceFiles
StaticHashTableI.H
StaticHashTable.C
StaticHashTableIO.C
\*---------------------------------------------------------------------------*/
#ifndef StaticHashTable_H
#define StaticHashTable_H
#include "label.H"
#include "uLabel.H"
#include "word.H"
#include "Xfer.H"
#include "className.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// Forward declaration of friend functions and operators
template<class T> class List;
template<class T, class Key, class Hash> class StaticHashTable;
template<class T, class Key, class Hash> Istream& operator>>
(
Istream&,
StaticHashTable<T, Key, Hash>&
);
template<class T, class Key, class Hash> Ostream& operator<<
(
Ostream&,
const StaticHashTable<T, Key, Hash>&
);
/*---------------------------------------------------------------------------*\
Class StaticHashTableCore Declaration
\*---------------------------------------------------------------------------*/
//- Template-invariant bits for StaticHashTable
struct StaticHashTableCore
{
//- Return a canonical (power-of-two) of the requested size.
static label canonicalSize(const label requested_size);
//- Construct null
StaticHashTableCore()
{}
//- Define template name and debug
ClassName("StaticHashTable");
//- A zero-sized end iterator
struct iteratorEnd
{
//- Construct null
iteratorEnd()
{}
};
};
/*---------------------------------------------------------------------------*\
Class StaticHashTable Declaration
\*---------------------------------------------------------------------------*/
template<class T, class Key=word, class Hash=string::hash>
class StaticHashTable
:
public StaticHashTableCore
{
// Private data type for table entries
//- The lookup keys, ordered per hash value
List<List<Key>> keys_;
//- For each key the corresponding object.
List<List<T>> objects_;
//- The current number of elements in table
label nElmts_;
//- Return the hash index of the Key within the current table size.
// No checks for zero-sized tables.
inline label hashKeyIndex(const Key& key) const;
//- Assign a new hashed entry to a possibly already existing key
bool set(const Key& key, const T& obj, bool protect);
public:
// Forward declaration of STL iterators
template<class TRef, class TableRef>
class Iterator;
typedef Iterator
<
T&,
StaticHashTable<T, Key, Hash>&
> iterator;
typedef Iterator
<
const T&,
const StaticHashTable<T, Key, Hash>&
> const_iterator;
// Declare friendship with the iterators
friend class Iterator
<
T&,
StaticHashTable<T, Key, Hash>&
>;
friend class Iterator
<
const T&,
const StaticHashTable<T, Key, Hash>&
>;
// Constructors
//- Construct given initial table size
StaticHashTable(const label size = 128);
//- Construct from Istream
StaticHashTable(Istream&, const label size = 128);
//- Construct as copy
StaticHashTable(const StaticHashTable<T, Key, Hash>&);
//- Construct by transferring the parameter contents
StaticHashTable(const Xfer<StaticHashTable<T, Key, Hash>>&);
//- Destructor
~StaticHashTable();
// Member Functions
// Access
//- Return number of elements in table.
inline label size() const;
//- Return true if the hash table is empty
inline bool empty() const;
//- Return true if hashed entry is found in table
bool found(const Key& key) const;
//- Find and return an iterator set at the hashed entry
// If not found iterator = end()
iterator find(const Key& key);
//- Find and return an const_iterator set at the hashed entry
// If not found iterator = end()
const_iterator find(const Key& key) const;
//- Find and return an const_iterator set at the hashed entry
// If not found iterator = end()
const_iterator cfind(const Key& key) const;
//- Return the table of contents
List<Key> toc() const;
//- Print information
Ostream& printInfo(Ostream&) const;
// Edit
//- Insert a new hashed entry
bool insert(const Key& key, const T& newElmt);
//- Assign a new hashed entry, overwriting existing entries
inline bool set(const Key&, const T& newElmt);
//- Erase an hashed entry specified by given iterator
bool erase(const iterator& it);
//- Erase an hashed entry specified by given key if in table
bool erase(const Key& key);
//- Resize the hash table for efficiency
void resize(const label newSize);
//- Remove entries in the given hash table from this hash table
// Return the number of elements removed
label erase(const StaticHashTable<T, Key, Hash>&);
//- Clear all entries from table
void clear();
//- Clear the table entries and the table itself.
// Equivalent to clear() followed by resize(1)
void clearStorage();
//- Transfer the contents of the argument table into this table
// and annul the argument table.
void transfer(StaticHashTable<T, Key, Hash>&);
//- Transfer contents to the Xfer container
inline Xfer<StaticHashTable<T, Key, Hash>> xfer();
// Member Operators
//- Find and return an hashed entry
inline T& operator[](const Key&);
//- Find and return an hashed entry
inline const T& operator[](const Key&) const;
//- Find and return an hashed entry, create it null if not present.
inline T& operator()(const Key&);
//- Assignment
void operator=(const StaticHashTable<T, Key, Hash>&);
//- Equality. Two hash tables are equal if all contents of first are
// also in second and vice versa.
bool operator==(const StaticHashTable<T, Key, Hash>&) const;
//- The opposite of the equality operation.
bool operator!=(const StaticHashTable<T, Key, Hash>&) const;
// STL type definitions
//- Type of values the StaticHashTable contains.
typedef T value_type;
//- Type that can be used for storing into StaticHashTable::value_type
// objects. This type is usually List::value_type&.
typedef T& reference;
//- Type that can be used for storing into constant
// StaticHashTable::value_type objects. This type is usually const
// StaticHashTable::value_type&.
typedef const T& const_reference;
//- The type that can represent the size of a StaticHashTable.
typedef label size_type;
// STL iterator
//- An STL iterator
template<class TRef, class TableRef>
class Iterator
{
friend class StaticHashTable;
template<class TRef2, class TableRef2>
friend class Iterator;
// Private data
//- Reference to the StaticHashTable this is an iterator for
TableRef hashTable_;
//- Current hash index
label hashIndex_;
//- Index of current element at hashIndex
label elemIndex_;
public:
// Constructors
//- Construct from hash table, hash index and element index
inline Iterator
(
TableRef,
label hashIndex_,
label elemIndex_
);
//- Construct from the non-const iterator
inline Iterator(const iterator&);
// Member operators
inline void operator=(const iterator&);
inline bool operator==(const iterator&) const;
inline bool operator==(const const_iterator&) const;
inline bool operator!=(const iterator&) const;
inline bool operator!=(const const_iterator&) const;
inline TRef operator*();
inline TRef operator()();
inline Iterator& operator++();
inline Iterator operator++(int);
inline const Key& key() const;
};
//- Iterator set to the beginning of the StaticHashTable
inline iterator begin();
//- Iterator set to beyond the end of the StaticHashTable
inline const iterator& end();
//- const_iterator set to the beginning of the StaticHashTable
inline const_iterator cbegin() const;
//- const_iterator set to beyond the end of the StaticHashTable
inline const const_iterator& cend() const;
//- const_iterator set to the beginning of the StaticHashTable
inline const_iterator begin() const;
//- const_iterator set to beyond the end of the StaticHashTable
inline const const_iterator& end() const;
// IOstream Operator
friend Istream& operator>> <T, Key, Hash>
(
Istream&,
StaticHashTable<T, Key, Hash>&
);
friend Ostream& operator<< <T, Key, Hash>
(
Ostream&,
const StaticHashTable<T, Key, Hash>&
);
private:
//- Iterator returned by end()
iterator endIter_;
//- const_iterator returned by end()
const_iterator endConstIter_;
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#include "StaticHashTableI.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifndef NoStaticHashTableC
#ifdef NoRepository
#include "StaticHashTable.C"
#endif
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -1,86 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2012 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM 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 General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "StaticHashTable.H"
#include "uLabel.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
defineTypeNameAndDebug(StaticHashTableCore, 0);
}
// Approximately labelMax/4
static const Foam::label maxTableSize(1L << (sizeof(Foam::label)*8-3));
// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
Foam::label Foam::StaticHashTableCore::canonicalSize(const label requested_size)
{
if (requested_size < 1)
{
return 0;
}
else if (requested_size >= maxTableSize)
{
return maxTableSize;
}
// Enforce power of two - makes for a very fast modulus.
// Use unsigned for these calculations.
//
// - The lower limit (8) is somewhat arbitrary, but if the hash table
// is too small, there will be many direct table collisions.
// - The upper limit (approx. labelMax/4) must be a power of two,
// need not be extremely large for hashing.
uLabel powerOfTwo = 8u; // lower-limit
const uLabel size = requested_size;
if (size <= powerOfTwo)
{
return powerOfTwo;
}
else if (size & (size-1)) // <- Modulus of i^2
{
// Determine power-of-two. Brute-force is fast enough.
while (powerOfTwo < size)
{
powerOfTwo <<= 1;
}
return powerOfTwo;
}
else
{
return size;
}
}
// ************************************************************************* //

View File

@ -1,399 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM 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 General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "error.H"
#include "IOstreams.H"
// * * * * * * * * * * * * 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>
inline Foam::label Foam::StaticHashTable<T, Key, Hash>::size() const
{
return nElmts_;
}
template<class T, class Key, class Hash>
inline bool Foam::StaticHashTable<T, Key, Hash>::empty() const
{
return !nElmts_;
}
template<class T, class Key, class Hash>
inline bool Foam::StaticHashTable<T, Key, Hash>::insert
(
const Key& key,
const T& obj
)
{
return set(key, obj, true);
}
template<class T, class Key, class Hash>
inline bool Foam::StaticHashTable<T, Key, Hash>::set
(
const Key& key,
const T& obj
)
{
return set(key, obj, false);
}
template<class T, class Key, class Hash>
inline Foam::Xfer<Foam::StaticHashTable<T, Key, Hash>>
Foam::StaticHashTable<T, Key, Hash>::xfer()
{
return xferMove(*this);
}
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
template<class T, class Key, class Hash>
inline T& Foam::StaticHashTable<T, Key, Hash>::operator[](const Key& key)
{
iterator iter = find(key);
if (iter == end())
{
FatalErrorInFunction
<< toc()
<< exit(FatalError);
}
return *iter;
}
template<class T, class Key, class Hash>
inline const T& Foam::StaticHashTable<T, Key, Hash>::operator[]
(
const Key& key
) const
{
const_iterator iter = find(key);
if (iter == cend())
{
FatalErrorInFunction
<< toc()
<< exit(FatalError);
}
return *iter;
}
template<class T, class Key, class Hash>
inline T& Foam::StaticHashTable<T, Key, Hash>::operator()(const Key& key)
{
iterator iter = find(key);
if (iter == end())
{
insert(key, T());
return *find(key);
}
else
{
return *iter;
}
}
// * * * * * * * * * * * * * * * * STL iterator * * * * * * * * * * * * * * //
template<class T, class Key, class Hash>
template<class TRef, class TableRef>
inline Foam::StaticHashTable<T, Key, Hash>::Iterator<TRef, TableRef>::Iterator
(
TableRef hashTbl,
label hashIndex,
label elemIndex
)
:
hashTable_(hashTbl),
hashIndex_(hashIndex),
elemIndex_(elemIndex)
{}
template<class T, class Key, class Hash>
template<class TRef, class TableRef>
inline Foam::StaticHashTable<T, Key, Hash>::Iterator<TRef, TableRef>::Iterator
(
const iterator& iter
)
:
hashTable_(iter.hashTable_),
hashIndex_(iter.hashIndex_),
elemIndex_(iter.elemIndex_)
{}
template<class T, class Key, class Hash>
template<class TRef, class TableRef>
inline void
Foam::StaticHashTable<T, Key, Hash>::Iterator<TRef, TableRef>::operator=
(
const iterator& iter
)
{
this->hashIndex_ = iter.hashIndex_;
this->elemIndex_ = iter.elemIndex_;
}
template<class T, class Key, class Hash>
template<class TRef, class TableRef>
inline bool
Foam::StaticHashTable<T, Key, Hash>::Iterator<TRef, TableRef>::operator==
(
const iterator& iter
) const
{
return hashIndex_ == iter.hashIndex_ && elemIndex_ == iter.elemIndex_;
}
template<class T, class Key, class Hash>
template<class TRef, class TableRef>
inline bool
Foam::StaticHashTable<T, Key, Hash>::Iterator<TRef, TableRef>::operator==
(
const const_iterator& iter
) const
{
return hashIndex_ == iter.hashIndex_ && elemIndex_ == iter.elemIndex_;
}
template<class T, class Key, class Hash>
template<class TRef, class TableRef>
inline bool
Foam::StaticHashTable<T, Key, Hash>::Iterator<TRef, TableRef>::operator!=
(
const iterator& iter
) const
{
return !operator==(iter);
}
template<class T, class Key, class Hash>
template<class TRef, class TableRef>
inline bool
Foam::StaticHashTable<T, Key, Hash>::Iterator<TRef, TableRef>::operator!=
(
const const_iterator& iter
) const
{
return !operator==(iter);
}
template<class T, class Key, class Hash>
template<class TRef, class TableRef>
inline TRef
Foam::StaticHashTable<T, Key, Hash>::Iterator<TRef, TableRef>::operator*()
{
return hashTable_.objects_[hashIndex_][elemIndex_];
}
template<class T, class Key, class Hash>
template<class TRef, class TableRef>
inline TRef
Foam::StaticHashTable<T, Key, Hash>::Iterator<TRef, TableRef>::operator()()
{
return operator*();
}
template<class T, class Key, class Hash>
template<class TRef, class TableRef>
inline
typename Foam::StaticHashTable<T, Key, Hash>::template Iterator
<
TRef,
TableRef
>&
Foam::StaticHashTable<T, Key, Hash>::Iterator
<
TRef,
TableRef
>::operator++()
{
// A negative index is a special value from erase
// (see notes in HashTable)
if (hashIndex_ < 0)
{
hashIndex_ = -(hashIndex_+1) - 1;
}
else
{
// Try the next element on the local list
elemIndex_++;
if (elemIndex_ < hashTable_.objects_[hashIndex_].size())
{
return *this;
}
}
// Step to the next table entry
elemIndex_ = 0;
while
(
++hashIndex_ < hashTable_.objects_.size()
&& !hashTable_.objects_[hashIndex_].size()
)
{}
if (hashIndex_ >= hashTable_.objects_.size())
{
// make end iterator
hashIndex_ = hashTable_.keys_.size();
}
return *this;
}
template<class T, class Key, class Hash>
template<class TRef, class TableRef>
inline
typename Foam::StaticHashTable<T, Key, Hash>::template Iterator
<
TRef,
TableRef
>
Foam::StaticHashTable<T, Key, Hash>::Iterator
<
TRef,
TableRef
>::operator++
(
int
)
{
iterator tmp = *this;
++*this;
return tmp;
}
template<class T, class Key, class Hash>
template<class TRef, class TableRef>
inline const Key&
Foam::StaticHashTable<T, Key, Hash>::Iterator<TRef, TableRef>::key() const
{
return hashTable_.keys_[hashIndex_][elemIndex_];
}
template<class T, class Key, class Hash>
inline typename Foam::StaticHashTable<T, Key, Hash>::iterator
Foam::StaticHashTable<T, Key, Hash>::begin()
{
// Find first non-empty entry
forAll(keys_, hashIdx)
{
if (keys_[hashIdx].size())
{
return iterator(*this, hashIdx, 0);
}
}
return StaticHashTable<T, Key, Hash>::endIter_;
}
template<class T, class Key, class Hash>
inline const typename Foam::StaticHashTable<T, Key, Hash>::iterator&
Foam::StaticHashTable<T, Key, Hash>::end()
{
return StaticHashTable<T, Key, Hash>::endIter_;
}
template<class T, class Key, class Hash>
inline typename Foam::StaticHashTable<T, Key, Hash>::const_iterator
Foam::StaticHashTable<T, Key, Hash>::cbegin() const
{
// Find first non-empty entry
forAll(keys_, hashIdx)
{
if (keys_[hashIdx].size())
{
return const_iterator(*this, hashIdx, 0);
}
}
return StaticHashTable<T, Key, Hash>::endConstIter_;
}
template<class T, class Key, class Hash>
inline const typename Foam::StaticHashTable<T, Key, Hash>::const_iterator&
Foam::StaticHashTable<T, Key, Hash>::cend() const
{
return StaticHashTable<T, Key, Hash>::endConstIter_;
}
template<class T, class Key, class Hash>
inline typename Foam::StaticHashTable<T, Key, Hash>::const_iterator
Foam::StaticHashTable<T, Key, Hash>::begin() const
{
return this->cbegin();
}
template<class T, class Key, class Hash>
inline const typename Foam::StaticHashTable<T, Key, Hash>::const_iterator&
Foam::StaticHashTable<T, Key, Hash>::end() const
{
return StaticHashTable<T, Key, Hash>::endConstIter_;
}
// ************************************************************************* //

View File

@ -1,237 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2015 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM 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 General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "StaticHashTable.H"
#include "Istream.H"
#include "Ostream.H"
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
template<class T, class Key, class Hash>
Foam::StaticHashTable<T, Key, Hash>::StaticHashTable
(
Istream& is,
const label size
)
:
StaticHashTableCore(),
keys_(StaticHashTableCore::canonicalSize(size)),
objects_(StaticHashTableCore::canonicalSize(size)),
nElmts_(0),
endIter_(*this, keys_.size(), 0),
endConstIter_(*this, keys_.size(), 0)
{
if (size < 1)
{
FatalErrorInFunction
<< "Illegal size " << size << " for StaticHashTable."
<< " Minimum size is 1" << abort(FatalError);
}
operator>>(is, *this);
}
// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
template<class T, class Key, class Hash>
Foam::Ostream&
Foam::StaticHashTable<T, Key, Hash>::printInfo(Ostream& os) const
{
label used = 0;
label maxChain = 0;
unsigned avgChain = 0;
// Find first non-empty entry
forAll(keys_, hashIdx)
{
const label count = keys_[hashIdx].size();
if (count)
{
++used;
avgChain += count;
if (maxChain < count)
{
maxChain = count;
}
}
}
os << "StaticHashTable<T,Key,Hash>"
<< " elements:" << size() << " slots:" << used << "/" << keys_.size()
<< " chaining(avg/max):" << (used ? float(avgChain/used) : 0)
<< "/" << maxChain << endl;
return os;
}
// * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * //
template<class T, class Key, class Hash>
Foam::Istream& Foam::operator>>(Istream& is, StaticHashTable<T, Key, Hash>& L)
{
is.fatalCheck(FUNCTION_NAME);
// Anull list
L.clear();
is.fatalCheck(FUNCTION_NAME);
token firstToken(is);
is.fatalCheck
(
"operator>>(Istream&, StaticHashTable<T, Key, Hash>&) : "
"reading first token"
);
if (firstToken.isLabel())
{
label s = firstToken.labelToken();
// Read beginning of contents
char delimiter = is.readBeginList("StaticHashTable<T, Key, Hash>");
if (s)
{
if (2*s > L.keys_.size())
{
L.resize(2*s);
}
if (delimiter == token::BEGIN_LIST)
{
for (label i=0; i<s; i++)
{
Key key;
is >> key;
L.insert(key, pTraits<T>(is));
is.fatalCheck
(
"operator>>(Istream&, StaticHashTable<T, Key, Hash>&)"
" : reading entry"
);
}
}
else
{
FatalIOErrorInFunction
(
is
) << "incorrect first token, '(', found " << firstToken.info()
<< exit(FatalIOError);
}
}
// Read end of contents
is.readEndList("StaticHashTable");
}
else if (firstToken.isPunctuation())
{
if (firstToken.pToken() != token::BEGIN_LIST)
{
FatalIOErrorInFunction
(
is
) << "incorrect first token, '(', found " << firstToken.info()
<< exit(FatalIOError);
}
token lastToken(is);
while
(
!(
lastToken.isPunctuation()
&& lastToken.pToken() == token::END_LIST
)
)
{
is.putBack(lastToken);
Key key;
is >> key;
T element;
is >> element;
L.insert(key, element);
is.fatalCheck
(
"operator>>(Istream&, StaticHashTable<T, Key, Hash>&) : "
"reading entry"
);
is >> lastToken;
}
}
else
{
FatalIOErrorInFunction
(
is
) << "incorrect first token, expected <int> or '(', found "
<< firstToken.info()
<< exit(FatalIOError);
}
is.fatalCheck(FUNCTION_NAME);
return is;
}
template<class T, class Key, class Hash>
Foam::Ostream& Foam::operator<<
(
Ostream& os,
const StaticHashTable<T, Key, Hash>& L)
{
// Write size and start delimiter
os << nl << L.size() << nl << token::BEGIN_LIST << nl;
// Write contents
for
(
typename StaticHashTable<T, Key, Hash>::const_iterator iter = L.begin();
iter != L.end();
++iter
)
{
os << iter.key() << token::SPACE << iter() << nl;
}
// Write end delimiter
os << token::END_LIST;
os.check(FUNCTION_NAME);
return os;
}
// ************************************************************************* //