ENH: minor update of PackedList methods

- additional convenience constructors
This commit is contained in:
Mark Olesen
2017-10-07 16:10:35 +02:00
parent f76552f7f9
commit 4ba4899660
6 changed files with 131 additions and 93 deletions

View File

@ -41,7 +41,7 @@ using namespace Foam;
template<unsigned nBits> template<unsigned nBits>
inline void reportInfo() inline void reportInfo()
{ {
unsigned offset = PackedList<nBits>::packing(); const unsigned offset = PackedList<nBits>::packing();
unsigned useSHL = ((1u << (nBits * offset)) - 1); unsigned useSHL = ((1u << (nBits * offset)) - 1);
unsigned useSHR = (~0u >> (sizeof(unsigned)*CHAR_BIT - nBits * offset)); unsigned useSHR = (~0u >> (sizeof(unsigned)*CHAR_BIT - nBits * offset));

View File

@ -92,13 +92,15 @@ bool Foam::PackedBoolList::bitorPrepare
template<class LabelListType> template<class LabelListType>
Foam::label Foam::PackedBoolList::setIndices(const LabelListType& indices) Foam::label Foam::PackedBoolList::setIndices(const LabelListType& indices)
{ {
// no better information, just guess something about the size const label len = indices.size();
reserve(indices.size());
// No better information, just guess something from the size
reserve(len);
label cnt = 0; label cnt = 0;
forAll(indices, elemI) for (label i = 0; i < len; ++i)
{ {
if (set(indices[elemI])) if (set(indices[i]))
{ {
++cnt; ++cnt;
} }
@ -112,9 +114,10 @@ template<class LabelListType>
Foam::label Foam::PackedBoolList::unsetIndices(const LabelListType& indices) Foam::label Foam::PackedBoolList::unsetIndices(const LabelListType& indices)
{ {
label cnt = 0; label cnt = 0;
forAll(indices, elemI) const label len = indices.size();
for (label i = 0; i < len; ++i)
{ {
if (unset(indices[elemI])) if (unset(indices[i]))
{ {
++cnt; ++cnt;
} }
@ -127,29 +130,30 @@ Foam::label Foam::PackedBoolList::unsetIndices(const LabelListType& indices)
template<class LabelListType> template<class LabelListType>
Foam::label Foam::PackedBoolList::subsetIndices(const LabelListType& indices) Foam::label Foam::PackedBoolList::subsetIndices(const LabelListType& indices)
{ {
// handle trivial case const label len = indices.size();
if (empty() || indices.empty())
// Handle trivial case
if (empty() || !len)
{ {
clear(); clear();
return 0; return 0;
} }
// normal case PackedBoolList result;
PackedBoolList anded; result.reserve(size());
anded.reserve(size());
label cnt = 0; label cnt = 0;
forAll(indices, elemI) for (label i = 0; i < len; ++i)
{ {
const label& index = indices[elemI]; const label index = indices[i];
if (operator[](index)) if (get(index))
{ {
anded.set(index); result.set(index);
++cnt; ++cnt;
} }
} }
transfer(anded); transfer(result);
return cnt; return cnt;
} }
@ -176,7 +180,7 @@ void Foam::PackedBoolList::set(const PackedList<1>& lst)
StorageList& lhs = this->storage(); StorageList& lhs = this->storage();
const StorageList& rhs = lst.storage(); const StorageList& rhs = lst.storage();
for (label i=0; i < len; ++i) for (label i = 0; i < len; ++i)
{ {
lhs[i] |= rhs[i]; lhs[i] |= rhs[i];
} }
@ -209,7 +213,7 @@ void Foam::PackedBoolList::unset(const PackedList<1>& lst)
// overlapping storage size // overlapping storage size
const label len = min(this->packedLength(), lst.packedLength()); const label len = min(this->packedLength(), lst.packedLength());
for (label i=0; i < len; ++i) for (label i = 0; i < len; ++i)
{ {
lhs[i] &= ~rhs[i]; lhs[i] &= ~rhs[i];
} }
@ -242,7 +246,7 @@ void Foam::PackedBoolList::subset(const PackedList<1>& lst)
const label len = this->packedLength(); const label len = this->packedLength();
for (label i=0; i < len; ++i) for (label i = 0; i < len; ++i)
{ {
lhs[i] &= rhs[i]; lhs[i] &= rhs[i];
} }
@ -288,12 +292,13 @@ Foam::Xfer<Foam::labelList> Foam::PackedBoolList::used() const
void Foam::PackedBoolList::operator=(const UList<bool>& lst) void Foam::PackedBoolList::operator=(const UList<bool>& lst)
{ {
this->setSize(lst.size()); const label len = lst.size();
this->setSize(len);
// overwrite with new true/false values // Overwrite with new true/false values
forAll(*this, elemI) for (label i = 0; i < len; ++i)
{ {
set(elemI, lst[elemI]); set(i, lst[i]);
} }
} }
@ -301,15 +306,15 @@ void Foam::PackedBoolList::operator=(const UList<bool>& lst)
Foam::PackedBoolList& Foam::PackedBoolList&
Foam::PackedBoolList::operator^=(const PackedList<1>& lst) Foam::PackedBoolList::operator^=(const PackedList<1>& lst)
{ {
// extend addressable area if needed, return maximum size possible // Extend addressable area if needed, return maximum size possible
label len = 0; label len = 0;
const bool needTrim = bitorPrepare(lst, len); const bool needTrim = bitorPrepare(lst, len);
// operate directly with the underlying storage // Operate directly with the underlying storage
StorageList& lhs = this->storage(); StorageList& lhs = this->storage();
const StorageList& rhs = lst.storage(); const StorageList& rhs = lst.storage();
for (label i=0; i < len; ++i) for (label i = 0; i < len; ++i)
{ {
lhs[i] ^= rhs[i]; lhs[i] ^= rhs[i];
} }
@ -334,7 +339,7 @@ Foam::PackedBoolList Foam::operator&
PackedBoolList result(lst1); PackedBoolList result(lst1);
result &= lst2; result &= lst2;
// trim to bits actually used // Trim to bits actually used
result.trim(); result.trim();
return result; return result;
@ -350,7 +355,7 @@ Foam::PackedBoolList Foam::operator^
PackedBoolList result(lst1); PackedBoolList result(lst1);
result ^= lst2; result ^= lst2;
// trim to bits actually used // Trim to bits actually used
result.trim(); result.trim();
return result; return result;

View File

@ -3,7 +3,7 @@
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | \\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\/ M anipulation | \\/ M anipulation | Copyright (C) 2017 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -96,7 +96,7 @@ public:
//- Construct from Istream //- Construct from Istream
PackedBoolList(Istream& is); PackedBoolList(Istream& is);
//- Construct with given size, initializes list to 0 //- Construct with given size, initializes list to 0 (false)
explicit inline PackedBoolList(const label size); explicit inline PackedBoolList(const label size);
//- Construct with given size and value for all elements //- Construct with given size and value for all elements
@ -114,6 +114,20 @@ public:
//- Construct by transferring the parameter contents //- Construct by transferring the parameter contents
inline PackedBoolList(const Xfer<PackedList<1>>& lst); inline PackedBoolList(const Xfer<PackedList<1>>& lst);
//- Construct with given size and list of labels to set as true.
inline PackedBoolList
(
const label size,
const labelUList& indices
);
//- Construct with given size and list of labels to set as true.
inline PackedBoolList
(
const label size,
const UIndirectList<label>& indices
);
//- Construct from a list of bools //- Construct from a list of bools
explicit inline PackedBoolList(const UList<bool>& lst); explicit inline PackedBoolList(const UList<bool>& lst);

View File

@ -3,7 +3,7 @@
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | \\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\/ M anipulation | \\/ M anipulation | Copyright (C) 2017 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -75,23 +75,52 @@ inline Foam::PackedBoolList::PackedBoolList(const Xfer<PackedList<1>>& lst)
inline Foam::PackedBoolList::PackedBoolList(const UList<bool>& lst) inline Foam::PackedBoolList::PackedBoolList(const UList<bool>& lst)
: :
PackedList<1>() PackedList<1>(lst.size())
{ {
operator=(lst); // Set according to indices that are true
const label len = lst.size();
for (label i = 0; i < len; ++i)
{
if (lst[i])
{
this->set(i, 1u);
}
}
} }
inline Foam::PackedBoolList::PackedBoolList(const labelUList& indices) inline Foam::PackedBoolList::PackedBoolList(const labelUList& indices)
: :
PackedList<1>(indices.size(), 0u) PackedBoolList(indices.size(), indices)
{}
inline Foam::PackedBoolList::PackedBoolList(const UIndirectList<label>& indices)
:
PackedBoolList(indices.size(), indices)
{}
inline Foam::PackedBoolList::PackedBoolList
(
const label size,
const labelUList& indices
)
:
PackedList<1>(size)
{ {
set(indices); set(indices);
} }
inline Foam::PackedBoolList::PackedBoolList(const UIndirectList<label>& indices) inline Foam::PackedBoolList::PackedBoolList
(
const label size,
const UIndirectList<label>& indices
)
: :
PackedList<1>(indices.size(), 0u) PackedList<1>(size)
{ {
set(indices); set(indices);
} }

View File

@ -48,8 +48,9 @@ Note
list[1] = list[5] = list[6]; // propagates value list[1] = list[5] = list[6]; // propagates value
\endcode \endcode
Using get() or the '[]' operator are similarly fast. Looping and reading Reading via the get() or the '[]' operator are identical.
via an iterator is approx. 15% slower, but can be more flexible. Looping and reading via an iterator is approx. 15% slower,
but can be more flexible.
Using the set() operator (and the '[]' operator) are marginally slower Using the set() operator (and the '[]' operator) are marginally slower
(approx. 5%) than using an iterator, but the set() method has the (approx. 5%) than using an iterator, but the set() method has the
@ -157,7 +158,7 @@ protected:
// Protected Member Functions // Protected Member Functions
//- Calculate the list length when packed //- Calculate the list length when packed
inline static label packedLength(const label); inline static label packedLength(const label nElem);
//- Read a list entry (allows for specialization) //- Read a list entry (allows for specialization)
inline static unsigned int readValue(Istream& is); inline static unsigned int readValue(Istream& is);
@ -200,14 +201,14 @@ public:
//- The max. number of bits that can be templated. //- The max. number of bits that can be templated.
// Might someday be useful for a template assert. // Might someday be useful for a template assert.
inline static unsigned int max_bits(); inline static constexpr unsigned int max_bits();
//- The max. value for an entry, which simultaneously the bit-mask //- The max. value for an entry, which simultaneously the bit-mask
// eg, ((1 << 2) - 1) yields 0b0011 // eg, ((1 << 2) - 1) yields 0b0011
inline static unsigned int max_value(); inline static constexpr unsigned int max_value();
//- The number of entries per packed storage element //- The number of entries per packed storage element
inline static unsigned int packing(); inline static constexpr unsigned int packing();
//- Masking for all bits below the offset //- Masking for all bits below the offset
inline static unsigned int maskLower(unsigned offset); inline static unsigned int maskLower(unsigned offset);
@ -393,11 +394,11 @@ public:
//- Remove and return the last element //- Remove and return the last element
inline unsigned int remove(); inline unsigned int remove();
//- Get value at index I //- Identical to get() - get value at index.
// Never auto-vivify entries. // Never auto-vivify entries.
inline unsigned int operator[](const label i) const; inline unsigned int operator[](const label i) const;
//- Set value at index I. //- Non-const access to value at index.
// Returns iterator to perform the actual operation. // Returns iterator to perform the actual operation.
// Does not auto-vivify entries, but will when assigned to. // Does not auto-vivify entries, but will when assigned to.
inline iteratorBase operator[](const label i); inline iteratorBase operator[](const label i);
@ -496,11 +497,11 @@ public:
//- Disallow copy constructor from const_iterator //- Disallow copy constructor from const_iterator
// This would violate const-ness! // This would violate const-ness!
iterator(const const_iterator& iter); iterator(const const_iterator& iter) = delete;
//- Disallow assignment from const_iterator //- Disallow assignment from const_iterator
// This would violate const-ness! // This would violate const-ness!
void operator=(const const_iterator& iter); void operator=(const const_iterator& iter) = delete;
public: public:

View File

@ -3,7 +3,7 @@
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | \\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\/ M anipulation | \\/ M anipulation | Copyright (C) 2017 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -25,24 +25,24 @@ License
#include <climits> #include <climits>
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
template<unsigned nBits> template<unsigned nBits>
inline unsigned int Foam::PackedList<nBits>::max_bits() inline constexpr unsigned int Foam::PackedList<nBits>::max_bits()
{ {
return sizeof(StorageType)*CHAR_BIT - 1; return sizeof(StorageType)*CHAR_BIT - 1;
} }
template<unsigned nBits> template<unsigned nBits>
inline unsigned int Foam::PackedList<nBits>::max_value() inline constexpr unsigned int Foam::PackedList<nBits>::max_value()
{ {
return (1u << nBits) - 1; return (1u << nBits) - 1;
} }
template<unsigned nBits> template<unsigned nBits>
inline unsigned int Foam::PackedList<nBits>::packing() inline constexpr unsigned int Foam::PackedList<nBits>::packing()
{ {
return sizeof(StorageType)*CHAR_BIT / nBits; return sizeof(StorageType)*CHAR_BIT / nBits;
} }
@ -65,6 +65,8 @@ inline Foam::label Foam::PackedList<nBits>::packedLength(const label nElem)
} }
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
namespace Foam namespace Foam
{ {
// Template specialization for bool entries // Template specialization for bool entries
@ -88,13 +90,10 @@ namespace Foam
if (this->get()) if (this->get())
{ {
os << index_; os << index_;
return true; return true;
} }
else
{ return false;
return false;
}
} }
} }
@ -119,12 +118,12 @@ inline unsigned int Foam::PackedList<nBits>::readValue(Istream& is)
template<unsigned nBits> template<unsigned nBits>
inline void Foam::PackedList<nBits>::setPair(Istream& is) inline void Foam::PackedList<nBits>::setPair(Istream& is)
{ {
is.readBegin("Tuple2<label, unsigned int>"); is.readBegin("Tuple2<label,unsigned int>");
const label ind = readLabel(is); const label ind = readLabel(is);
const unsigned int val = readLabel(is); const unsigned int val = readLabel(is);
is.readEnd("Tuple2<label, unsigned int>"); is.readEnd("Tuple2<label,unsigned int>");
if (val > max_value()) if (val > max_value())
{ {
@ -154,10 +153,8 @@ inline bool Foam::PackedList<nBits>::iteratorBase::writeIfSet(Ostream& os) const
return true; return true;
} }
else
{ return false;
return false;
}
} }
@ -233,7 +230,8 @@ inline Foam::PackedList<nBits>::PackedList(const labelUList& lst)
StorageList(packedLength(lst.size()), 0u), StorageList(packedLength(lst.size()), 0u),
size_(lst.size()) size_(lst.size())
{ {
forAll(lst, i) const label len = lst.size();
for (label i = 0; i < len; ++i)
{ {
set(i, lst[i]); set(i, lst[i]);
} }
@ -247,7 +245,8 @@ inline Foam::PackedList<nBits>::PackedList(const UIndirectList<label>& lst)
StorageList(packedLength(lst.size()), 0u), StorageList(packedLength(lst.size()), 0u),
size_(lst.size()) size_(lst.size())
{ {
forAll(lst, i) const label len = lst.size();
for (label i = 0; i < len; ++i)
{ {
set(i, lst[i]); set(i, lst[i]);
} }
@ -862,16 +861,16 @@ inline void Foam::PackedList<nBits>::reserve(const label nElem)
{ {
const label len = packedLength(nElem); const label len = packedLength(nElem);
// Need more capacity? // Allocate more capacity if necessary
if (len > StorageList::size()) if (len > StorageList::size())
{ {
// Like DynamicList with SizeInc=0, SizeMult=2, SizeDiv=1
StorageList::setSize StorageList::setSize
( (
max max
( (
len, len,
StorageList::size()*2 // SizeInc=0, SizeMult=2, SizeDiv=1
2 * StorageList::size()
), ),
0u 0u
); );
@ -964,27 +963,17 @@ inline unsigned int Foam::PackedList<nBits>::get(const label i) const
// Lazy evaluation - return 0 for out-of-range // Lazy evaluation - return 0 for out-of-range
if (i < 0 || i >= size_) if (i < 0 || i >= size_)
{ {
return 0; return 0u;
}
else
{
return iteratorBase(this, i).get();
} }
return iteratorBase(this, i).get();
} }
template<unsigned nBits> template<unsigned nBits>
inline unsigned int Foam::PackedList<nBits>::operator[](const label i) const inline unsigned int Foam::PackedList<nBits>::operator[](const label i) const
{ {
// Lazy evaluation - return 0 for out-of-range return get(i);
if (i < 0 || i >= size_)
{
return 0;
}
else
{
return iteratorBase(this, i).get();
}
} }
@ -1024,10 +1013,8 @@ inline bool Foam::PackedList<nBits>::unset(const label i)
{ {
return false; return false;
} }
else
{ return iteratorBase(this, i).set(0u);
return iteratorBase(this, i).set(0u);
}
} }
@ -1035,11 +1022,11 @@ template<unsigned nBits>
inline Foam::PackedList<nBits>& inline Foam::PackedList<nBits>&
Foam::PackedList<nBits>::append(const unsigned int val) Foam::PackedList<nBits>::append(const unsigned int val)
{ {
const label elemI = size_; const label idx = size_;
reserve(elemI + 1); reserve(idx + 1);
size_++; size_++;
iteratorBase(this, elemI).set(val); iteratorBase(this, idx).set(val);
return *this; return *this;
} }
@ -1047,15 +1034,17 @@ Foam::PackedList<nBits>::append(const unsigned int val)
template<unsigned nBits> template<unsigned nBits>
inline unsigned int Foam::PackedList<nBits>::remove() inline unsigned int Foam::PackedList<nBits>::remove()
{ {
if (!size_) // Location of last element and simultaneously the new size
const label idx = size_ - 1;
if (idx < 0)
{ {
FatalErrorInFunction FatalErrorInFunction
<< "List is empty" << abort(FatalError); << "List is empty" << abort(FatalError);
} }
label elemI = size_ - 1; const unsigned int val = iteratorBase(this, idx).get();
const unsigned int val = iteratorBase(this, elemI).get(); resize(idx);
resize(elemI);
return val; return val;
} }