PackedList tweaks

- set() handles overflow as max_value() - the principle of least surprise.
- use pointers in iterator to avoid any assignment issues. Allows default
  bitwise copy/assignment.
This commit is contained in:
Mark Olesen
2009-01-26 10:16:37 +01:00
parent 94dc33da2e
commit 295d503d83
3 changed files with 100 additions and 68 deletions

View File

@ -31,7 +31,7 @@ License
template<int nBits> template<int nBits>
Foam::PackedList<nBits>::PackedList(const label size, const unsigned int val) Foam::PackedList<nBits>::PackedList(const label size, const unsigned int val)
: :
List<PackedStorage>(packedLength(size), 0u), StorageList(packedLength(size), 0u),
size_(size) size_(size)
{ {
operator=(val); operator=(val);
@ -41,7 +41,7 @@ Foam::PackedList<nBits>::PackedList(const label size, const unsigned int val)
template<int nBits> template<int nBits>
Foam::PackedList<nBits>::PackedList(const UList<label>& lst) Foam::PackedList<nBits>::PackedList(const UList<label>& lst)
: :
List<PackedStorage>(packedLength(lst.size()), 0u), StorageList(packedLength(lst.size()), 0u),
size_(lst.size()) size_(lst.size())
{ {
forAll(lst, i) forAll(lst, i)
@ -94,7 +94,7 @@ Foam::Ostream& Foam::PackedList<nBits>::print(Ostream& os) const
label packLen = packedLength(size()); label packLen = packedLength(size());
os << ")\n" os << ")\n"
<< "storage: " << packLen << "/" << storage().size() << "( "; << "storage: " << packLen << "/" << StorageList::size() << "( ";
// mask for the valid bits // mask for the valid bits
unsigned int validBits = max_value(); unsigned int validBits = max_value();
@ -105,7 +105,7 @@ Foam::Ostream& Foam::PackedList<nBits>::print(Ostream& os) const
for (label i=0; i < packLen; i++) for (label i=0; i < packLen; i++)
{ {
const PackedStorage& rawBits = storage()[i]; const StorageType& rawBits = StorageList::operator[](i);
// the final storage may not be full, modify validBits accordingly // the final storage may not be full, modify validBits accordingly
if (i+1 == packLen) if (i+1 == packLen)
@ -155,7 +155,7 @@ template<int nBits>
void Foam::PackedList<nBits>::operator=(const PackedList<nBits>& lst) void Foam::PackedList<nBits>::operator=(const PackedList<nBits>& lst)
{ {
setCapacity(lst.size()); setCapacity(lst.size());
List<PackedStorage>::operator=(lst); StorageList::operator=(lst);
} }

View File

@ -92,7 +92,8 @@ class PackedList
: :
private List<unsigned int> private List<unsigned int>
{ {
typedef unsigned int PackedStorage; typedef unsigned int StorageType;
typedef List<StorageType> StorageList;
// Private data // Private data
@ -247,9 +248,9 @@ public:
// friend Ostream& operator<< <nBits> (Ostream&, const PackedList<nBits>&); // friend Ostream& operator<< <nBits> (Ostream&, const PackedList<nBits>&);
//- The const_iterator for PackedList //- The const_iterator for PackedList
// Note: make data and functions protected, to allow reuse by iterator. // Note: data and functions are protected, to allow reuse by iterator.
// Try not to be disturbed by non-const methods such as set(), they are // Try not to be disturbed by non-const methods such as set(), they are
// just inherited by iterator. // just inherited and used by iterator.
class const_iterator class const_iterator
{ {
friend class PackedList; friend class PackedList;
@ -258,8 +259,9 @@ public:
// Protected Data // Protected Data
//- Reference to original list //- Pointer to original list
PackedList& list_; // This also lets us use the default bitwise copy/assignment
PackedList* list_;
//- Element index within storage //- Element index within storage
unsigned index_; unsigned index_;
@ -281,7 +283,7 @@ public:
// Constructors // Constructors
//- Construct from base list and position index //- Construct from base list and position index
inline const_iterator(const PackedList&, const label); inline const_iterator(const PackedList*, const label);
//- Construct from non-const iterator //- Construct from non-const iterator
explicit inline const_iterator(const iterator&); explicit inline const_iterator(const iterator&);
@ -351,7 +353,7 @@ public:
// Constructors // Constructors
//- Construct from base list and position index //- Construct from base list and position index
inline iterator(const PackedList&, const label); inline iterator(const PackedList*, const label);
// Member Operators // Member Operators
inline void operator=(const iterator&); inline void operator=(const iterator&);

View File

@ -33,7 +33,7 @@ License
template<int nBits> template<int nBits>
inline unsigned int Foam::PackedList<nBits>::max_bits() inline unsigned int Foam::PackedList<nBits>::max_bits()
{ {
return sizeof(PackedStorage)*CHAR_BIT - 1; return sizeof(StorageType)*CHAR_BIT - 1;
} }
@ -47,7 +47,7 @@ inline unsigned int Foam::PackedList<nBits>::max_value()
template<int nBits> template<int nBits>
inline unsigned int Foam::PackedList<nBits>::packing() inline unsigned int Foam::PackedList<nBits>::packing()
{ {
return sizeof(PackedStorage)*CHAR_BIT / nBits; return sizeof(StorageType)*CHAR_BIT / nBits;
} }
@ -81,7 +81,7 @@ inline void Foam::PackedList<nBits>::checkIndex(const label i) const
template<int nBits> template<int nBits>
inline Foam::PackedList<nBits>::PackedList() inline Foam::PackedList<nBits>::PackedList()
: :
List<PackedStorage>(), StorageList(),
size_(0) size_(0)
{} {}
@ -89,7 +89,7 @@ inline Foam::PackedList<nBits>::PackedList()
template<int nBits> template<int nBits>
inline Foam::PackedList<nBits>::PackedList(const label size) inline Foam::PackedList<nBits>::PackedList(const label size)
: :
List<PackedStorage>(packedLength(size), 0u), StorageList(packedLength(size), 0u),
size_(size) size_(size)
{} {}
@ -97,7 +97,7 @@ inline Foam::PackedList<nBits>::PackedList(const label size)
template<int nBits> template<int nBits>
inline Foam::PackedList<nBits>::PackedList(const PackedList<nBits>& lst) inline Foam::PackedList<nBits>::PackedList(const PackedList<nBits>& lst)
: :
List<PackedStorage>(lst), StorageList(lst),
size_(lst.size()) size_(lst.size())
{} {}
@ -122,11 +122,11 @@ Foam::PackedList<nBits>::clone() const
template<int nBits> template<int nBits>
inline Foam::PackedList<nBits>::const_iterator::const_iterator inline Foam::PackedList<nBits>::const_iterator::const_iterator
( (
const PackedList<nBits>& lst, const PackedList<nBits>* lst,
const label i const label i
) )
: :
list_(const_cast<PackedList<nBits>&>(lst)), list_(const_cast<PackedList<nBits>*>(lst)),
index_(i / packing()), index_(i / packing()),
offset_(i % packing()) offset_(i % packing())
{} {}
@ -135,7 +135,7 @@ inline Foam::PackedList<nBits>::const_iterator::const_iterator
template<int nBits> template<int nBits>
inline Foam::PackedList<nBits>::iterator::iterator inline Foam::PackedList<nBits>::iterator::iterator
( (
const PackedList<nBits>& lst, const PackedList<nBits>* lst,
const label i const label i
) )
: :
@ -155,17 +155,6 @@ inline Foam::PackedList<nBits>::const_iterator::const_iterator
{} {}
template<int nBits>
inline void Foam::PackedList<nBits>::iterator::operator=
(
const iterator& it
)
{
this->index_ = it.index_;
this->offset_ = it.offset_;
}
template<int nBits> template<int nBits>
inline bool Foam::PackedList<nBits>::const_iterator::operator== inline bool Foam::PackedList<nBits>::const_iterator::operator==
( (
@ -189,7 +178,7 @@ inline bool Foam::PackedList<nBits>::const_iterator::operator!=
template<int nBits> template<int nBits>
inline unsigned int Foam::PackedList<nBits>::const_iterator::get() const inline unsigned int Foam::PackedList<nBits>::const_iterator::get() const
{ {
const unsigned int& stored = list_.List<PackedStorage>::operator[](index_); const unsigned int& stored = list_->StorageList::operator[](index_);
return (stored >> (nBits * offset_)) & max_value(); return (stored >> (nBits * offset_)) & max_value();
} }
@ -197,13 +186,30 @@ inline unsigned int Foam::PackedList<nBits>::const_iterator::get() const
template<int nBits> template<int nBits>
inline bool Foam::PackedList<nBits>::const_iterator::set(const unsigned int val) inline bool Foam::PackedList<nBits>::const_iterator::set(const unsigned int val)
{ {
unsigned int& stored = list_.List<PackedStorage>::operator[](index_); unsigned int& stored = list_->StorageList::operator[](index_);
const unsigned int prev = stored; const unsigned int prev = stored;
const unsigned int startBit = nBits * offset_; const unsigned int startBit = nBits * offset_;
const unsigned int maskNew = max_value() << startBit; const unsigned int maskNew = max_value() << startBit;
if (val & ~max_value())
{
# ifdef DEBUGList
FatalErrorIn("PackedList<T>::iterator::set(const unsigned int)")
<< "value " << label(val)
<< " out-of-range 0 ... " << label(max_value())
<< " representable by " << nBits << " bits"
<< abort(FatalError);
# endif
// treat overflow as max_value
stored |= maskNew;
}
else
{
stored = (stored & ~maskNew) | (maskNew & (val << startBit)); stored = (stored & ~maskNew) | (maskNew & (val << startBit));
}
return prev != stored; return prev != stored;
} }
@ -338,7 +344,7 @@ template<int nBits>
inline typename Foam::PackedList<nBits>::iterator inline typename Foam::PackedList<nBits>::iterator
Foam::PackedList<nBits>::begin() Foam::PackedList<nBits>::begin()
{ {
return iterator(*this, 0); return iterator(this, 0);
} }
@ -346,7 +352,7 @@ template<int nBits>
inline typename Foam::PackedList<nBits>::const_iterator inline typename Foam::PackedList<nBits>::const_iterator
Foam::PackedList<nBits>::begin() const Foam::PackedList<nBits>::begin() const
{ {
return const_iterator(*this, 0); return const_iterator(this, 0);
} }
@ -354,7 +360,7 @@ template<int nBits>
inline typename Foam::PackedList<nBits>::const_iterator inline typename Foam::PackedList<nBits>::const_iterator
Foam::PackedList<nBits>::cbegin() const Foam::PackedList<nBits>::cbegin() const
{ {
return const_iterator(*this, 0); return const_iterator(this, 0);
} }
@ -362,7 +368,7 @@ template<int nBits>
inline typename Foam::PackedList<nBits>::iterator inline typename Foam::PackedList<nBits>::iterator
Foam::PackedList<nBits>::end() Foam::PackedList<nBits>::end()
{ {
return iterator(*this, size()); return iterator(this, this->size());
} }
@ -370,7 +376,7 @@ template<int nBits>
inline typename Foam::PackedList<nBits>::const_iterator inline typename Foam::PackedList<nBits>::const_iterator
Foam::PackedList<nBits>::end() const Foam::PackedList<nBits>::end() const
{ {
return iterator(*this, size()); return iterator(this, this->size());
} }
@ -378,7 +384,7 @@ template<int nBits>
inline typename Foam::PackedList<nBits>::const_iterator inline typename Foam::PackedList<nBits>::const_iterator
Foam::PackedList<nBits>::cend() const Foam::PackedList<nBits>::cend() const
{ {
return iterator(*this, size()); return iterator(this, this->size());
} }
@ -413,7 +419,21 @@ inline void Foam::PackedList<nBits>::resize
if (size_) if (size_)
{ {
// fill value for complete chunks // fill value for complete chunks
unsigned int fill = val & max_value(); unsigned int fill = val;
if (fill & ~max_value())
{
# ifdef DEBUGList
FatalErrorIn("PackedList<T>::resize(label, const unsigned int)")
<< "value " << label(val)
<< " out-of-range 0 ... " << label(max_value())
<< " representable by " << nBits << " bits"
<< abort(FatalError);
# endif
// treat overflow as max_value
fill = max_value();
}
for (unsigned int i = 1; i < packing(); ++i) for (unsigned int i = 1; i < packing(); ++i)
{ {
fill |= (fill << nBits); fill |= (fill << nBits);
@ -432,8 +452,8 @@ inline void Foam::PackedList<nBits>::resize
maskOld |= (maskOld << nBits); maskOld |= (maskOld << nBits);
} }
List<PackedStorage>::operator[](begIdx) &= maskOld; StorageList::operator[](begIdx) &= maskOld;
List<PackedStorage>::operator[](begIdx) |= ~maskOld & fill; StorageList::operator[](begIdx) |= ~maskOld & fill;
// continue with the next chunk // continue with the next chunk
begIdx++; begIdx++;
@ -442,7 +462,7 @@ inline void Foam::PackedList<nBits>::resize
// fill in complete elements // fill in complete elements
while (begIdx < endIdx) while (begIdx < endIdx)
{ {
List<PackedStorage>::operator[](begIdx++) = fill; StorageList::operator[](begIdx++) = fill;
} }
} }
else else
@ -471,14 +491,14 @@ inline void Foam::PackedList<nBits>::setSize
template<int nBits> template<int nBits>
inline Foam::label Foam::PackedList<nBits>::capacity() const inline Foam::label Foam::PackedList<nBits>::capacity() const
{ {
return packing() * List<PackedStorage>::size(); return packing() * StorageList::size();
} }
template<int nBits> template<int nBits>
inline void Foam::PackedList<nBits>::setCapacity(const label nElem) inline void Foam::PackedList<nBits>::setCapacity(const label nElem)
{ {
List<PackedStorage>::setSize(packedLength(nElem), 0u); StorageList::setSize(packedLength(nElem), 0u);
// truncate addressed size too? // truncate addressed size too?
if (size_ > nElem) if (size_ > nElem)
@ -497,9 +517,9 @@ inline void Foam::PackedList<nBits>::reserve
label len = packedLength(nElem); label len = packedLength(nElem);
// need more capacity? // need more capacity?
if (len > List<PackedStorage>::size()) if (len > StorageList::size())
{ {
List<PackedStorage>::setSize(len, 0); StorageList::setSize(len, 0u);
} }
} }
@ -514,7 +534,7 @@ inline void Foam::PackedList<nBits>::clear()
template<int nBits> template<int nBits>
inline void Foam::PackedList<nBits>::clearStorage() inline void Foam::PackedList<nBits>::clearStorage()
{ {
List<PackedStorage>::clear(); StorageList::clear();
size_ = 0; size_ = 0;
} }
@ -525,9 +545,9 @@ inline void Foam::PackedList<nBits>::shrink()
label len = packedLength(size_); label len = packedLength(size_);
// we have unused space? // we have unused space?
if (len < List<PackedStorage>::size()) if (len < StorageList::size())
{ {
List<PackedStorage>::setSize(len); StorageList::setSize(len);
} }
} }
@ -535,7 +555,7 @@ template<int nBits>
inline const Foam::List<unsigned int>& inline const Foam::List<unsigned int>&
Foam::PackedList<nBits>::storage() const Foam::PackedList<nBits>::storage() const
{ {
return static_cast<const List<PackedStorage>&>(*this); return static_cast<const StorageList&>(*this);
} }
@ -545,7 +565,7 @@ inline void Foam::PackedList<nBits>::transfer(PackedList<nBits>& lst)
size_ = lst.size_; size_ = lst.size_;
lst.size_ = 0; lst.size_ = 0;
List<PackedStorage>::transfer(lst); StorageList::transfer(lst);
} }
@ -564,14 +584,14 @@ inline unsigned int Foam::PackedList<nBits>::get(const label i) const
checkIndex(i); checkIndex(i);
# endif # endif
return const_iterator(*this, i).get(); return const_iterator(this, i).get();
} }
template<int nBits> template<int nBits>
inline unsigned int Foam::PackedList<nBits>::operator[](const label i) const inline unsigned int Foam::PackedList<nBits>::operator[](const label i) const
{ {
return const_iterator(*this, i).get(); return const_iterator(this, i).get();
} }
@ -595,7 +615,7 @@ inline bool Foam::PackedList<nBits>::set
} }
# endif # endif
return iterator(*this, i).set(val); return iterator(this, i).set(val);
} }
@ -606,16 +626,14 @@ inline void Foam::PackedList<nBits>::append(const unsigned int val)
reserve(elemI + 1); reserve(elemI + 1);
size_++; size_++;
iterator(*this, elemI) = val; iterator(this, elemI).set(val);
} }
template<int nBits> template<int nBits>
inline unsigned int Foam::PackedList<nBits>::remove() inline unsigned int Foam::PackedList<nBits>::remove()
{ {
label elemI = size_ - 1; if (!size_)
if (elemI < 0)
{ {
FatalErrorIn FatalErrorIn
( (
@ -623,9 +641,8 @@ inline unsigned int Foam::PackedList<nBits>::remove()
) << "List is empty" << abort(FatalError); ) << "List is empty" << abort(FatalError);
} }
label elemI = size_ - 1;
const unsigned int val = const_iterator(*this, elemI).get(); const unsigned int val = const_iterator(this, elemI).get();
resize(elemI); resize(elemI);
return val; return val;
@ -641,29 +658,42 @@ Foam::PackedList<nBits>::operator[](const label i)
resize(i + 1); resize(i + 1);
} }
return iterator(*this, i); return iterator(this, i);
} }
// specialization for nBits=1 isn't worth the bother
template<int nBits> template<int nBits>
inline void Foam::PackedList<nBits>::operator=(const unsigned int val) inline void Foam::PackedList<nBits>::operator=(const unsigned int val)
{ {
if (val) if (val)
{ {
// specialization for nBits=1 isn't worth the bother unsigned int fill = val;
unsigned int fill = val & max_value(); if (fill & ~max_value())
{
# ifdef DEBUGList
FatalErrorIn("PackedList<T>::operator=(const unsigned int)")
<< "value " << label(val)
<< " out-of-range 0 ... " << label(max_value())
<< " representable by " << nBits << " bits"
<< abort(FatalError);
# endif
// treat overflow as max_value
fill = max_value();
}
for (unsigned int i = 1; i < packing(); ++i) for (unsigned int i = 1; i < packing(); ++i)
{ {
fill |= (fill << nBits); fill |= (fill << nBits);
} }
List<PackedStorage>::operator=(fill); StorageList::operator=(fill);
} }
else else
{ {
List<PackedStorage>::operator=(0u); StorageList::operator=(0u);
} }
} }