PackedList - activated lazy evaluation

- moving back to original flat addressing in iterators means there is no
  performance issue with using lazy evaluation
- set() method now has ~0 for a default value.
  We can thus simply write 'set(i) to trun on all of the bits.
  This means we can use it just like labelHashSet::set(i)
- added flip() method for inverting bits. I don't know where we might need
  it, but the STL has it so we might as well too.
This commit is contained in:
Mark Olesen
2009-01-30 00:07:53 +01:00
parent f0f677e3d6
commit 1f6733d91d
4 changed files with 229 additions and 273 deletions

View File

@ -52,13 +52,25 @@ int main(int argc, char *argv[])
list1 = -1; list1 = -1;
list1.print(Info); list1.print(Info);
Info<< "\ntest zero\n";
list1 = 0;
list1.print(Info);
Info<< "\ntest set() with default argument (max_value)\n";
list1.set(3);
list1.print(Info);
Info<< "\ntest assign between references\n"; Info<< "\ntest assign between references\n";
list1[2] = 3; list1[2] = 3;
list1[4] = list1[2]; list1[4] = list1[2];
list1.print(Info); list1.print(Info);
Info<< "\ntest assign between references, with chaining\n"; Info<< "\ntest assign between references, with chaining\n";
list1[4] = list1[2] = 1; list1[0] = list1[4] = 1;
list1.print(Info);
Info<< "\ntest assign between references, with chaining and auto-vivify\n";
list1[1] = list1[8] = list1[10] = list1[14] = 2;
list1.print(Info); list1.print(Info);
{ {
@ -91,6 +103,14 @@ int main(int argc, char *argv[])
list1.resize(8, list1.max_value()); list1.resize(8, list1.max_value());
list1.print(Info); list1.print(Info);
Info<< "\ntest flip() function\n";
list1.flip();
list1.print(Info);
Info<< "\nre-flip()\n";
list1.flip();
list1.print(Info);
Info<< "\ntest set() function\n"; Info<< "\ntest set() function\n";
list1.set(1, 5); list1.set(1, 5);
list1.print(Info); list1.print(Info);
@ -188,15 +208,23 @@ int main(int argc, char *argv[])
{ {
Info<< "\ntest assignment of iterator\n"; Info<< "\ntest assignment of iterator\n";
list1.print(Info); list1.print(Info);
PackedList<3>::iterator cit = list1[25]; Info<< "cend()\n";
cit.print(Info);
list1.end().print(Info); list1.end().print(Info);
PackedList<3>::iterator cit = list1[100];
Info<< "out-of-range: ";
cit.print(Info);
cit = list1[15];
Info<< "in-range: ";
cit.print(Info);
Info<< "out-of-range: ";
cit = list1[1000];
cit.print(Info);
} }
for for
( (
PackedList<3>::iterator cit = list1[5]; PackedList<3>::iterator cit = list1[30];
cit != list1.end(); cit != list1.end();
++cit ++cit
) )
@ -204,14 +232,19 @@ int main(int argc, char *argv[])
cit.print(Info); cit.print(Info);
} }
// Info<< "\ntest operator[] auto-vivify\n"; Info<< "\ntest operator[] auto-vivify\n";
// const unsigned int val = list1[45]; Info<< "size:" << list1.size() << "\n";
//
// Info<< "list[45]:" << val << "\n"; const unsigned int val = list1[45];
// list1[45] = list1.max_value();
// Info<< "list[45]:" << list1[45] << "\n"; Info<< "list[45]:" << val << "\n";
// list1[49] = list1.max_value(); Info<< "size after read:" << list1.size() << "\n";
// list1.print(Info);
list1[45] = list1.max_value();
Info<< "size after write:" << list1.size() << "\n";
Info<< "list[45]:" << list1[45] << "\n";
list1[49] = list1[100];
list1.print(Info);
Info<< "\ntest copy constructor + append\n"; Info<< "\ntest copy constructor + append\n";

View File

@ -83,25 +83,25 @@ unsigned int Foam::PackedList<nBits>::count() const
if (size_) if (size_)
{ {
// mask value for complete chunks // mask value for complete segments
unsigned int mask = maskLower(packing()); unsigned int mask = maskLower(packing());
unsigned int endIdx = size_ / packing(); const unsigned int endSeg = size_ / packing();
unsigned int endOff = size_ % packing(); const unsigned int endOff = size_ % packing();
// count bits in complete elements // count bits in complete segments
for (unsigned i = 0; i < endIdx; ++i) for (unsigned i = 0; i < endSeg; ++i)
{ {
register unsigned int bits = StorageList::operator[](i) & mask; register unsigned int bits = StorageList::operator[](i) & mask;
COUNT_PACKEDBITS(c, bits); COUNT_PACKEDBITS(c, bits);
} }
// count bits in partial chunk // count bits in partial segment
if (endOff) if (endOff)
{ {
mask = maskLower(endOff); mask = maskLower(endOff);
register unsigned int bits = StorageList::operator[](endIdx) & mask; register unsigned int bits = StorageList::operator[](endSeg) & mask;
COUNT_PACKEDBITS(c, bits); COUNT_PACKEDBITS(c, bits);
} }
} }
@ -118,7 +118,7 @@ bool Foam::PackedList<nBits>::trim()
return false; return false;
} }
// mask value for complete chunks // mask value for complete segments
unsigned int mask = maskLower(packing()); unsigned int mask = maskLower(packing());
label currElem = packedLength(size_) - 1; label currElem = packedLength(size_) - 1;
@ -130,7 +130,7 @@ bool Foam::PackedList<nBits>::trim()
StorageList::operator[](currElem) &= maskLower(endOff); StorageList::operator[](currElem) &= maskLower(endOff);
} }
// test entire chunk // test entire segment
while (currElem > 0 && !(StorageList::operator[](currElem) &= mask)) while (currElem > 0 && !(StorageList::operator[](currElem) &= mask))
{ {
currElem--; currElem--;
@ -162,10 +162,22 @@ bool Foam::PackedList<nBits>::trim()
} }
template<unsigned nBits>
void Foam::PackedList<nBits>::flip()
{
label packLen = packedLength(size_);
for (label i=0; i < packLen; i++)
{
StorageList::operator[](i) = ~StorageList::operator[](i);
}
}
template<unsigned nBits> template<unsigned nBits>
Foam::labelList Foam::PackedList<nBits>::values() const Foam::labelList Foam::PackedList<nBits>::values() const
{ {
labelList elems(size()); labelList elems(size_);
forAll(*this, i) forAll(*this, i)
{ {
@ -179,9 +191,10 @@ template<unsigned nBits>
Foam::Ostream& Foam::PackedList<nBits>::iteratorBase::print(Ostream& os) const Foam::Ostream& Foam::PackedList<nBits>::iteratorBase::print(Ostream& os) const
{ {
os << "iterator<" << label(nBits) << "> [" os << "iterator<" << label(nBits) << "> ["
<< (index_ * packing() + offset_) << "]" << this->index_ << "]"
<< " index:" << index_ << " offset:" << offset_ << " segment:" << label(this->index_ / packing())
<< " value:" << unsigned(*this) << " offset:" << label(this->index_ % packing())
<< " value:" << this->get()
<< nl; << nl;
return os; return os;
@ -194,7 +207,7 @@ Foam::Ostream& Foam::PackedList<nBits>::print(Ostream& os) const
os << "PackedList<" << label(nBits) << ">" os << "PackedList<" << label(nBits) << ">"
<< " max_value:" << max_value() << " max_value:" << max_value()
<< " packing:" << packing() << nl << " packing:" << packing() << nl
<< "values: " << size() << "/" << capacity() << "( "; << "values: " << size_ << "/" << capacity() << "( ";
forAll(*this, i) forAll(*this, i)
{ {
os << get(i) << ' '; os << get(i) << ' ';
@ -205,17 +218,17 @@ Foam::Ostream& Foam::PackedList<nBits>::print(Ostream& os) const
os << ")\n" os << ")\n"
<< "storage: " << packLen << "/" << StorageList::size() << "( "; << "storage: " << packLen << "/" << StorageList::size() << "( ";
// mask value for complete chunks // mask value for complete segments
unsigned int mask = maskLower(packing()); unsigned int mask = maskLower(packing());
for (label i=0; i < packLen; i++) for (label i=0; i < packLen; i++)
{ {
const StorageType& rawBits = StorageList::operator[](i); const StorageType& rawBits = StorageList::operator[](i);
// the final storage may not be full, modify mask accordingly // the final segment may not be full, modify mask accordingly
if (i+1 == packLen) if (i+1 == packLen)
{ {
unsigned endOff = size_ % packing(); unsigned int endOff = size_ % packing();
if (endOff) if (endOff)
{ {
@ -229,7 +242,7 @@ Foam::Ostream& Foam::PackedList<nBits>::print(Ostream& os) const
for (unsigned int testBit = (1 << max_bits()); testBit; testBit >>= 1) for (unsigned int testBit = (1 << max_bits()); testBit; testBit >>= 1)
{ {
if (testBit & mask) if (mask & testBit)
{ {
if (rawBits & testBit) if (rawBits & testBit)
{ {

View File

@ -44,9 +44,9 @@ Note
Using the iteratorBase as a proxy allows assignment of values Using the iteratorBase as a proxy allows assignment of values
between list elements. Thus the following bit of code works as expected: between list elements. Thus the following bit of code works as expected:
@code @code
blist[1] = blist[5]; // value assignment, not iterator position list[1] = list[5]; // value assignment, not iterator position
blist[2] = blist[5] = 4; // propagates value list[2] = list[5] = 4; // propagates value
blist[1] = blist[5] = blist[6]; // propagates value list[1] = list[5] = list[6]; // propagates value
@endcode @endcode
Using get() or the '[]' operator are similarly fast. Looping and reading Using get() or the '[]' operator are similarly fast. Looping and reading
@ -58,11 +58,21 @@ Note
useful for branching on changed values. useful for branching on changed values.
@code @code
blist[5] = 4; list[5] = 4;
changed = blist.set(5, 8); changed = list.set(5, 8);
if (changed) ... if (changed) ...
@endcode @endcode
The lazy evaluation used means that reading an out-of-range element
returns zero, but does not affect the list size. Even in a non-const
context, only the assigment causes the element to be created.
For example,
@code
list.resize(4);
Info<< list[10] << "\n"; // print zero, but doesn't adjust list
list[8] = 1;
@endcode
SeeAlso SeeAlso
Foam::DynamicList Foam::DynamicList
@ -120,9 +130,6 @@ class PackedList
//- Calculate the list length when packed //- Calculate the list length when packed
inline static label packedLength(const label); inline static label packedLength(const label);
//- Check index I is within valid range [ 0 .. max_value() ]
inline void checkIndex(const label) const;
public: public:
// Public data // Public data
@ -172,22 +179,23 @@ public:
// Access // Access
//- The number of elements that can be stored before resizing //- The number of elements that can be stored before reallocating
inline label capacity() const; inline label capacity() const;
//- Number of entries. //- Number of entries.
inline label size() const; inline label size() const;
//- Return true if the list is empty (i.e., if size() == 0). //- Return true if the list is empty (i.e., size() == 0).
inline bool empty() const; inline bool empty() const;
//- Get value at index I. //- Get value at index I.
// Does not auto-vivify entries. // Never auto-vivify entries.
inline unsigned int get(const label) const; inline unsigned int get(const label) const;
//- Set value at index I. Return true if value changed. //- Set value at index I. Return true if value changed.
// Does not auto-vivify entries. // Does auto-vivify for non-existent entries.
inline bool set(const label, const unsigned int val); // Default value set is the max_value.
inline bool set(const label, const unsigned int val = ~0u);
//- Return the underlying packed storage //- Return the underlying packed storage
inline List<unsigned int>& storage(); inline List<unsigned int>& storage();
@ -200,9 +208,6 @@ public:
// http://en.wikipedia.org/wiki/Hamming_weight // http://en.wikipedia.org/wiki/Hamming_weight
unsigned int count() const; unsigned int count() const;
//- Trim any trailing zero elements
bool trim();
//- Return the values as a labelList //- Return the values as a labelList
labelList values() const; labelList values() const;
@ -211,6 +216,12 @@ public:
// Edit // Edit
//- Trim any trailing zero elements
bool trim();
//- Invert the bits in the addressable region.
void flip();
//- Alter the size of the underlying storage. //- Alter the size of the underlying storage.
// The addressed size will be truncated if needed to fit, but will // The addressed size will be truncated if needed to fit, but will
// remain otherwise untouched. // remain otherwise untouched.
@ -255,12 +266,12 @@ public:
inline unsigned int remove(); inline unsigned int remove();
//- Get value at index I //- Get value at index I
// Does not auto-vivify entries. // Never auto-vivify entries.
inline unsigned int operator[](const label) const; inline unsigned int operator[](const label) const;
//- Set value at index I. //- Set value at index I.
// Returns iterator to perform the actual operation. // Returns iterator to perform the actual operation.
// Does not auto-vivify entries. // Does not auto-vivify entries, but will when assigned to.
inline iteratorBase operator[](const label); inline iteratorBase operator[](const label);
//- Assignment of all entries to the given value. Takes linear time. //- Assignment of all entries to the given value. Takes linear time.
@ -294,52 +305,27 @@ public:
// This also lets us use the default bitwise copy/assignment // This also lets us use the default bitwise copy/assignment
PackedList* list_; PackedList* list_;
//- Element index within storage //- Element index
unsigned index_; label index_;
//- Offset within storage element
unsigned offset_;
// Protected Member Functions // Protected Member Functions
//- Get value as unsigned //- Get value as unsigned, no range-checking
inline unsigned int get() const; inline unsigned int get() const;
//- Set value, returning true if changed //- Set value, returning true if changed, no range-checking
inline bool set(unsigned int); inline bool set(unsigned int);
//- Increment to new position
inline void incr();
//- Decrement to new position
inline void decr();
//- Move to new position, but not beyond end()
inline void seek(const iteratorBase&);
// Constructors // Constructors
//- Construct null //- Construct null
inline iteratorBase(); inline iteratorBase();
//- Copy construct
inline iteratorBase(const iteratorBase&);
//- Construct from base list and position index //- Construct from base list and position index
inline iteratorBase(const PackedList*, const label); inline iteratorBase(const PackedList*, const label);
public: public:
// Member Functions
//- Return true if the element is within addressable range
inline bool valid() const;
//- Move iterator to end() if it would otherwise be out-of-range
// Returns true if the element was already ok
inline bool validate();
// Member Operators // Member Operators
//- Compare positions //- Compare positions
@ -350,10 +336,12 @@ public:
// This allows packed[0] = packed[3] for assigning values // This allows packed[0] = packed[3] for assigning values
inline unsigned int operator=(const iteratorBase&); inline unsigned int operator=(const iteratorBase&);
//- Assign value //- Assign value.
// A non-existent entry will be auto-vivified.
inline unsigned int operator=(const unsigned int val); inline unsigned int operator=(const unsigned int val);
//- Conversion operator //- Conversion operator
// Never auto-vivify entries.
inline operator unsigned int () const; inline operator unsigned int () const;
//- Print value and information //- Print value and information
@ -378,6 +366,8 @@ public:
inline iterator(); inline iterator();
//- Construct from iterator base, eg iter(packedlist[i]) //- Construct from iterator base, eg iter(packedlist[i])
// but also "iterator iter = packedlist[i];"
// An out-of-range iterator is assigned end()
inline iterator(const iteratorBase&); inline iterator(const iteratorBase&);
//- Construct from base list and position index //- Construct from base list and position index
@ -386,6 +376,7 @@ public:
// Member Operators // Member Operators
//- Assign from iteratorBase, eg iter = packedlist[i] //- Assign from iteratorBase, eg iter = packedlist[i]
// An out-of-range iterator is assigned end()
inline iterator& operator=(const iteratorBase&); inline iterator& operator=(const iteratorBase&);
//- Return value //- Return value
@ -427,7 +418,9 @@ public:
//- Construct null //- Construct null
inline const_iterator(); inline const_iterator();
//- Construct from iterator base //- Construct from iterator base, eg iter(packedlist[i])
// but also "const_iterator iter = packedlist[i];"
// An out-of-range iterator is assigned end()
inline const_iterator(const iteratorBase&); inline const_iterator(const iteratorBase&);
//- Construct from base list and position index //- Construct from base list and position index
@ -439,7 +432,7 @@ public:
// Member operators // Member operators
//- Assign from iteratorBase or derived //- Assign from iteratorBase or derived
// eg, iter = packedlist[i] or iter = [non-const]list.begin() // eg, iter = packedlist[i] or even iter = list.begin()
inline const_iterator& operator=(const iteratorBase&); inline const_iterator& operator=(const iteratorBase&);
//- Return referenced value directly //- Return referenced value directly

View File

@ -65,24 +65,6 @@ inline Foam::label Foam::PackedList<nBits>::packedLength(const label nElem)
} }
template<unsigned nBits>
inline void Foam::PackedList<nBits>::checkIndex(const label i) const
{
if (!size_)
{
FatalErrorIn("PackedList<nBits>::checkIndex(const label)")
<< "attempt to access element from zero-sized list"
<< abort(FatalError);
}
else if (i < 0 || i >= size_)
{
FatalErrorIn("PackedList<nBits>::checkIndex(const label)")
<< "index " << i << " out of range 0 ... " << size_-1
<< abort(FatalError);
}
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
template<unsigned nBits> template<unsigned nBits>
@ -105,7 +87,7 @@ template<unsigned nBits>
inline Foam::PackedList<nBits>::PackedList(const PackedList<nBits>& lst) inline Foam::PackedList<nBits>::PackedList(const PackedList<nBits>& lst)
: :
StorageList(lst), StorageList(lst),
size_(lst.size()) size_(lst.size_)
{} {}
@ -132,20 +114,7 @@ template<unsigned nBits>
inline Foam::PackedList<nBits>::iteratorBase::iteratorBase() inline Foam::PackedList<nBits>::iteratorBase::iteratorBase()
: :
list_(0), list_(0),
index_(0), index_(0)
offset_(0)
{}
template<unsigned nBits>
inline Foam::PackedList<nBits>::iteratorBase::iteratorBase
(
const iteratorBase& iter
)
:
list_(iter.list_),
index_(iter.index_),
offset_(iter.offset_)
{} {}
@ -157,8 +126,7 @@ inline Foam::PackedList<nBits>::iteratorBase::iteratorBase
) )
: :
list_(const_cast<PackedList<nBits>*>(lst)), list_(const_cast<PackedList<nBits>*>(lst)),
index_(i / packing()), index_(i)
offset_(i % packing())
{} {}
@ -166,8 +134,11 @@ template<unsigned nBits>
inline unsigned int inline unsigned int
Foam::PackedList<nBits>::iteratorBase::get() const Foam::PackedList<nBits>::iteratorBase::get() const
{ {
const unsigned int& stored = list_->StorageList::operator[](index_); const unsigned int seg = index_ / packing();
return (stored >> (nBits * offset_)) & max_value(); const unsigned int off = index_ % packing();
const unsigned int& stored = list_->StorageList::operator[](seg);
return (stored >> (nBits * off)) & max_value();
} }
@ -175,114 +146,37 @@ template<unsigned nBits>
inline bool inline bool
Foam::PackedList<nBits>::iteratorBase::set(const unsigned int val) Foam::PackedList<nBits>::iteratorBase::set(const unsigned int val)
{ {
unsigned int& stored = list_->StorageList::operator[](index_); const unsigned int seg = index_ / packing();
const unsigned int off = index_ % packing();
unsigned int& stored = list_->StorageList::operator[](seg);
const unsigned int prev = stored; const unsigned int prev = stored;
const unsigned int startBit = nBits * offset_; const unsigned int startBit = nBits * off;
const unsigned int maskNew = max_value() << startBit; const unsigned int maskNew = max_value() << startBit;
if (val & ~max_value()) if (val & ~max_value())
{ {
# ifdef DEBUGList // overflow is max_value, fill everything
FatalErrorIn("PackedList<T>::iteratorBase::set(const unsigned int)")
<< "value " << label(val)
w << " out-of-range 0 ... " << label(max_value())
<< " representable by " << nBits << " bits"
<< abort(FatalError);
# endif
// treat overflow as max_value
stored |= maskNew; stored |= maskNew;
} }
else else
{ {
stored = (stored & ~maskNew) | (maskNew & (val << startBit)); stored &= ~maskNew;
stored |= maskNew & (val << startBit);
} }
return prev != stored; return prev != stored;
} }
template<unsigned nBits>
inline void
Foam::PackedList<nBits>::iteratorBase::incr()
{
offset_++;
if (offset_ >= packing())
{
offset_ = 0;
index_++;
}
}
template<unsigned nBits>
inline void
Foam::PackedList<nBits>::iteratorBase::decr()
{
if (!offset_)
{
offset_ = packing();
index_--;
}
offset_--;
}
template<unsigned nBits>
inline void
Foam::PackedList<nBits>::iteratorBase::seek
(
const iteratorBase& iter
)
{
list_ = iter.list_;
index_ = iter.index_;
offset_ = iter.offset_;
this->validate();
}
template<unsigned nBits>
inline bool
Foam::PackedList<nBits>::iteratorBase::valid() const
{
label elemI = offset_ + index_ * packing();
return (elemI < list_->size_);
}
template<unsigned nBits>
inline bool
Foam::PackedList<nBits>::iteratorBase::validate()
{
// avoid going past end()
unsigned endIdx = list_->size_ / packing();
unsigned endOff = list_->size_ % packing();
if (index_ > endIdx || (index_ == endIdx && offset_ > endOff))
{
index_ = endIdx;
offset_ = endOff;
return false;
}
else
{
return true;
}
}
template<unsigned nBits> template<unsigned nBits>
inline bool Foam::PackedList<nBits>::iteratorBase::operator== inline bool Foam::PackedList<nBits>::iteratorBase::operator==
( (
const iteratorBase& iter const iteratorBase& iter
) const ) const
{ {
return this->index_ == iter.index_ && this->offset_ == iter.offset_; return this->index_ == iter.index_;
} }
@ -292,7 +186,7 @@ inline bool Foam::PackedList<nBits>::iteratorBase::operator!=
const iteratorBase& iter const iteratorBase& iter
) const ) const
{ {
return this->index_ != iter.index_ || this->offset_ != iter.offset_; return this->index_ != iter.index_;
} }
@ -310,14 +204,11 @@ template<unsigned nBits>
inline unsigned int inline unsigned int
Foam::PackedList<nBits>::iteratorBase::operator=(const unsigned int val) Foam::PackedList<nBits>::iteratorBase::operator=(const unsigned int val)
{ {
# ifdef DEBUGList // lazy evaluation - increase size on assigment
// lazy evaluation would be nice to keep, but really slows things down if (index_ >= list_->size_)
label minsize = 1 + offset_ + index_ * packing();
if (minsize > list_->size_)
{ {
list_->resize(minsize); list_->resize(index_ + 1);
} }
#endif
this->set(val); this->set(val);
return val; return val;
@ -328,14 +219,11 @@ template<unsigned nBits>
inline Foam::PackedList<nBits>::iteratorBase::operator inline Foam::PackedList<nBits>::iteratorBase::operator
unsigned int () const unsigned int () const
{ {
# ifdef DEBUGList // lazy evaluation - return 0 for out-of-range
// lazy evaluation would be nice to keep, but really slows things down if (index_ >= list_->size_)
label minsize = 1 + offset_ + index_ * packing();
if (minsize > list_->size_)
{ {
return 0; return 0;
} }
#endif
return this->get(); return this->get();
} }
@ -365,7 +253,12 @@ inline Foam::PackedList<nBits>::iterator::iterator
: :
iteratorBase(iter) iteratorBase(iter)
{ {
this->validate(); // avoid going past end()
// eg, iter = iterator(list, Inf)
if (this->index_ > this->list_->size_)
{
this->index_ = this->list_->size_;
}
} }
@ -377,7 +270,12 @@ inline Foam::PackedList<nBits>::const_iterator::const_iterator
: :
iteratorBase(iter) iteratorBase(iter)
{ {
this->validate(); // avoid going past end()
// eg, iter = iterator(list, Inf)
if (this->index_ > this->list_->size_)
{
this->index_ = this->list_->size_;
}
} }
@ -417,7 +315,16 @@ template<unsigned nBits>
inline typename Foam::PackedList<nBits>::iterator& inline typename Foam::PackedList<nBits>::iterator&
Foam::PackedList<nBits>::iterator::operator=(const iteratorBase& iter) Foam::PackedList<nBits>::iterator::operator=(const iteratorBase& iter)
{ {
this->seek(iter); this->list_ = iter.list_;
this->index_ = iter.index_;
// avoid going past end()
// eg, iter = iterator(list, Inf)
if (this->index_ > this->list_->size_)
{
this->index_ = this->list_->size_;
}
return *this; return *this;
} }
@ -426,7 +333,16 @@ template<unsigned nBits>
inline typename Foam::PackedList<nBits>::const_iterator& inline typename Foam::PackedList<nBits>::const_iterator&
Foam::PackedList<nBits>::const_iterator::operator=(const iteratorBase& iter) Foam::PackedList<nBits>::const_iterator::operator=(const iteratorBase& iter)
{ {
this->seek(iter); this->list_ = iter.list_;
this->index_ = iter.index_;
// avoid going past end()
// eg, iter = iterator(list, Inf)
if (this->index_ > this->list_->size_)
{
this->index_ = this->list_->size_;
}
return *this; return *this;
} }
@ -435,7 +351,7 @@ template<unsigned nBits>
inline typename Foam::PackedList<nBits>::iterator& inline typename Foam::PackedList<nBits>::iterator&
Foam::PackedList<nBits>::iterator::operator++() Foam::PackedList<nBits>::iterator::operator++()
{ {
this->incr(); ++this->index_;
return *this; return *this;
} }
@ -444,7 +360,7 @@ template<unsigned nBits>
inline typename Foam::PackedList<nBits>::const_iterator& inline typename Foam::PackedList<nBits>::const_iterator&
Foam::PackedList<nBits>::const_iterator::operator++() Foam::PackedList<nBits>::const_iterator::operator++()
{ {
this->incr(); ++this->index_;
return *this; return *this;
} }
@ -454,7 +370,7 @@ inline typename Foam::PackedList<nBits>::iterator
Foam::PackedList<nBits>::iterator::operator++(int) Foam::PackedList<nBits>::iterator::operator++(int)
{ {
iterator old = *this; iterator old = *this;
this->incr(); ++this->index_;
return old; return old;
} }
@ -464,7 +380,7 @@ inline typename Foam::PackedList<nBits>::const_iterator
Foam::PackedList<nBits>::const_iterator::operator++(int) Foam::PackedList<nBits>::const_iterator::operator++(int)
{ {
const_iterator old = *this; const_iterator old = *this;
this->incr(); ++this->index_;
return old; return old;
} }
@ -473,7 +389,7 @@ template<unsigned nBits>
inline typename Foam::PackedList<nBits>::iterator& inline typename Foam::PackedList<nBits>::iterator&
Foam::PackedList<nBits>::iterator::operator--() Foam::PackedList<nBits>::iterator::operator--()
{ {
this->decr(); --this->index_;
return *this; return *this;
} }
@ -482,7 +398,7 @@ template<unsigned nBits>
inline typename Foam::PackedList<nBits>::const_iterator& inline typename Foam::PackedList<nBits>::const_iterator&
Foam::PackedList<nBits>::const_iterator::operator--() Foam::PackedList<nBits>::const_iterator::operator--()
{ {
this->decr(); --this->index_;
return *this; return *this;
} }
@ -492,7 +408,7 @@ inline typename Foam::PackedList<nBits>::iterator
Foam::PackedList<nBits>::iterator::operator--(int) Foam::PackedList<nBits>::iterator::operator--(int)
{ {
iterator old = *this; iterator old = *this;
this->decr(); --this->index_;
return old; return old;
} }
@ -502,7 +418,7 @@ inline typename Foam::PackedList<nBits>::const_iterator
Foam::PackedList<nBits>::const_iterator::operator--(int) Foam::PackedList<nBits>::const_iterator::operator--(int)
{ {
const_iterator old = *this; const_iterator old = *this;
this->decr(); --this->index_;
return old; return old;
} }
@ -567,7 +483,7 @@ template<unsigned nBits>
inline typename Foam::PackedList<nBits>::iterator inline typename Foam::PackedList<nBits>::iterator
Foam::PackedList<nBits>::end() Foam::PackedList<nBits>::end()
{ {
return iterator(this, this->size()); return iterator(this, size_);
} }
@ -575,7 +491,7 @@ template<unsigned 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 const_iterator(this, this->size()); return const_iterator(this, size_);
} }
@ -583,7 +499,7 @@ template<unsigned 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 const_iterator(this, this->size()); return const_iterator(this, size_);
} }
@ -617,20 +533,12 @@ inline void Foam::PackedList<nBits>::resize
// fill new elements or newly exposed elements // fill new elements or newly exposed elements
if (size_) if (size_)
{ {
// fill value for complete chunks // fill value for complete segments
unsigned int fill = val; unsigned int fill = val;
if (fill & ~max_value()) if (fill & ~max_value())
{ {
# ifdef DEBUGList // overflow is max_value, fill everything
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 everything
fill = ~0; fill = ~0;
} }
else else
@ -641,26 +549,26 @@ inline void Foam::PackedList<nBits>::resize
} }
} }
unsigned begIdx = size_ / packing(); unsigned int seg = size_ / packing();
unsigned begOff = size_ % packing(); unsigned int off = size_ % packing();
unsigned endIdx = nElem / packing();
// partial chunk, preserve existing value // partial segment, preserve existing value
if (begOff) if (off)
{ {
unsigned int maskOld = maskLower(begOff); unsigned int maskOld = maskLower(off);
StorageList::operator[](begIdx) &= maskOld; StorageList::operator[](seg) &= maskOld;
StorageList::operator[](begIdx) |= ~maskOld & fill; StorageList::operator[](seg) |= ~maskOld & fill;
// continue with the next chunk // continue with the next segment
begIdx++; seg++;
} }
unsigned int endSeg = nElem / packing();
// fill in complete elements // fill in complete elements
while (begIdx < endIdx) while (seg < endSeg)
{ {
StorageList::operator[](begIdx++) = fill; StorageList::operator[](seg++) = fill;
} }
} }
else else
@ -786,17 +694,31 @@ Foam::PackedList<nBits>::xfer()
template<unsigned nBits> template<unsigned nBits>
inline unsigned int Foam::PackedList<nBits>::get(const label i) const inline unsigned int Foam::PackedList<nBits>::get(const label i) const
{ {
# ifdef DEBUGList # ifdef FULLDEBUG
checkIndex(i); if (i < 0)
{
FatalErrorIn("PackedList<nBits>::get(const label)")
<< "negative index " << i << " max=" << size_-1
<< abort(FatalError);
}
# endif # endif
// lazy evaluation - return 0 for out-of-range
if (i < size_)
{
return iteratorBase(this, i).get(); return iteratorBase(this, i).get();
}
else
{
return 0;
}
} }
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
if (i < size_) if (i < size_)
{ {
return iteratorBase(this, i).get(); return iteratorBase(this, i).get();
@ -815,18 +737,21 @@ inline bool Foam::PackedList<nBits>::set
const unsigned int val const unsigned int val
) )
{ {
# ifdef DEBUGList # ifdef FULLDEBUG
checkIndex(i); if (i < 0)
if (val & ~max_value())
{ {
FatalErrorIn("PackedList<T>::set(const label, const unsigned int)") FatalErrorIn("PackedList<nBits>::set(const label)")
<< "value " << label(val) << "negative index " << i << " max=" << size_-1
<< " out-of-range 0 ... " << label(max_value())
<< " representable by " << nBits << " bits"
<< abort(FatalError); << abort(FatalError);
} }
# endif #endif
// lazy evaluation - increase size on assigment
if (i >= size_)
{
resize(i + 1);
}
return iteratorBase(this, i).set(val); return iteratorBase(this, i).set(val);
} }
@ -879,14 +804,6 @@ inline void Foam::PackedList<nBits>::operator=(const unsigned int val)
if (fill & ~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 // treat overflow as max_value
fill = ~0; fill = ~0;
} }