Commit 4ee65d12 authored by Mark Olesen's avatar Mark Olesen
Browse files

ENH: HashTable and HashSet improvements

- unfriend HashSet, HashTable IO operators

- global min(), max(), minMax() functions taking a labelHashSet and an
  optional limit. For example,

      labelHashSet set = ...;

      Info<< "min is " << min(set) << nl;
      Info<< "max (non-negative) " << max(set, 0) << nl;

- make HashTable iterator '->' dereferencing more consistent by also
  supporting non-pointer types as well.

- read HashTable values in-situ to avoid copying
parent 05739d6a
...@@ -32,6 +32,7 @@ Description ...@@ -32,6 +32,7 @@ Description
#include "HashOps.H" #include "HashOps.H"
#include "HashSet.H" #include "HashSet.H"
#include "Map.H" #include "Map.H"
#include "MinMax.H"
#include "labelPairHashes.H" #include "labelPairHashes.H"
#include "FlatOutput.H" #include "FlatOutput.H"
...@@ -184,6 +185,9 @@ int main(int argc, char *argv[]) ...@@ -184,6 +185,9 @@ int main(int argc, char *argv[])
1, 11, 42 1, 11, 42
}; };
Info<<"Set with min/max:" << minMax(setB)
<< " min:" << min(setB) << " max:" << max(setB) << nl;
setB = FixedList<label, 4>({1, 2, 3, 4}); setB = FixedList<label, 4>({1, 2, 3, 4});
setB = {1, 2, 4}; setB = {1, 2, 4};
setB = List<label>({1, 2, 4}); setB = List<label>({1, 2, 4});
......
...@@ -261,14 +261,24 @@ int main(int argc, char *argv[]) ...@@ -261,14 +261,24 @@ int main(int argc, char *argv[])
labelList list1(identity(4, -4)); labelList list1(identity(4, -4));
Info<<"move insert " << list1 << nl; Info<< "move insert " << list1 << nl;
ltable1.insert("pqr", std::move(list1)); ltable1.insert("pqr", std::move(list1));
Info<<"after insert " << list1 << nl; Info<< "after insert " << list1 << nl;
Info<< nl << "HashTable<labelList>: " Info<< nl << "HashTable<labelList>: "
<< ltable1 << nl; << ltable1 << nl;
// Use '->' dereferencing
const auto iter = ltable1.cfind("ghi");
if (iter)
{
Info<< "got with " << iter->size() << nl;
}
} }
Info<< "\nEnd\n" << endl; Info<< "\nEnd\n" << endl;
......
...@@ -171,6 +171,7 @@ containers/Bits/bitSet/bitSetIO.C ...@@ -171,6 +171,7 @@ containers/Bits/bitSet/bitSetIO.C
containers/Bits/BitOps/BitOps.C containers/Bits/BitOps/BitOps.C
containers/Bits/PackedList/PackedListCore.C containers/Bits/PackedList/PackedListCore.C
containers/HashTables/HashOps/HashOps.C containers/HashTables/HashOps/HashOps.C
containers/HashTables/HashSet/hashSets.C
containers/HashTables/HashTable/HashTableCore.C containers/HashTables/HashTable/HashTableCore.C
containers/Lists/SortableList/ParSortableListName.C containers/Lists/SortableList/ParSortableListName.C
containers/Lists/ListOps/ListOps.C containers/Lists/ListOps/ListOps.C
......
...@@ -73,10 +73,7 @@ namespace Foam ...@@ -73,10 +73,7 @@ namespace Foam
{ {
// Forward declarations // Forward declarations
template<class Key, class Hash> class HashSet; template<class T> class MinMax;
template<class Key, class Hash>
Ostream& operator<<(Ostream& os, const HashSet<Key, Hash>& tbl);
/*---------------------------------------------------------------------------*\ /*---------------------------------------------------------------------------*\
...@@ -380,15 +377,6 @@ public: ...@@ -380,15 +377,6 @@ public:
inline this_type& operator-=(const this_type& rhs); inline this_type& operator-=(const this_type& rhs);
// IOstream Operator
friend Ostream& operator<< <Key, Hash>
(
Ostream& os,
const HashSet<Key, Hash>& tbl
);
// Housekeeping // Housekeeping
//- Not applicable for HashSet //- Not applicable for HashSet
...@@ -418,8 +406,36 @@ public: ...@@ -418,8 +406,36 @@ public:
}; };
// Typedefs
//- A HashSet with word keys.
typedef HashSet<word> wordHashSet;
//- A HashSet with label keys and label hasher.
typedef HashSet<label, Hash<label>> labelHashSet;
// Global Functions
//- Find the min value in labelHashSet, optionally limited by second argument.
// For an empty set, returns the second argument (eg, labelMax).
label min(const labelHashSet& set, label minValue = labelMax);
//- Find the max value in labelHashSet, optionally limited by second argument.
// For an empty set, returns the second argument (eg, labelMin).
label max(const labelHashSet& set, label maxValue = labelMin);
//- Find the min/max values of labelHashSet
MinMax<label> minMax(const labelHashSet& set);
// Global Operators // Global Operators
//- Write the list of HashSet keys
template<class Key, class Hash>
Ostream& operator<<(Ostream& os, const HashSet<Key, Hash>& tbl);
//- Combine entries from HashSets //- Combine entries from HashSets
template<class Key, class Hash> template<class Key, class Hash>
HashSet<Key, Hash> operator| HashSet<Key, Hash> operator|
...@@ -447,13 +463,6 @@ HashSet<Key, Hash> operator^ ...@@ -447,13 +463,6 @@ HashSet<Key, Hash> operator^
); );
//- A HashSet with word keys.
typedef HashSet<word> wordHashSet;
//- A HashSet with label keys and label hasher.
typedef HashSet<label, Hash<label>> labelHashSet;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam } // End namespace Foam
......
...@@ -104,12 +104,6 @@ template<class T> class UList; ...@@ -104,12 +104,6 @@ template<class T> class UList;
template<class T, unsigned N> class FixedList; template<class T, unsigned N> class FixedList;
template<class T, class Key, class Hash> class HashTable; template<class T, class Key, class Hash> class HashTable;
template<class T, class Key, class Hash>
Istream& operator>>(Istream& is, HashTable<T, Key, Hash>& tbl);
template<class T, class Key, class Hash>
Ostream& operator<<(Ostream& os, const HashTable<T, Key, Hash>& tbl);
/*---------------------------------------------------------------------------*\ /*---------------------------------------------------------------------------*\
Class HashTable Declaration Class HashTable Declaration
...@@ -149,10 +143,6 @@ class HashTable ...@@ -149,10 +143,6 @@ class HashTable
// No checks for zero-sized tables. // No checks for zero-sized tables.
inline label hashKeyIndex(const Key& key) const; inline label hashKeyIndex(const Key& key) const;
//- Read entry (key, val) and assign
// \return True if the new entry was set.
bool addEntry(Istream& is, const bool overwrite = false);
//- Assign a new hash-entry to a possibly already existing key. //- Assign a new hash-entry to a possibly already existing key.
// \return True if the new entry was set. // \return True if the new entry was set.
template<class... Args> template<class... Args>
...@@ -732,7 +722,7 @@ public: ...@@ -732,7 +722,7 @@ public:
inline reference operator*() const { return this->val(); } inline reference operator*() const { return this->val(); }
inline reference operator()() const { return this->val(); } inline reference operator()() const { return this->val(); }
//- For pointer types, allow direct pointer dereferencing //- Direct pointer dereferencing (pointer types)
template<class TypeT = T> template<class TypeT = T>
typename std::enable_if typename std::enable_if
< <
...@@ -740,6 +730,14 @@ public: ...@@ -740,6 +730,14 @@ public:
T T
>::type operator->() const { return this->val(); } >::type operator->() const { return this->val(); }
//- Address of iterated value (non-pointer types)
template<class TypeT = T>
typename std::enable_if
<
!Detail::isPointer<TypeT>::value,
T*
>::type operator->() const { return &(this->val()); }
inline iterator& operator++(); inline iterator& operator++();
inline iterator operator++(int); inline iterator operator++(int);
}; };
...@@ -802,7 +800,7 @@ public: ...@@ -802,7 +800,7 @@ public:
inline reference operator*() const { return this->val(); } inline reference operator*() const { return this->val(); }
inline reference operator()() const { return this->val(); } inline reference operator()() const { return this->val(); }
//- For pointer types, allow direct pointer dereferencing //- Direct pointer dereferencing (pointer types)
template<class TypeT = T> template<class TypeT = T>
typename std::enable_if typename std::enable_if
< <
...@@ -810,6 +808,14 @@ public: ...@@ -810,6 +808,14 @@ public:
const T const T
>::type operator->() const { return this->val(); } >::type operator->() const { return this->val(); }
//- Address of iterated value (non-pointer types)
template<class TypeT = T>
typename std::enable_if
<
!Detail::isPointer<TypeT>::value,
const T*
>::type operator->() const { return &(this->val()); }
inline const_iterator& operator++(); inline const_iterator& operator++();
inline const_iterator operator++(int); inline const_iterator operator++(int);
...@@ -911,22 +917,16 @@ public: ...@@ -911,22 +917,16 @@ public:
//- when length exceeds shortLen. //- when length exceeds shortLen.
// Using '0' suppresses line-breaks entirely. // Using '0' suppresses line-breaks entirely.
Ostream& writeKeys(Ostream& os, const label shortLen=0) const; Ostream& writeKeys(Ostream& os, const label shortLen=0) const;
};
// IOstream Operator // IOstream Operators
friend Istream& operator>> <T, Key, Hash> template<class T, class Key, class Hash>
( Istream& operator>>(Istream& is, HashTable<T, Key, Hash>& tbl);
Istream& is,
HashTable<T, Key, Hash>& tbl
);
friend Ostream& operator<< <T, Key, Hash> template<class T, class Key, class Hash>
( Ostream& operator<<(Ostream& os, const HashTable<T, Key, Hash>& tbl);
Ostream& os,
const HashTable<T, Key, Hash>& tbl
);
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
......
...@@ -29,28 +29,6 @@ License ...@@ -29,28 +29,6 @@ License
#include "Istream.H" #include "Istream.H"
#include "Ostream.H" #include "Ostream.H"
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
template<class T, class Key, class Hash>
bool Foam::HashTable<T, Key, Hash>::addEntry(Istream& is, const bool overwrite)
{
typename node_type::key_type key;
typename node_type::mapped_type val;
is >> key >> val;
const bool ok = this->setEntry(overwrite, key, val);
is.fatalCheck
(
"HashTable::addEntry(Istream&) : "
"reading entry"
);
return ok;
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
...@@ -168,11 +146,11 @@ template<class T, class Key, class Hash> ...@@ -168,11 +146,11 @@ template<class T, class Key, class Hash>
Foam::Istream& Foam::operator>> Foam::Istream& Foam::operator>>
( (
Istream& is, Istream& is,
HashTable<T, Key, Hash>& L HashTable<T, Key, Hash>& tbl
) )
{ {
// Anull existing table // Anull existing table
L.clear(); tbl.clear();
is.fatalCheck(FUNCTION_NAME); is.fatalCheck(FUNCTION_NAME);
...@@ -193,23 +171,31 @@ Foam::Istream& Foam::operator>> ...@@ -193,23 +171,31 @@ Foam::Istream& Foam::operator>>
if (len) if (len)
{ {
if (2*len > L.capacity_) if (delimiter != token::BEGIN_LIST)
{ {
L.resize(2*len); FatalIOErrorInFunction(is)
<< "incorrect first token, '(', found " << firstToken.info()
<< exit(FatalIOError);
} }
if (delimiter == token::BEGIN_LIST) if (2*len > tbl.capacity())
{ {
for (label i=0; i<len; ++i) tbl.resize(2*len);
{
L.addEntry(is);
}
} }
else
for (label i=0; i<len; ++i)
{ {
FatalIOErrorInFunction(is) Key key;
<< "incorrect first token, '(', found " << firstToken.info()
<< exit(FatalIOError); is >> key; // Read the key
T& val = tbl(key); // Insert nameless T() into table
is >> val; // Read directly into the table value
is.fatalCheck
(
"operator>>(Istream&, HashTable&) : "
"reading entry"
);
} }
} }
...@@ -236,7 +222,17 @@ Foam::Istream& Foam::operator>> ...@@ -236,7 +222,17 @@ Foam::Istream& Foam::operator>>
{ {
is.putBack(lastToken); is.putBack(lastToken);
L.addEntry(is); Key key;
is >> key; // Read the key
T& val = tbl(key); // Insert nameless T() into table
is >> val; // Read directly into the table value
is.fatalCheck
(
"operator>>(Istream&, HashTable&) : "
"reading entry"
);
is >> lastToken; is >> lastToken;
} }
...@@ -250,7 +246,6 @@ Foam::Istream& Foam::operator>> ...@@ -250,7 +246,6 @@ Foam::Istream& Foam::operator>>
} }
is.fatalCheck(FUNCTION_NAME); is.fatalCheck(FUNCTION_NAME);
return is; return is;
} }
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment